blob: 6e3ddc9094ea9fd97671a76bbda11f2cc676cbb2 [file] [log] [blame]
Avichal Rakesh362242f2022-02-08 12:40:53 -08001/*
2 * Copyright (C) 2022 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 */
Rucha Katakward08a0152023-10-13 15:47:58 -070016#include <gtest/gtest.h>
Avichal Rakesh362242f2022-02-08 12:40:53 -080017
18#include <aidl/Vintf.h>
19#include <aidl/android/hardware/camera/common/VendorTagSection.h>
20#include <aidl/android/hardware/camera/device/ICameraDevice.h>
21#include <aidlcommonsupport/NativeHandle.h>
22#include <camera_aidl_test.h>
23#include <cutils/properties.h>
24#include <device_cb.h>
25#include <empty_device_cb.h>
26#include <grallocusage/GrallocUsageConversion.h>
27#include <gtest/gtest.h>
28#include <hardware/gralloc.h>
29#include <hardware/gralloc1.h>
30#include <hidl/GtestPrinter.h>
31#include <hidl/HidlSupport.h>
32#include <torch_provider_cb.h>
Rucha Katakward08a0152023-10-13 15:47:58 -070033#include <com_android_internal_camera_flags.h>
Avichal Rakesh362242f2022-02-08 12:40:53 -080034#include <list>
35
36using ::aidl::android::hardware::camera::common::CameraDeviceStatus;
37using ::aidl::android::hardware::camera::common::CameraResourceCost;
38using ::aidl::android::hardware::camera::common::TorchModeStatus;
39using ::aidl::android::hardware::camera::common::VendorTagSection;
40using ::aidl::android::hardware::camera::device::ICameraDevice;
Austin Borger4728fc42022-07-15 11:27:53 -070041using ::aidl::android::hardware::camera::metadata::RequestAvailableColorSpaceProfilesMap;
Avichal Rakeshd3503a32022-02-25 06:23:14 +000042using ::aidl::android::hardware::camera::metadata::RequestAvailableDynamicRangeProfilesMap;
Avichal Rakesh362242f2022-02-08 12:40:53 -080043using ::aidl::android::hardware::camera::metadata::SensorPixelMode;
44using ::aidl::android::hardware::camera::provider::CameraIdAndStreamCombination;
Avichal Rakesh4bf91c72022-05-23 20:44:02 +000045using ::aidl::android::hardware::camera::provider::BnCameraProviderCallback;
Avichal Rakesh362242f2022-02-08 12:40:53 -080046
47using ::ndk::ScopedAStatus;
48
49namespace {
50const int32_t kBurstFrameCount = 10;
51const uint32_t kMaxStillWidth = 2048;
52const uint32_t kMaxStillHeight = 1536;
53
54const int64_t kEmptyFlushTimeoutMSec = 200;
Rucha Katakward08a0152023-10-13 15:47:58 -070055namespace flags = com::android::internal::camera::flags;
Avichal Rakesh362242f2022-02-08 12:40:53 -080056
Shuzhen Wang36efa712022-03-08 10:10:44 -080057const static std::vector<int64_t> kMandatoryUseCases = {
Avichal Rakesh362242f2022-02-08 12:40:53 -080058 ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT,
59 ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_PREVIEW,
60 ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_STILL_CAPTURE,
61 ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_RECORD,
62 ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_PREVIEW_VIDEO_STILL,
63 ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_CALL};
64} // namespace
65
66TEST_P(CameraAidlTest, getCameraIdList) {
67 std::vector<std::string> idList;
68 ScopedAStatus ret = mProvider->getCameraIdList(&idList);
69 ASSERT_TRUE(ret.isOk());
70
71 for (size_t i = 0; i < idList.size(); i++) {
72 ALOGI("Camera Id[%zu] is %s", i, idList[i].c_str());
73 }
74}
75
76// Test if ICameraProvider::getVendorTags returns Status::OK
77TEST_P(CameraAidlTest, getVendorTags) {
78 std::vector<VendorTagSection> vendorTags;
79 ScopedAStatus ret = mProvider->getVendorTags(&vendorTags);
80
81 ASSERT_TRUE(ret.isOk());
82 for (size_t i = 0; i < vendorTags.size(); i++) {
83 ALOGI("Vendor tag section %zu name %s", i, vendorTags[i].sectionName.c_str());
84 for (auto& tag : vendorTags[i].tags) {
85 ALOGI("Vendor tag id %u name %s type %d", tag.tagId, tag.tagName.c_str(),
86 (int)tag.tagType);
87 }
88 }
89}
90
91// Test if ICameraProvider::setCallback returns Status::OK
92TEST_P(CameraAidlTest, setCallback) {
Avichal Rakesh4bf91c72022-05-23 20:44:02 +000093 struct ProviderCb : public BnCameraProviderCallback {
Avichal Rakesh362242f2022-02-08 12:40:53 -080094 ScopedAStatus cameraDeviceStatusChange(const std::string& cameraDeviceName,
95 CameraDeviceStatus newStatus) override {
96 ALOGI("camera device status callback name %s, status %d", cameraDeviceName.c_str(),
97 (int)newStatus);
98 return ScopedAStatus::ok();
99 }
100 ScopedAStatus torchModeStatusChange(const std::string& cameraDeviceName,
101 TorchModeStatus newStatus) override {
102 ALOGI("Torch mode status callback name %s, status %d", cameraDeviceName.c_str(),
103 (int)newStatus);
104 return ScopedAStatus::ok();
105 }
106 ScopedAStatus physicalCameraDeviceStatusChange(const std::string& cameraDeviceName,
107 const std::string& physicalCameraDeviceName,
108 CameraDeviceStatus newStatus) override {
109 ALOGI("physical camera device status callback name %s, physical camera name %s,"
110 " status %d",
111 cameraDeviceName.c_str(), physicalCameraDeviceName.c_str(), (int)newStatus);
112 return ScopedAStatus::ok();
113 }
114 };
115
Avichal Rakesh4bf91c72022-05-23 20:44:02 +0000116 std::shared_ptr<ProviderCb> cb = ndk::SharedRefBase::make<ProviderCb>();
Avichal Rakesh362242f2022-02-08 12:40:53 -0800117 ScopedAStatus ret = mProvider->setCallback(cb);
118 ASSERT_TRUE(ret.isOk());
119 ret = mProvider->setCallback(nullptr);
Avichal Rakesh4bf91c72022-05-23 20:44:02 +0000120 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT), ret.getServiceSpecificError());
Avichal Rakesh362242f2022-02-08 12:40:53 -0800121}
122
123// Test if ICameraProvider::getCameraDeviceInterface returns Status::OK and non-null device
124TEST_P(CameraAidlTest, getCameraDeviceInterface) {
125 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
126
127 for (const auto& name : cameraDeviceNames) {
128 std::shared_ptr<ICameraDevice> cameraDevice;
129 ScopedAStatus ret = mProvider->getCameraDeviceInterface(name, &cameraDevice);
130 ALOGI("getCameraDeviceInterface returns: %d:%d", ret.getExceptionCode(),
131 ret.getServiceSpecificError());
132 ASSERT_TRUE(ret.isOk());
133 ASSERT_NE(cameraDevice, nullptr);
134 }
135}
136
137// Verify that the device resource cost can be retrieved and the values are
138// correct.
139TEST_P(CameraAidlTest, getResourceCost) {
140 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
141
142 for (const auto& deviceName : cameraDeviceNames) {
143 std::shared_ptr<ICameraDevice> cameraDevice;
144 ScopedAStatus ret = mProvider->getCameraDeviceInterface(deviceName, &cameraDevice);
145 ALOGI("getCameraDeviceInterface returns: %d:%d", ret.getExceptionCode(),
146 ret.getServiceSpecificError());
147 ASSERT_TRUE(ret.isOk());
148 ASSERT_NE(cameraDevice, nullptr);
149
150 CameraResourceCost resourceCost;
151 ret = cameraDevice->getResourceCost(&resourceCost);
152 ALOGI("getResourceCost returns: %d:%d", ret.getExceptionCode(),
153 ret.getServiceSpecificError());
154 ASSERT_TRUE(ret.isOk());
155
156 ALOGI(" Resource cost is %d", resourceCost.resourceCost);
157 ASSERT_LE(resourceCost.resourceCost, 100u);
158
159 for (const auto& name : resourceCost.conflictingDevices) {
160 ALOGI(" Conflicting device: %s", name.c_str());
161 }
162 }
163}
164
Rucha Katakward08a0152023-10-13 15:47:58 -0700165// Validate the integrity of manual flash strength control metadata
166TEST_P(CameraAidlTest, validateManualFlashStrengthControlKeys) {
167 if (flags::camera_manual_flash_strength_control()) {
168 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
169 for (const auto& name : cameraDeviceNames) {
170 ALOGI("validateManualFlashStrengthControlKeys: Testing camera device %s", name.c_str());
171 CameraMetadata meta;
172 std::shared_ptr<ICameraDevice> cameraDevice;
173 openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/,
174 &cameraDevice /*out*/);
175 ndk::ScopedAStatus ret = cameraDevice->getCameraCharacteristics(&meta);
176 ASSERT_TRUE(ret.isOk());
177 const camera_metadata_t* staticMeta =
178 reinterpret_cast<const camera_metadata_t*>(meta.metadata.data());
179 verifyManualFlashStrengthControlCharacteristics(staticMeta);
180 }
181 } else {
182 ALOGI("validateManualFlashStrengthControlKeys: Test skipped.\n");
183 GTEST_SKIP();
184 }
185}
186
Avichal Rakesh362242f2022-02-08 12:40:53 -0800187TEST_P(CameraAidlTest, systemCameraTest) {
188 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
189 std::map<std::string, std::vector<SystemCameraKind>> hiddenPhysicalIdToLogicalMap;
190 for (const auto& name : cameraDeviceNames) {
191 std::shared_ptr<ICameraDevice> device;
Avichal Rakeshfbcf7ea2022-03-09 01:00:34 +0000192 ALOGI("systemCameraTest: Testing camera device %s", name.c_str());
Avichal Rakesh362242f2022-02-08 12:40:53 -0800193 ndk::ScopedAStatus ret = mProvider->getCameraDeviceInterface(name, &device);
194 ASSERT_TRUE(ret.isOk());
195 ASSERT_NE(device, nullptr);
196
197 CameraMetadata cameraCharacteristics;
198 ret = device->getCameraCharacteristics(&cameraCharacteristics);
199 ASSERT_TRUE(ret.isOk());
200
201 const camera_metadata_t* staticMeta =
202 reinterpret_cast<const camera_metadata_t*>(cameraCharacteristics.metadata.data());
203 Status rc = isLogicalMultiCamera(staticMeta);
204 if (rc == Status::OPERATION_NOT_SUPPORTED) {
205 return;
206 }
207
208 ASSERT_EQ(rc, Status::OK);
209 std::unordered_set<std::string> physicalIds;
210 ASSERT_EQ(getPhysicalCameraIds(staticMeta, &physicalIds), Status::OK);
211 SystemCameraKind systemCameraKind = SystemCameraKind::PUBLIC;
212 Status retStatus = getSystemCameraKind(staticMeta, &systemCameraKind);
213 ASSERT_EQ(retStatus, Status::OK);
214
215 for (auto physicalId : physicalIds) {
216 bool isPublicId = false;
217 for (auto& deviceName : cameraDeviceNames) {
218 std::string publicVersion, publicId;
219 ASSERT_TRUE(matchDeviceName(deviceName, mProviderType, &publicVersion, &publicId));
220 if (physicalId == publicId) {
221 isPublicId = true;
222 break;
223 }
224 }
Avichal Rakeshfbcf7ea2022-03-09 01:00:34 +0000225
Avichal Rakesh362242f2022-02-08 12:40:53 -0800226 // For hidden physical cameras, collect their associated logical cameras
227 // and store the system camera kind.
228 if (!isPublicId) {
229 auto it = hiddenPhysicalIdToLogicalMap.find(physicalId);
230 if (it == hiddenPhysicalIdToLogicalMap.end()) {
231 hiddenPhysicalIdToLogicalMap.insert(std::make_pair(
Avichal Rakeshfbcf7ea2022-03-09 01:00:34 +0000232 physicalId, std::vector<SystemCameraKind>({systemCameraKind})));
Avichal Rakesh362242f2022-02-08 12:40:53 -0800233 } else {
234 it->second.push_back(systemCameraKind);
235 }
236 }
237 }
238 }
239
240 // Check that the system camera kind of the logical cameras associated with
241 // each hidden physical camera is the same.
242 for (const auto& it : hiddenPhysicalIdToLogicalMap) {
243 SystemCameraKind neededSystemCameraKind = it.second.front();
244 for (auto foundSystemCamera : it.second) {
245 ASSERT_EQ(neededSystemCameraKind, foundSystemCamera);
246 }
247 }
248}
249
250// Verify that the static camera characteristics can be retrieved
251// successfully.
252TEST_P(CameraAidlTest, getCameraCharacteristics) {
253 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
254
255 for (const auto& name : cameraDeviceNames) {
256 std::shared_ptr<ICameraDevice> device;
257 ALOGI("getCameraCharacteristics: Testing camera device %s", name.c_str());
258 ndk::ScopedAStatus ret = mProvider->getCameraDeviceInterface(name, &device);
259 ALOGI("getCameraDeviceInterface returns: %d:%d", ret.getExceptionCode(),
260 ret.getServiceSpecificError());
261 ASSERT_TRUE(ret.isOk());
262 ASSERT_NE(device, nullptr);
263
264 CameraMetadata chars;
265 ret = device->getCameraCharacteristics(&chars);
266 ASSERT_TRUE(ret.isOk());
267 verifyCameraCharacteristics(chars);
268 verifyMonochromeCharacteristics(chars);
269 verifyRecommendedConfigs(chars);
Kwangkyu Park4b7fd452023-05-12 00:22:22 +0900270 verifyHighSpeedRecordingCharacteristics(name, chars);
Avichal Rakesh362242f2022-02-08 12:40:53 -0800271 verifyLogicalOrUltraHighResCameraMetadata(name, device, chars, cameraDeviceNames);
272
273 ASSERT_TRUE(ret.isOk());
274
275 // getPhysicalCameraCharacteristics will fail for publicly
276 // advertised camera IDs.
277 std::string version, cameraId;
278 ASSERT_TRUE(matchDeviceName(name, mProviderType, &version, &cameraId));
279 CameraMetadata devChars;
280 ret = device->getPhysicalCameraCharacteristics(cameraId, &devChars);
281 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT), ret.getServiceSpecificError());
282 ASSERT_EQ(0, devChars.metadata.size());
283 }
284}
285
Bharatt Kukreja48c35ba2023-12-14 20:55:17 +0000286TEST_P(CameraAidlTest, getSessionCharacteristics) {
287 if (flags::feature_combination_query()) {
288 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
289
290 for (const auto& name : cameraDeviceNames) {
291 std::shared_ptr<ICameraDevice> device;
292 ALOGI("getSessionCharacteristics: Testing camera device %s", name.c_str());
293 ndk::ScopedAStatus ret = mProvider->getCameraDeviceInterface(name, &device);
294 ALOGI("getCameraDeviceInterface returns: %d:%d", ret.getExceptionCode(),
295 ret.getServiceSpecificError());
296 ASSERT_TRUE(ret.isOk());
297 ASSERT_NE(device, nullptr);
298
299 CameraMetadata meta;
300 openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/,
301 &device /*out*/);
302
303 std::vector<AvailableStream> outputStreams;
304 camera_metadata_t* staticMeta =
305 reinterpret_cast<camera_metadata_t*>(meta.metadata.data());
306 outputStreams.clear();
307 ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta, outputStreams));
308 ASSERT_NE(0u, outputStreams.size());
309
310 AvailableStream sampleStream = outputStreams[0];
311
312 int32_t streamId = 0;
313 Stream stream = {streamId,
314 StreamType::OUTPUT,
315 sampleStream.width,
316 sampleStream.height,
317 static_cast<PixelFormat>(sampleStream.format),
318 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
319 GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER),
320 Dataspace::UNKNOWN,
321 StreamRotation::ROTATION_0,
322 std::string(),
323 /*bufferSize*/ 0,
324 /*groupId*/ -1,
325 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
326 RequestAvailableDynamicRangeProfilesMap::
327 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
328
329 std::vector<Stream> streams = {stream};
330 StreamConfiguration config;
331 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config);
332
Bharatt Kukrejaa343d982024-01-11 21:19:41 +0000333 CameraMetadata camera_chars;
334 ret = device->getCameraCharacteristics(&camera_chars);
Bharatt Kukreja48c35ba2023-12-14 20:55:17 +0000335 ASSERT_TRUE(ret.isOk());
Bharatt Kukrejaa343d982024-01-11 21:19:41 +0000336
337 CameraMetadata session_chars;
338 ret = device->getSessionCharacteristics(config, &session_chars);
339 ASSERT_TRUE(ret.isOk());
340 verifySessionCharacteristics(session_chars, camera_chars);
Bharatt Kukreja48c35ba2023-12-14 20:55:17 +0000341 }
342 } else {
343 ALOGI("getSessionCharacteristics: Test skipped.\n");
344 GTEST_SKIP();
345 }
346}
347
Avichal Rakesh362242f2022-02-08 12:40:53 -0800348// Verify that the torch strength level can be set and retrieved successfully.
349TEST_P(CameraAidlTest, turnOnTorchWithStrengthLevel) {
350 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
351
352 std::shared_ptr<TorchProviderCb> cb = ndk::SharedRefBase::make<TorchProviderCb>(this);
353 ndk::ScopedAStatus ret = mProvider->setCallback(cb);
354 ASSERT_TRUE(ret.isOk());
355
356 for (const auto& name : cameraDeviceNames) {
357 int32_t defaultLevel;
358 std::shared_ptr<ICameraDevice> device;
359 ALOGI("%s: Testing camera device %s", __FUNCTION__, name.c_str());
360
361 ret = mProvider->getCameraDeviceInterface(name, &device);
362 ASSERT_TRUE(ret.isOk());
363 ASSERT_NE(device, nullptr);
364
365 CameraMetadata chars;
366 ret = device->getCameraCharacteristics(&chars);
367 ASSERT_TRUE(ret.isOk());
368
369 const camera_metadata_t* staticMeta =
370 reinterpret_cast<const camera_metadata_t*>(chars.metadata.data());
371 bool torchStrengthControlSupported = isTorchStrengthControlSupported(staticMeta);
372 camera_metadata_ro_entry entry;
373 int rc = find_camera_metadata_ro_entry(staticMeta,
374 ANDROID_FLASH_INFO_STRENGTH_DEFAULT_LEVEL, &entry);
375 if (torchStrengthControlSupported) {
376 ASSERT_EQ(rc, 0);
377 ASSERT_GT(entry.count, 0);
378 defaultLevel = *entry.data.i32;
379 ALOGI("Default level is:%d", defaultLevel);
380 }
381
382 mTorchStatus = TorchModeStatus::NOT_AVAILABLE;
383 ret = device->turnOnTorchWithStrengthLevel(2);
384 ALOGI("turnOnTorchWithStrengthLevel returns status: %d", ret.getServiceSpecificError());
385 // OPERATION_NOT_SUPPORTED check
386 if (!torchStrengthControlSupported) {
387 ALOGI("Torch strength control not supported.");
388 ASSERT_EQ(static_cast<int32_t>(Status::OPERATION_NOT_SUPPORTED),
389 ret.getServiceSpecificError());
390 } else {
391 {
392 ASSERT_TRUE(ret.isOk());
393 std::unique_lock<std::mutex> l(mTorchLock);
394 while (TorchModeStatus::NOT_AVAILABLE == mTorchStatus) {
395 auto timeout = std::chrono::system_clock::now() +
396 std::chrono::seconds(kTorchTimeoutSec);
397 ASSERT_NE(std::cv_status::timeout, mTorchCond.wait_until(l, timeout));
398 }
399 ASSERT_EQ(TorchModeStatus::AVAILABLE_ON, mTorchStatus);
400 mTorchStatus = TorchModeStatus::NOT_AVAILABLE;
401 }
402 ALOGI("getTorchStrengthLevel: Testing");
403 int32_t strengthLevel;
404 ret = device->getTorchStrengthLevel(&strengthLevel);
405 ASSERT_TRUE(ret.isOk());
406 ALOGI("Torch strength level is : %d", strengthLevel);
407 ASSERT_EQ(strengthLevel, 2);
408
409 // Turn OFF the torch and verify torch strength level is reset to default level.
410 ALOGI("Testing torch strength level reset after turning the torch OFF.");
411 ret = device->setTorchMode(false);
412 ASSERT_TRUE(ret.isOk());
413 {
414 std::unique_lock<std::mutex> l(mTorchLock);
415 while (TorchModeStatus::NOT_AVAILABLE == mTorchStatus) {
416 auto timeout = std::chrono::system_clock::now() +
417 std::chrono::seconds(kTorchTimeoutSec);
418 ASSERT_NE(std::cv_status::timeout, mTorchCond.wait_until(l, timeout));
419 }
420 ASSERT_EQ(TorchModeStatus::AVAILABLE_OFF, mTorchStatus);
421 }
422
423 ret = device->getTorchStrengthLevel(&strengthLevel);
424 ASSERT_TRUE(ret.isOk());
425 ALOGI("Torch strength level after turning OFF torch is : %d", strengthLevel);
426 ASSERT_EQ(strengthLevel, defaultLevel);
427 }
428 }
429}
430
431// In case it is supported verify that torch can be enabled.
432// Check for corresponding torch callbacks as well.
433TEST_P(CameraAidlTest, setTorchMode) {
434 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
435
436 std::shared_ptr<TorchProviderCb> cb = ndk::SharedRefBase::make<TorchProviderCb>(this);
437 ndk::ScopedAStatus ret = mProvider->setCallback(cb);
438 ALOGI("setCallback returns status: %d", ret.getServiceSpecificError());
439 ASSERT_TRUE(ret.isOk());
440 ASSERT_NE(cb, nullptr);
441
442 for (const auto& name : cameraDeviceNames) {
443 std::shared_ptr<ICameraDevice> device;
444 ALOGI("setTorchMode: Testing camera device %s", name.c_str());
445 ret = mProvider->getCameraDeviceInterface(name, &device);
446 ALOGI("getCameraDeviceInterface returns status:%d:%d", ret.getExceptionCode(),
447 ret.getServiceSpecificError());
448 ASSERT_TRUE(ret.isOk());
449 ASSERT_NE(device, nullptr);
450
451 CameraMetadata metadata;
452 ret = device->getCameraCharacteristics(&metadata);
453 ALOGI("getCameraCharacteristics returns status:%d", ret.getServiceSpecificError());
454 ASSERT_TRUE(ret.isOk());
455 camera_metadata_t* staticMeta =
456 reinterpret_cast<camera_metadata_t*>(metadata.metadata.data());
457 bool torchSupported = isTorchSupported(staticMeta);
458
459 mTorchStatus = TorchModeStatus::NOT_AVAILABLE;
460 ret = device->setTorchMode(true);
461 ALOGI("setTorchMode returns status: %d", ret.getServiceSpecificError());
462 if (!torchSupported) {
463 ASSERT_EQ(static_cast<int32_t>(Status::OPERATION_NOT_SUPPORTED),
464 ret.getServiceSpecificError());
465 } else {
466 ASSERT_TRUE(ret.isOk());
467 {
468 std::unique_lock<std::mutex> l(mTorchLock);
469 while (TorchModeStatus::NOT_AVAILABLE == mTorchStatus) {
470 auto timeout = std::chrono::system_clock::now() +
471 std::chrono::seconds(kTorchTimeoutSec);
472 ASSERT_NE(std::cv_status::timeout, mTorchCond.wait_until(l, timeout));
473 }
474 ASSERT_EQ(TorchModeStatus::AVAILABLE_ON, mTorchStatus);
475 mTorchStatus = TorchModeStatus::NOT_AVAILABLE;
476 }
477
478 ret = device->setTorchMode(false);
479 ASSERT_TRUE(ret.isOk());
480 {
481 std::unique_lock<std::mutex> l(mTorchLock);
482 while (TorchModeStatus::NOT_AVAILABLE == mTorchStatus) {
483 auto timeout = std::chrono::system_clock::now() +
484 std::chrono::seconds(kTorchTimeoutSec);
485 ASSERT_NE(std::cv_status::timeout, mTorchCond.wait_until(l, timeout));
486 }
487 ASSERT_EQ(TorchModeStatus::AVAILABLE_OFF, mTorchStatus);
488 }
489 }
490 }
Avichal Rakesh362242f2022-02-08 12:40:53 -0800491}
492
493// Check dump functionality.
494TEST_P(CameraAidlTest, dump) {
495 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
496
497 for (const auto& name : cameraDeviceNames) {
498 std::shared_ptr<ICameraDevice> device;
499 ALOGI("dump: Testing camera device %s", name.c_str());
500
501 ndk::ScopedAStatus ret = mProvider->getCameraDeviceInterface(name, &device);
502 ALOGI("getCameraDeviceInterface returns status:%d:%d", ret.getExceptionCode(),
503 ret.getServiceSpecificError());
504 ASSERT_TRUE(ret.isOk());
505 ASSERT_NE(device, nullptr);
506
507 int raw_handle = open(kDumpOutput, O_RDWR);
508 ASSERT_GE(raw_handle, 0);
509
510 auto retStatus = device->dump(raw_handle, nullptr, 0);
511 ASSERT_EQ(retStatus, ::android::OK);
512 close(raw_handle);
513 }
514}
515
516// Open, dump, then close
517TEST_P(CameraAidlTest, openClose) {
518 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
519
520 for (const auto& name : cameraDeviceNames) {
521 std::shared_ptr<ICameraDevice> device;
522 ALOGI("openClose: Testing camera device %s", name.c_str());
523 ndk::ScopedAStatus ret = mProvider->getCameraDeviceInterface(name, &device);
524 ALOGI("getCameraDeviceInterface returns status:%d:%d", ret.getExceptionCode(),
525 ret.getServiceSpecificError());
526 ASSERT_TRUE(ret.isOk());
527 ASSERT_NE(device, nullptr);
528
529 std::shared_ptr<EmptyDeviceCb> cb = ndk::SharedRefBase::make<EmptyDeviceCb>();
530
531 ret = device->open(cb, &mSession);
532 ASSERT_TRUE(ret.isOk());
533 ALOGI("device::open returns status:%d:%d", ret.getExceptionCode(),
534 ret.getServiceSpecificError());
535 ASSERT_NE(mSession, nullptr);
536 int raw_handle = open(kDumpOutput, O_RDWR);
537 ASSERT_GE(raw_handle, 0);
538
539 auto retStatus = device->dump(raw_handle, nullptr, 0);
540 ASSERT_EQ(retStatus, ::android::OK);
541 close(raw_handle);
542
543 ret = mSession->close();
544 mSession = nullptr;
545 ASSERT_TRUE(ret.isOk());
546 // TODO: test all session API calls return INTERNAL_ERROR after close
547 // TODO: keep a wp copy here and verify session cannot be promoted out of this scope
548 }
549}
550
551// Check whether all common default request settings can be successfully
552// constructed.
553TEST_P(CameraAidlTest, constructDefaultRequestSettings) {
554 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
555
556 for (const auto& name : cameraDeviceNames) {
557 std::shared_ptr<ICameraDevice> device;
558 ALOGI("constructDefaultRequestSettings: Testing camera device %s", name.c_str());
559 ndk::ScopedAStatus ret = mProvider->getCameraDeviceInterface(name, &device);
560 ALOGI("getCameraDeviceInterface returns status:%d:%d", ret.getExceptionCode(),
561 ret.getServiceSpecificError());
562 ASSERT_TRUE(ret.isOk());
563 ASSERT_NE(device, nullptr);
564
Shuzhen Wangdf89cb92023-11-09 18:24:42 -0800565 int32_t interfaceVersion;
566 ret = device->getInterfaceVersion(&interfaceVersion);
567 ASSERT_TRUE(ret.isOk());
568 bool supportFeatureCombinationQuery =
569 (interfaceVersion >= CAMERA_DEVICE_API_MINOR_VERSION_3);
570
Avichal Rakesh362242f2022-02-08 12:40:53 -0800571 std::shared_ptr<EmptyDeviceCb> cb = ndk::SharedRefBase::make<EmptyDeviceCb>();
572 ret = device->open(cb, &mSession);
573 ALOGI("device::open returns status:%d:%d", ret.getExceptionCode(),
574 ret.getServiceSpecificError());
575 ASSERT_TRUE(ret.isOk());
576 ASSERT_NE(mSession, nullptr);
577
578 for (int32_t t = (int32_t)RequestTemplate::PREVIEW; t <= (int32_t)RequestTemplate::MANUAL;
579 t++) {
580 RequestTemplate reqTemplate = (RequestTemplate)t;
581 CameraMetadata rawMetadata;
582 ret = mSession->constructDefaultRequestSettings(reqTemplate, &rawMetadata);
583 ALOGI("constructDefaultRequestSettings returns status:%d:%d", ret.getExceptionCode(),
584 ret.getServiceSpecificError());
Avichal Rakeshd3503a32022-02-25 06:23:14 +0000585
Avichal Rakesh362242f2022-02-08 12:40:53 -0800586 if (reqTemplate == RequestTemplate::ZERO_SHUTTER_LAG ||
587 reqTemplate == RequestTemplate::MANUAL) {
588 // optional templates
589 ASSERT_TRUE(ret.isOk() || static_cast<int32_t>(Status::ILLEGAL_ARGUMENT) ==
590 ret.getServiceSpecificError());
591 } else {
592 ASSERT_TRUE(ret.isOk());
593 }
594
595 if (ret.isOk()) {
Shuzhen Wangdba6eaa2023-12-20 23:54:38 +0000596 validateDefaultRequestMetadata(reqTemplate, rawMetadata);
Avichal Rakesh362242f2022-02-08 12:40:53 -0800597 } else {
598 ASSERT_EQ(0u, rawMetadata.metadata.size());
599 }
Shuzhen Wangdf89cb92023-11-09 18:24:42 -0800600
601 if (flags::feature_combination_query()) {
602 if (supportFeatureCombinationQuery) {
603 CameraMetadata rawMetadata2;
604 ndk::ScopedAStatus ret2 =
605 device->constructDefaultRequestSettings(reqTemplate, &rawMetadata2);
606
Shuzhen Wangdba6eaa2023-12-20 23:54:38 +0000607 ASSERT_EQ(ret.isOk(), ret2.isOk());
608 ASSERT_EQ(ret.getStatus(), ret2.getStatus());
Shuzhen Wangdf89cb92023-11-09 18:24:42 -0800609
Shuzhen Wangdba6eaa2023-12-20 23:54:38 +0000610 ASSERT_EQ(rawMetadata.metadata.size(), rawMetadata2.metadata.size());
611 if (ret2.isOk()) {
612 validateDefaultRequestMetadata(reqTemplate, rawMetadata2);
Shuzhen Wangdf89cb92023-11-09 18:24:42 -0800613 }
614 }
615 }
Avichal Rakesh362242f2022-02-08 12:40:53 -0800616 }
617 ret = mSession->close();
618 mSession = nullptr;
619 ASSERT_TRUE(ret.isOk());
620 }
621}
622
623// Verify that all supported stream formats and sizes can be configured
624// successfully.
625TEST_P(CameraAidlTest, configureStreamsAvailableOutputs) {
626 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
627 std::vector<AvailableStream> outputStreams;
628
629 for (const auto& name : cameraDeviceNames) {
630 CameraMetadata meta;
631 std::shared_ptr<ICameraDevice> device;
632
633 openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/, &device /*out*/);
634
635 camera_metadata_t* staticMeta = reinterpret_cast<camera_metadata_t*>(meta.metadata.data());
636 outputStreams.clear();
637 ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta, outputStreams));
638 ASSERT_NE(0u, outputStreams.size());
639
640 int32_t jpegBufferSize = 0;
641 ASSERT_EQ(Status::OK, getJpegBufferSize(staticMeta, &jpegBufferSize));
642 ASSERT_NE(0u, jpegBufferSize);
643
644 int32_t streamId = 0;
645 int32_t streamConfigCounter = 0;
646 for (auto& it : outputStreams) {
647 Stream stream;
648 Dataspace dataspace = getDataspace(static_cast<PixelFormat>(it.format));
649 stream.id = streamId;
650 stream.streamType = StreamType::OUTPUT;
651 stream.width = it.width;
652 stream.height = it.height;
653 stream.format = static_cast<PixelFormat>(it.format);
654 stream.dataSpace = dataspace;
655 stream.usage = static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
656 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER);
657 stream.rotation = StreamRotation::ROTATION_0;
Avichal Rakeshd3503a32022-02-25 06:23:14 +0000658 stream.dynamicRangeProfile = RequestAvailableDynamicRangeProfilesMap::
659 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD;
Austin Borger263e3622023-06-15 11:32:04 -0700660 stream.useCase = ScalerAvailableStreamUseCases::
661 ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT;
662 stream.colorSpace = static_cast<int>(
663 RequestAvailableColorSpaceProfilesMap::
664 ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED);
Avichal Rakesh362242f2022-02-08 12:40:53 -0800665
666 std::vector<Stream> streams = {stream};
667 StreamConfiguration config;
668 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
669 jpegBufferSize);
670
Shuzhen Wangdf89cb92023-11-09 18:24:42 -0800671 verifyStreamCombination(device, config, /*expectedStatus*/ true);
Avichal Rakesh362242f2022-02-08 12:40:53 -0800672
673 config.streamConfigCounter = streamConfigCounter++;
674 std::vector<HalStream> halConfigs;
675 ndk::ScopedAStatus ret = mSession->configureStreams(config, &halConfigs);
676 ASSERT_TRUE(ret.isOk());
677 ASSERT_EQ(halConfigs.size(), 1);
678 ASSERT_EQ(halConfigs[0].id, streamId);
679
680 streamId++;
681 }
682
683 ndk::ScopedAStatus ret = mSession->close();
684 mSession = nullptr;
685 ASSERT_TRUE(ret.isOk());
686 }
687}
688
689// Verify that mandatory concurrent streams and outputs are supported.
690TEST_P(CameraAidlTest, configureConcurrentStreamsAvailableOutputs) {
691 struct CameraTestInfo {
692 CameraMetadata staticMeta;
693 std::shared_ptr<ICameraDeviceSession> session;
694 std::shared_ptr<ICameraDevice> cameraDevice;
695 StreamConfiguration config;
696 };
697
698 std::map<std::string, std::string> idToNameMap = getCameraDeviceIdToNameMap(mProvider);
699 std::vector<ConcurrentCameraIdCombination> concurrentDeviceCombinations =
700 getConcurrentDeviceCombinations(mProvider);
701 std::vector<AvailableStream> outputStreams;
702 for (const auto& cameraDeviceIds : concurrentDeviceCombinations) {
703 std::vector<CameraIdAndStreamCombination> cameraIdsAndStreamCombinations;
704 std::vector<CameraTestInfo> cameraTestInfos;
Avichal Rakesh362242f2022-02-08 12:40:53 -0800705 for (const auto& id : cameraDeviceIds.combination) {
706 CameraTestInfo cti;
707 auto it = idToNameMap.find(id);
708 ASSERT_TRUE(idToNameMap.end() != it);
709 std::string name = it->second;
710
711 openEmptyDeviceSession(name, mProvider, &cti.session /*out*/, &cti.staticMeta /*out*/,
712 &cti.cameraDevice /*out*/);
713
714 outputStreams.clear();
715 camera_metadata_t* staticMeta =
716 reinterpret_cast<camera_metadata_t*>(cti.staticMeta.metadata.data());
717 ASSERT_EQ(Status::OK, getMandatoryConcurrentStreams(staticMeta, &outputStreams));
718 ASSERT_NE(0u, outputStreams.size());
719
720 int32_t jpegBufferSize = 0;
721 ASSERT_EQ(Status::OK, getJpegBufferSize(staticMeta, &jpegBufferSize));
722 ASSERT_NE(0u, jpegBufferSize);
723
724 int32_t streamId = 0;
725 std::vector<Stream> streams(outputStreams.size());
726 size_t j = 0;
727 for (const auto& s : outputStreams) {
728 Stream stream;
729 Dataspace dataspace = getDataspace(static_cast<PixelFormat>(s.format));
730 stream.id = streamId++;
731 stream.streamType = StreamType::OUTPUT;
732 stream.width = s.width;
733 stream.height = s.height;
734 stream.format = static_cast<PixelFormat>(s.format);
735 stream.usage = static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
736 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER);
737 stream.dataSpace = dataspace;
738 stream.rotation = StreamRotation::ROTATION_0;
739 stream.sensorPixelModesUsed = {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT};
Avichal Rakeshd3503a32022-02-25 06:23:14 +0000740 stream.dynamicRangeProfile = RequestAvailableDynamicRangeProfilesMap::
741 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD;
Avichal Rakesh362242f2022-02-08 12:40:53 -0800742 streams[j] = stream;
743 j++;
744 }
745
746 // Add the created stream configs to cameraIdsAndStreamCombinations
747 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &cti.config,
748 jpegBufferSize);
749
750 cti.config.streamConfigCounter = outputStreams.size();
751 CameraIdAndStreamCombination cameraIdAndStreamCombination;
752 cameraIdAndStreamCombination.cameraId = id;
753 cameraIdAndStreamCombination.streamConfiguration = cti.config;
754 cameraIdsAndStreamCombinations.push_back(cameraIdAndStreamCombination);
Avichal Rakesh362242f2022-02-08 12:40:53 -0800755 cameraTestInfos.push_back(cti);
756 }
757 // Now verify that concurrent streams are supported
758 bool combinationSupported;
759 ndk::ScopedAStatus ret = mProvider->isConcurrentStreamCombinationSupported(
760 cameraIdsAndStreamCombinations, &combinationSupported);
761 ASSERT_TRUE(ret.isOk());
762 ASSERT_EQ(combinationSupported, true);
763
764 // Test the stream can actually be configured
765 for (auto& cti : cameraTestInfos) {
766 if (cti.session != nullptr) {
Shuzhen Wangdf89cb92023-11-09 18:24:42 -0800767 verifyStreamCombination(cti.cameraDevice, cti.config, /*expectedStatus*/ true);
Avichal Rakesh362242f2022-02-08 12:40:53 -0800768 }
769
770 if (cti.session != nullptr) {
771 std::vector<HalStream> streamConfigs;
772 ret = cti.session->configureStreams(cti.config, &streamConfigs);
773 ASSERT_TRUE(ret.isOk());
774 ASSERT_EQ(cti.config.streams.size(), streamConfigs.size());
775 }
776 }
777
778 for (auto& cti : cameraTestInfos) {
779 ret = cti.session->close();
780 ASSERT_TRUE(ret.isOk());
781 }
782 }
783}
784
785// Check for correct handling of invalid/incorrect configuration parameters.
786TEST_P(CameraAidlTest, configureStreamsInvalidOutputs) {
787 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
788 std::vector<AvailableStream> outputStreams;
789
790 for (const auto& name : cameraDeviceNames) {
791 CameraMetadata meta;
792 std::shared_ptr<ICameraDevice> cameraDevice;
793
794 openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/,
795 &cameraDevice /*out*/);
796 camera_metadata_t* staticMeta = reinterpret_cast<camera_metadata_t*>(meta.metadata.data());
797 outputStreams.clear();
798
799 ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta, outputStreams));
800 ASSERT_NE(0u, outputStreams.size());
801
802 int32_t jpegBufferSize = 0;
803 ASSERT_EQ(Status::OK, getJpegBufferSize(staticMeta, &jpegBufferSize));
804 ASSERT_NE(0u, jpegBufferSize);
805
806 int32_t streamId = 0;
807 Stream stream = {streamId++,
808 StreamType::OUTPUT,
809 static_cast<uint32_t>(0),
810 static_cast<uint32_t>(0),
811 static_cast<PixelFormat>(outputStreams[0].format),
812 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
813 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
814 Dataspace::UNKNOWN,
815 StreamRotation::ROTATION_0,
816 std::string(),
817 jpegBufferSize,
818 -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +0000819 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
820 RequestAvailableDynamicRangeProfilesMap::
821 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -0800822 int32_t streamConfigCounter = 0;
823 std::vector<Stream> streams = {stream};
824 StreamConfiguration config;
825 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
826 jpegBufferSize);
827
Shuzhen Wangdf89cb92023-11-09 18:24:42 -0800828 verifyStreamCombination(cameraDevice, config, /*expectedStatus*/ false);
Avichal Rakesh362242f2022-02-08 12:40:53 -0800829
830 config.streamConfigCounter = streamConfigCounter++;
831 std::vector<HalStream> halConfigs;
832 ndk::ScopedAStatus ret = mSession->configureStreams(config, &halConfigs);
833 ASSERT_TRUE(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT) ==
834 ret.getServiceSpecificError() ||
835 static_cast<int32_t>(Status::INTERNAL_ERROR) == ret.getServiceSpecificError());
836
837 stream = {streamId++,
838 StreamType::OUTPUT,
839 /*width*/ INT32_MAX,
840 /*height*/ INT32_MAX,
841 static_cast<PixelFormat>(outputStreams[0].format),
842 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
843 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
844 Dataspace::UNKNOWN,
845 StreamRotation::ROTATION_0,
846 std::string(),
847 jpegBufferSize,
848 -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +0000849 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
850 RequestAvailableDynamicRangeProfilesMap::
851 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -0800852
853 streams[0] = stream;
854 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
855 jpegBufferSize);
856
857 config.streamConfigCounter = streamConfigCounter++;
858 halConfigs.clear();
859 ret = mSession->configureStreams(config, &halConfigs);
860 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT), ret.getServiceSpecificError());
861
862 for (auto& it : outputStreams) {
863 stream = {streamId++,
864 StreamType::OUTPUT,
865 it.width,
866 it.height,
867 static_cast<PixelFormat>(UINT32_MAX),
868 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
869 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
870 Dataspace::UNKNOWN,
871 StreamRotation::ROTATION_0,
872 std::string(),
873 jpegBufferSize,
874 -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +0000875 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
876 RequestAvailableDynamicRangeProfilesMap::
877 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -0800878
879 streams[0] = stream;
880 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
881 jpegBufferSize);
882 config.streamConfigCounter = streamConfigCounter++;
883 halConfigs.clear();
884 ret = mSession->configureStreams(config, &halConfigs);
885 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT),
886 ret.getServiceSpecificError());
887
888 stream = {streamId++,
889 StreamType::OUTPUT,
890 it.width,
891 it.height,
892 static_cast<PixelFormat>(it.format),
893 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
894 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
895 Dataspace::UNKNOWN,
896 static_cast<StreamRotation>(UINT32_MAX),
897 std::string(),
898 jpegBufferSize,
899 -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +0000900 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
901 RequestAvailableDynamicRangeProfilesMap::
902 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -0800903
904 streams[0] = stream;
905 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
906 jpegBufferSize);
907
908 config.streamConfigCounter = streamConfigCounter++;
909 halConfigs.clear();
910 ret = mSession->configureStreams(config, &halConfigs);
911 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT),
912 ret.getServiceSpecificError());
913 }
914
915 ret = mSession->close();
916 mSession = nullptr;
917 ASSERT_TRUE(ret.isOk());
918 }
919}
920
921// Check whether all supported ZSL output stream combinations can be
922// configured successfully.
923TEST_P(CameraAidlTest, configureStreamsZSLInputOutputs) {
924 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
925 std::vector<AvailableStream> inputStreams;
926 std::vector<AvailableZSLInputOutput> inputOutputMap;
927
928 for (const auto& name : cameraDeviceNames) {
929 CameraMetadata meta;
930 std::shared_ptr<ICameraDevice> cameraDevice;
931
932 openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/,
933 &cameraDevice /*out*/);
934 camera_metadata_t* staticMeta = reinterpret_cast<camera_metadata_t*>(meta.metadata.data());
935
936 Status rc = isZSLModeAvailable(staticMeta);
937 if (Status::OPERATION_NOT_SUPPORTED == rc) {
938 ndk::ScopedAStatus ret = mSession->close();
939 mSession = nullptr;
940 ASSERT_TRUE(ret.isOk());
941 continue;
942 }
943 ASSERT_EQ(Status::OK, rc);
944
945 inputStreams.clear();
946 ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta, inputStreams));
947 ASSERT_NE(0u, inputStreams.size());
948
949 inputOutputMap.clear();
950 ASSERT_EQ(Status::OK, getZSLInputOutputMap(staticMeta, inputOutputMap));
951 ASSERT_NE(0u, inputOutputMap.size());
952
953 bool supportMonoY8 = false;
954 if (Status::OK == isMonochromeCamera(staticMeta)) {
955 for (auto& it : inputStreams) {
956 if (it.format == static_cast<uint32_t>(PixelFormat::Y8)) {
957 supportMonoY8 = true;
958 break;
959 }
960 }
961 }
962
963 int32_t jpegBufferSize = 0;
964 ASSERT_EQ(Status::OK, getJpegBufferSize(staticMeta, &jpegBufferSize));
965 ASSERT_NE(0u, jpegBufferSize);
966
967 int32_t streamId = 0;
968 bool hasPrivToY8 = false, hasY8ToY8 = false, hasY8ToBlob = false;
969 uint32_t streamConfigCounter = 0;
970 for (auto& inputIter : inputOutputMap) {
971 AvailableStream input;
972 ASSERT_EQ(Status::OK, findLargestSize(inputStreams, inputIter.inputFormat, input));
973 ASSERT_NE(0u, inputStreams.size());
974
975 if (inputIter.inputFormat ==
976 static_cast<uint32_t>(PixelFormat::IMPLEMENTATION_DEFINED) &&
977 inputIter.outputFormat == static_cast<uint32_t>(PixelFormat::Y8)) {
978 hasPrivToY8 = true;
979 } else if (inputIter.inputFormat == static_cast<uint32_t>(PixelFormat::Y8)) {
980 if (inputIter.outputFormat == static_cast<uint32_t>(PixelFormat::BLOB)) {
981 hasY8ToBlob = true;
982 } else if (inputIter.outputFormat == static_cast<uint32_t>(PixelFormat::Y8)) {
983 hasY8ToY8 = true;
984 }
985 }
986 AvailableStream outputThreshold = {INT32_MAX, INT32_MAX, inputIter.outputFormat};
987 std::vector<AvailableStream> outputStreams;
988 ASSERT_EQ(Status::OK,
989 getAvailableOutputStreams(staticMeta, outputStreams, &outputThreshold));
990 for (auto& outputIter : outputStreams) {
991 Dataspace outputDataSpace =
992 getDataspace(static_cast<PixelFormat>(outputIter.format));
993 Stream zslStream = {
994 streamId++,
995 StreamType::OUTPUT,
996 input.width,
997 input.height,
998 static_cast<PixelFormat>(input.format),
999 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
1000 GRALLOC_USAGE_HW_CAMERA_ZSL),
1001 Dataspace::UNKNOWN,
1002 StreamRotation::ROTATION_0,
1003 std::string(),
1004 jpegBufferSize,
1005 -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00001006 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
1007 RequestAvailableDynamicRangeProfilesMap::
1008 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08001009 Stream inputStream = {
1010 streamId++,
1011 StreamType::INPUT,
1012 input.width,
1013 input.height,
1014 static_cast<PixelFormat>(input.format),
1015 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(0),
1016 Dataspace::UNKNOWN,
1017 StreamRotation::ROTATION_0,
1018 std::string(),
1019 jpegBufferSize,
1020 -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00001021 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
1022 RequestAvailableDynamicRangeProfilesMap::
1023 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08001024 Stream outputStream = {
1025 streamId++,
1026 StreamType::OUTPUT,
1027 outputIter.width,
1028 outputIter.height,
1029 static_cast<PixelFormat>(outputIter.format),
1030 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
1031 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
1032 outputDataSpace,
1033 StreamRotation::ROTATION_0,
1034 std::string(),
1035 jpegBufferSize,
1036 -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00001037 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
1038 RequestAvailableDynamicRangeProfilesMap::
1039 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08001040
1041 std::vector<Stream> streams = {inputStream, zslStream, outputStream};
1042
1043 StreamConfiguration config;
1044 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
1045 jpegBufferSize);
1046
Shuzhen Wangdf89cb92023-11-09 18:24:42 -08001047 verifyStreamCombination(cameraDevice, config, /*expectedStatus*/ true);
Avichal Rakesh362242f2022-02-08 12:40:53 -08001048
1049 config.streamConfigCounter = streamConfigCounter++;
1050 std::vector<HalStream> halConfigs;
1051 ndk::ScopedAStatus ret = mSession->configureStreams(config, &halConfigs);
1052 ASSERT_TRUE(ret.isOk());
1053 ASSERT_EQ(3u, halConfigs.size());
1054 }
1055 }
1056
1057 if (supportMonoY8) {
1058 if (Status::OK == isZSLModeAvailable(staticMeta, PRIV_REPROCESS)) {
1059 ASSERT_TRUE(hasPrivToY8);
1060 }
1061 if (Status::OK == isZSLModeAvailable(staticMeta, YUV_REPROCESS)) {
1062 ASSERT_TRUE(hasY8ToY8);
1063 ASSERT_TRUE(hasY8ToBlob);
1064 }
1065 }
1066
1067 ndk::ScopedAStatus ret = mSession->close();
1068 mSession = nullptr;
1069 ASSERT_TRUE(ret.isOk());
1070 }
1071}
1072
1073// Check whether session parameters are supported. If Hal support for them
1074// exist, then try to configure a preview stream using them.
1075TEST_P(CameraAidlTest, configureStreamsWithSessionParameters) {
1076 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
1077 std::vector<AvailableStream> outputPreviewStreams;
1078 AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
1079 static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
1080
1081 for (const auto& name : cameraDeviceNames) {
1082 CameraMetadata meta;
1083
1084 std::shared_ptr<ICameraDevice> unusedCameraDevice;
1085 openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/,
1086 &unusedCameraDevice /*out*/);
1087 camera_metadata_t* staticMetaBuffer =
1088 reinterpret_cast<camera_metadata_t*>(meta.metadata.data());
1089
1090 std::unordered_set<int32_t> availableSessionKeys;
1091 auto rc = getSupportedKeys(staticMetaBuffer, ANDROID_REQUEST_AVAILABLE_SESSION_KEYS,
1092 &availableSessionKeys);
1093 ASSERT_TRUE(Status::OK == rc);
1094 if (availableSessionKeys.empty()) {
1095 ndk::ScopedAStatus ret = mSession->close();
1096 mSession = nullptr;
1097 ASSERT_TRUE(ret.isOk());
1098 continue;
1099 }
1100
1101 android::hardware::camera::common::V1_0::helper::CameraMetadata previewRequestSettings;
1102 android::hardware::camera::common::V1_0::helper::CameraMetadata sessionParams,
1103 modifiedSessionParams;
1104 constructFilteredSettings(mSession, availableSessionKeys, RequestTemplate::PREVIEW,
1105 &previewRequestSettings, &sessionParams);
1106 if (sessionParams.isEmpty()) {
1107 ndk::ScopedAStatus ret = mSession->close();
1108 mSession = nullptr;
1109 ASSERT_TRUE(ret.isOk());
1110 continue;
1111 }
1112
1113 outputPreviewStreams.clear();
1114
1115 ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMetaBuffer, outputPreviewStreams,
1116 &previewThreshold));
1117 ASSERT_NE(0u, outputPreviewStreams.size());
1118
Avichal Rakeshd3503a32022-02-25 06:23:14 +00001119 Stream previewStream = {
1120 0,
1121 StreamType::OUTPUT,
1122 outputPreviewStreams[0].width,
1123 outputPreviewStreams[0].height,
1124 static_cast<PixelFormat>(outputPreviewStreams[0].format),
1125 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
1126 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
1127 Dataspace::UNKNOWN,
1128 StreamRotation::ROTATION_0,
1129 std::string(),
1130 /*bufferSize*/ 0,
1131 /*groupId*/ -1,
1132 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
1133 RequestAvailableDynamicRangeProfilesMap::
1134 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08001135
1136 std::vector<Stream> streams = {previewStream};
1137 StreamConfiguration config;
1138
1139 config.streams = streams;
1140 config.operationMode = StreamConfigurationMode::NORMAL_MODE;
1141 modifiedSessionParams = sessionParams;
1142 auto sessionParamsBuffer = sessionParams.release();
1143 std::vector<uint8_t> rawSessionParam =
1144 std::vector(reinterpret_cast<uint8_t*>(sessionParamsBuffer),
1145 reinterpret_cast<uint8_t*>(sessionParamsBuffer) +
1146 get_camera_metadata_size(sessionParamsBuffer));
1147
1148 config.sessionParams.metadata = rawSessionParam;
1149 config.streamConfigCounter = 0;
1150 config.streams = {previewStream};
1151 config.streamConfigCounter = 0;
1152 config.multiResolutionInputImage = false;
1153
1154 bool newSessionParamsAvailable = false;
1155 for (const auto& it : availableSessionKeys) {
1156 if (modifiedSessionParams.exists(it)) {
1157 modifiedSessionParams.erase(it);
1158 newSessionParamsAvailable = true;
1159 break;
1160 }
1161 }
1162 if (newSessionParamsAvailable) {
1163 auto modifiedSessionParamsBuffer = modifiedSessionParams.release();
1164 verifySessionReconfigurationQuery(mSession, sessionParamsBuffer,
1165 modifiedSessionParamsBuffer);
1166 modifiedSessionParams.acquire(modifiedSessionParamsBuffer);
1167 }
1168
1169 std::vector<HalStream> halConfigs;
1170 ndk::ScopedAStatus ret = mSession->configureStreams(config, &halConfigs);
1171 ASSERT_TRUE(ret.isOk());
1172 ASSERT_EQ(1u, halConfigs.size());
1173
1174 sessionParams.acquire(sessionParamsBuffer);
1175 ret = mSession->close();
1176 mSession = nullptr;
1177 ASSERT_TRUE(ret.isOk());
1178 }
1179}
1180
1181// Verify that all supported preview + still capture stream combinations
1182// can be configured successfully.
1183TEST_P(CameraAidlTest, configureStreamsPreviewStillOutputs) {
1184 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
1185 std::vector<AvailableStream> outputBlobStreams;
1186 std::vector<AvailableStream> outputPreviewStreams;
1187 AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
1188 static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
1189 AvailableStream blobThreshold = {INT32_MAX, INT32_MAX, static_cast<int32_t>(PixelFormat::BLOB)};
1190
1191 for (const auto& name : cameraDeviceNames) {
1192 CameraMetadata meta;
1193
1194 std::shared_ptr<ICameraDevice> cameraDevice;
1195 openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/,
1196 &cameraDevice /*out*/);
1197
1198 camera_metadata_t* staticMeta = reinterpret_cast<camera_metadata_t*>(meta.metadata.data());
1199
1200 // Check if camera support depth only
1201 if (isDepthOnly(staticMeta)) {
1202 ndk::ScopedAStatus ret = mSession->close();
1203 mSession = nullptr;
1204 ASSERT_TRUE(ret.isOk());
1205 continue;
1206 }
1207
1208 outputBlobStreams.clear();
1209 ASSERT_EQ(Status::OK,
1210 getAvailableOutputStreams(staticMeta, outputBlobStreams, &blobThreshold));
1211 ASSERT_NE(0u, outputBlobStreams.size());
1212
1213 outputPreviewStreams.clear();
1214 ASSERT_EQ(Status::OK,
1215 getAvailableOutputStreams(staticMeta, outputPreviewStreams, &previewThreshold));
1216 ASSERT_NE(0u, outputPreviewStreams.size());
1217
1218 int32_t jpegBufferSize = 0;
1219 ASSERT_EQ(Status::OK, getJpegBufferSize(staticMeta, &jpegBufferSize));
1220 ASSERT_NE(0u, jpegBufferSize);
1221
1222 int32_t streamId = 0;
1223 uint32_t streamConfigCounter = 0;
1224
1225 for (auto& blobIter : outputBlobStreams) {
1226 for (auto& previewIter : outputPreviewStreams) {
1227 Stream previewStream = {
1228 streamId++,
1229 StreamType::OUTPUT,
1230 previewIter.width,
1231 previewIter.height,
1232 static_cast<PixelFormat>(previewIter.format),
1233 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
1234 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
1235 Dataspace::UNKNOWN,
1236 StreamRotation::ROTATION_0,
1237 std::string(),
1238 /*bufferSize*/ 0,
1239 /*groupId*/ -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00001240 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
1241 RequestAvailableDynamicRangeProfilesMap::
1242 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08001243 Stream blobStream = {
1244 streamId++,
1245 StreamType::OUTPUT,
1246 blobIter.width,
1247 blobIter.height,
1248 static_cast<PixelFormat>(blobIter.format),
1249 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
1250 GRALLOC1_CONSUMER_USAGE_CPU_READ),
1251 Dataspace::JFIF,
1252 StreamRotation::ROTATION_0,
1253 std::string(),
1254 /*bufferSize*/ 0,
1255 /*groupId*/ -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00001256 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
1257 RequestAvailableDynamicRangeProfilesMap::
1258 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08001259 std::vector<Stream> streams = {previewStream, blobStream};
1260 StreamConfiguration config;
1261
1262 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
1263 jpegBufferSize);
1264 config.streamConfigCounter = streamConfigCounter++;
Shuzhen Wangdf89cb92023-11-09 18:24:42 -08001265 verifyStreamCombination(cameraDevice, config, /*expectedStatus*/ true);
Avichal Rakesh362242f2022-02-08 12:40:53 -08001266
1267 std::vector<HalStream> halConfigs;
1268 ndk::ScopedAStatus ret = mSession->configureStreams(config, &halConfigs);
1269 ASSERT_TRUE(ret.isOk());
1270 ASSERT_EQ(2u, halConfigs.size());
1271 }
1272 }
1273
1274 ndk::ScopedAStatus ret = mSession->close();
1275 mSession = nullptr;
1276 ASSERT_TRUE(ret.isOk());
1277 }
1278}
1279
1280// In case constrained mode is supported, test whether it can be
1281// configured. Additionally check for common invalid inputs when
1282// using this mode.
1283TEST_P(CameraAidlTest, configureStreamsConstrainedOutputs) {
1284 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
1285
1286 for (const auto& name : cameraDeviceNames) {
1287 CameraMetadata meta;
1288 std::shared_ptr<ICameraDevice> cameraDevice;
1289
1290 openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/,
1291 &cameraDevice /*out*/);
1292 camera_metadata_t* staticMeta = reinterpret_cast<camera_metadata_t*>(meta.metadata.data());
1293
1294 Status rc = isConstrainedModeAvailable(staticMeta);
1295 if (Status::OPERATION_NOT_SUPPORTED == rc) {
1296 ndk::ScopedAStatus ret = mSession->close();
1297 mSession = nullptr;
1298 ASSERT_TRUE(ret.isOk());
1299 continue;
1300 }
1301 ASSERT_EQ(Status::OK, rc);
1302
1303 AvailableStream hfrStream;
1304 rc = pickConstrainedModeSize(staticMeta, hfrStream);
1305 ASSERT_EQ(Status::OK, rc);
1306
1307 int32_t streamId = 0;
1308 uint32_t streamConfigCounter = 0;
1309 Stream stream = {streamId,
1310 StreamType::OUTPUT,
1311 hfrStream.width,
1312 hfrStream.height,
1313 static_cast<PixelFormat>(hfrStream.format),
1314 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
1315 GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER),
1316 Dataspace::UNKNOWN,
1317 StreamRotation::ROTATION_0,
1318 std::string(),
1319 /*bufferSize*/ 0,
1320 /*groupId*/ -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00001321 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
1322 RequestAvailableDynamicRangeProfilesMap::
1323 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08001324 std::vector<Stream> streams = {stream};
1325 StreamConfiguration config;
1326 createStreamConfiguration(streams, StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE,
1327 &config);
1328
Shuzhen Wangdf89cb92023-11-09 18:24:42 -08001329 verifyStreamCombination(cameraDevice, config, /*expectedStatus*/ true);
Avichal Rakesh362242f2022-02-08 12:40:53 -08001330
1331 config.streamConfigCounter = streamConfigCounter++;
1332 std::vector<HalStream> halConfigs;
1333 ndk::ScopedAStatus ret = mSession->configureStreams(config, &halConfigs);
1334 ASSERT_TRUE(ret.isOk());
1335 ASSERT_EQ(1u, halConfigs.size());
1336 ASSERT_EQ(halConfigs[0].id, streamId);
1337
1338 stream = {streamId++,
1339 StreamType::OUTPUT,
1340 static_cast<uint32_t>(0),
1341 static_cast<uint32_t>(0),
1342 static_cast<PixelFormat>(hfrStream.format),
1343 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
1344 GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER),
1345 Dataspace::UNKNOWN,
1346 StreamRotation::ROTATION_0,
1347 std::string(),
1348 /*bufferSize*/ 0,
1349 /*groupId*/ -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00001350 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
1351 RequestAvailableDynamicRangeProfilesMap::
1352 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08001353 streams[0] = stream;
1354 createStreamConfiguration(streams, StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE,
1355 &config);
1356
1357 config.streamConfigCounter = streamConfigCounter++;
1358 std::vector<HalStream> halConfig;
1359 ret = mSession->configureStreams(config, &halConfig);
1360 ASSERT_TRUE(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT) ==
1361 ret.getServiceSpecificError() ||
1362 static_cast<int32_t>(Status::INTERNAL_ERROR) == ret.getServiceSpecificError());
1363
1364 stream = {streamId++,
1365 StreamType::OUTPUT,
1366 INT32_MAX,
1367 INT32_MAX,
1368 static_cast<PixelFormat>(hfrStream.format),
1369 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
1370 GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER),
1371 Dataspace::UNKNOWN,
1372 StreamRotation::ROTATION_0,
1373 std::string(),
1374 /*bufferSize*/ 0,
1375 /*groupId*/ -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00001376 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
1377 RequestAvailableDynamicRangeProfilesMap::
1378 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08001379 streams[0] = stream;
1380 createStreamConfiguration(streams, StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE,
1381 &config);
1382
1383 config.streamConfigCounter = streamConfigCounter++;
1384 halConfigs.clear();
1385 ret = mSession->configureStreams(config, &halConfigs);
1386 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT), ret.getServiceSpecificError());
1387
1388 stream = {streamId++,
1389 StreamType::OUTPUT,
1390 hfrStream.width,
1391 hfrStream.height,
1392 static_cast<PixelFormat>(UINT32_MAX),
1393 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
1394 GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER),
1395 Dataspace::UNKNOWN,
1396 StreamRotation::ROTATION_0,
1397 std::string(),
1398 /*bufferSize*/ 0,
1399 /*groupId*/ -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00001400 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
1401 RequestAvailableDynamicRangeProfilesMap::
1402 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08001403 streams[0] = stream;
1404 createStreamConfiguration(streams, StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE,
1405 &config);
1406
1407 config.streamConfigCounter = streamConfigCounter++;
1408 halConfigs.clear();
1409 ret = mSession->configureStreams(config, &halConfigs);
1410 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT), ret.getServiceSpecificError());
1411
1412 ret = mSession->close();
1413 mSession = nullptr;
1414 ASSERT_TRUE(ret.isOk());
1415 }
1416}
1417
1418// Verify that all supported video + snapshot stream combinations can
1419// be configured successfully.
1420TEST_P(CameraAidlTest, configureStreamsVideoStillOutputs) {
1421 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
1422 std::vector<AvailableStream> outputBlobStreams;
1423 std::vector<AvailableStream> outputVideoStreams;
1424 AvailableStream videoThreshold = {kMaxVideoWidth, kMaxVideoHeight,
1425 static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
1426 AvailableStream blobThreshold = {kMaxVideoWidth, kMaxVideoHeight,
1427 static_cast<int32_t>(PixelFormat::BLOB)};
1428
1429 for (const auto& name : cameraDeviceNames) {
1430 CameraMetadata meta;
1431 std::shared_ptr<ICameraDevice> cameraDevice;
1432
1433 openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/,
1434 &cameraDevice /*out*/);
1435
1436 camera_metadata_t* staticMeta = reinterpret_cast<camera_metadata_t*>(meta.metadata.data());
1437
1438 // Check if camera support depth only
1439 if (isDepthOnly(staticMeta)) {
1440 ndk::ScopedAStatus ret = mSession->close();
1441 mSession = nullptr;
1442 ASSERT_TRUE(ret.isOk());
1443 continue;
1444 }
1445
1446 outputBlobStreams.clear();
1447 ASSERT_EQ(Status::OK,
1448 getAvailableOutputStreams(staticMeta, outputBlobStreams, &blobThreshold));
1449 ASSERT_NE(0u, outputBlobStreams.size());
1450
1451 outputVideoStreams.clear();
1452 ASSERT_EQ(Status::OK,
1453 getAvailableOutputStreams(staticMeta, outputVideoStreams, &videoThreshold));
1454 ASSERT_NE(0u, outputVideoStreams.size());
1455
1456 int32_t jpegBufferSize = 0;
1457 ASSERT_EQ(Status::OK, getJpegBufferSize(staticMeta, &jpegBufferSize));
1458 ASSERT_NE(0u, jpegBufferSize);
1459
1460 int32_t streamId = 0;
1461 uint32_t streamConfigCounter = 0;
1462 for (auto& blobIter : outputBlobStreams) {
1463 for (auto& videoIter : outputVideoStreams) {
1464 Stream videoStream = {
1465 streamId++,
1466 StreamType::OUTPUT,
1467 videoIter.width,
1468 videoIter.height,
1469 static_cast<PixelFormat>(videoIter.format),
1470 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
1471 GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER),
1472 Dataspace::UNKNOWN,
1473 StreamRotation::ROTATION_0,
1474 std::string(),
1475 jpegBufferSize,
1476 /*groupId*/ -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00001477 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
1478 RequestAvailableDynamicRangeProfilesMap::
1479 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08001480 Stream blobStream = {
1481 streamId++,
1482 StreamType::OUTPUT,
1483 blobIter.width,
1484 blobIter.height,
1485 static_cast<PixelFormat>(blobIter.format),
1486 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
1487 GRALLOC1_CONSUMER_USAGE_CPU_READ),
1488 Dataspace::JFIF,
1489 StreamRotation::ROTATION_0,
1490 std::string(),
1491 jpegBufferSize,
1492 /*groupId*/ -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00001493 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
1494 RequestAvailableDynamicRangeProfilesMap::
1495 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08001496 std::vector<Stream> streams = {videoStream, blobStream};
1497 StreamConfiguration config;
1498
1499 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
1500 jpegBufferSize);
Shuzhen Wangdf89cb92023-11-09 18:24:42 -08001501 verifyStreamCombination(cameraDevice, config, /*expectedStatus*/ true);
Avichal Rakesh362242f2022-02-08 12:40:53 -08001502
1503 config.streamConfigCounter = streamConfigCounter++;
1504 std::vector<HalStream> halConfigs;
1505 ndk::ScopedAStatus ret = mSession->configureStreams(config, &halConfigs);
1506 ASSERT_TRUE(ret.isOk());
1507 ASSERT_EQ(2u, halConfigs.size());
1508 }
1509 }
1510
1511 ndk::ScopedAStatus ret = mSession->close();
1512 mSession = nullptr;
1513 ASSERT_TRUE(ret.isOk());
1514 }
1515}
1516
1517// Generate and verify a camera capture request
1518TEST_P(CameraAidlTest, processCaptureRequestPreview) {
1519 // TODO(b/220897574): Failing with BUFFER_ERROR
1520 processCaptureRequestInternal(GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, RequestTemplate::PREVIEW,
1521 false /*secureOnlyCameras*/);
1522}
1523
1524// Generate and verify a secure camera capture request
1525TEST_P(CameraAidlTest, processSecureCaptureRequest) {
1526 processCaptureRequestInternal(GRALLOC1_PRODUCER_USAGE_PROTECTED, RequestTemplate::STILL_CAPTURE,
1527 true /*secureOnlyCameras*/);
1528}
1529
1530TEST_P(CameraAidlTest, processCaptureRequestPreviewStabilization) {
1531 std::unordered_map<std::string, nsecs_t> cameraDeviceToTimeLag;
1532 processPreviewStabilizationCaptureRequestInternal(/*previewStabilizationOn*/ false,
1533 cameraDeviceToTimeLag);
1534 processPreviewStabilizationCaptureRequestInternal(/*previewStabilizationOn*/ true,
1535 cameraDeviceToTimeLag);
1536}
1537
1538// Generate and verify a multi-camera capture request
1539TEST_P(CameraAidlTest, processMultiCaptureRequestPreview) {
1540 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
1541 AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
1542 static_cast<int32_t>(PixelFormat::YCBCR_420_888)};
1543 int64_t bufferId = 1;
1544 uint32_t frameNumber = 1;
1545 std::vector<uint8_t> settings;
1546 std::vector<uint8_t> emptySettings;
1547 std::string invalidPhysicalId = "-1";
1548
1549 for (const auto& name : cameraDeviceNames) {
1550 std::string version, deviceId;
Avichal Rakeshfbcf7ea2022-03-09 01:00:34 +00001551 ALOGI("processMultiCaptureRequestPreview: Test device %s", name.c_str());
Avichal Rakesh362242f2022-02-08 12:40:53 -08001552 ASSERT_TRUE(matchDeviceName(name, mProviderType, &version, &deviceId));
1553 CameraMetadata metadata;
1554
1555 std::shared_ptr<ICameraDevice> unusedDevice;
1556 openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &metadata /*out*/,
1557 &unusedDevice /*out*/);
1558
1559 camera_metadata_t* staticMeta =
1560 reinterpret_cast<camera_metadata_t*>(metadata.metadata.data());
1561 Status rc = isLogicalMultiCamera(staticMeta);
1562 if (Status::OPERATION_NOT_SUPPORTED == rc) {
1563 ndk::ScopedAStatus ret = mSession->close();
1564 mSession = nullptr;
1565 ASSERT_TRUE(ret.isOk());
1566 continue;
1567 }
Avichal Rakeshfbcf7ea2022-03-09 01:00:34 +00001568 ASSERT_EQ(Status::OK, rc);
Avichal Rakesh362242f2022-02-08 12:40:53 -08001569
1570 std::unordered_set<std::string> physicalIds;
1571 rc = getPhysicalCameraIds(staticMeta, &physicalIds);
1572 ASSERT_TRUE(Status::OK == rc);
1573 ASSERT_TRUE(physicalIds.size() > 1);
1574
1575 std::unordered_set<int32_t> physicalRequestKeyIDs;
1576 rc = getSupportedKeys(staticMeta, ANDROID_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS,
1577 &physicalRequestKeyIDs);
1578 ASSERT_TRUE(Status::OK == rc);
1579 if (physicalRequestKeyIDs.empty()) {
1580 ndk::ScopedAStatus ret = mSession->close();
1581 mSession = nullptr;
1582 ASSERT_TRUE(ret.isOk());
1583 // The logical camera doesn't support any individual physical requests.
1584 continue;
1585 }
1586
1587 android::hardware::camera::common::V1_0::helper::CameraMetadata defaultPreviewSettings;
1588 android::hardware::camera::common::V1_0::helper::CameraMetadata filteredSettings;
1589 constructFilteredSettings(mSession, physicalRequestKeyIDs, RequestTemplate::PREVIEW,
1590 &defaultPreviewSettings, &filteredSettings);
1591 if (filteredSettings.isEmpty()) {
1592 // No physical device settings in default request.
1593 ndk::ScopedAStatus ret = mSession->close();
1594 mSession = nullptr;
1595 ASSERT_TRUE(ret.isOk());
1596 continue;
1597 }
1598
1599 const camera_metadata_t* settingsBuffer = defaultPreviewSettings.getAndLock();
1600 uint8_t* rawSettingsBuffer = (uint8_t*)settingsBuffer;
1601 settings.assign(rawSettingsBuffer,
1602 rawSettingsBuffer + get_camera_metadata_size(settingsBuffer));
1603 CameraMetadata settingsMetadata = {settings};
1604 overrideRotateAndCrop(&settingsMetadata);
1605
1606 ndk::ScopedAStatus ret = mSession->close();
1607 mSession = nullptr;
1608 ASSERT_TRUE(ret.isOk());
1609
1610 // Leave only 2 physical devices in the id set.
1611 auto it = physicalIds.begin();
1612 std::string physicalDeviceId = *it;
1613 it++;
1614 physicalIds.erase(++it, physicalIds.end());
1615 ASSERT_EQ(physicalIds.size(), 2u);
1616
1617 std::vector<HalStream> halStreams;
1618 bool supportsPartialResults = false;
Jayant Chowdhary4869ae72023-12-18 05:36:14 +00001619 std::set<int32_t> halBufManagedStreamIds;
Avichal Rakesh362242f2022-02-08 12:40:53 -08001620 int32_t partialResultCount = 0;
1621 Stream previewStream;
1622 std::shared_ptr<DeviceCb> cb;
1623
Avichal Rakeshfbcf7ea2022-03-09 01:00:34 +00001624 configurePreviewStreams(
1625 name, mProvider, &previewThreshold, physicalIds, &mSession, &previewStream,
1626 &halStreams /*out*/, &supportsPartialResults /*out*/, &partialResultCount /*out*/,
Jayant Chowdhary4869ae72023-12-18 05:36:14 +00001627 &halBufManagedStreamIds /*out*/, &cb /*out*/, 0 /*streamConfigCounter*/, true);
Avichal Rakeshfbcf7ea2022-03-09 01:00:34 +00001628 if (mSession == nullptr) {
1629 // stream combination not supported by HAL, skip test for device
1630 continue;
1631 }
Avichal Rakesh362242f2022-02-08 12:40:53 -08001632
1633 ::aidl::android::hardware::common::fmq::MQDescriptor<
1634 int8_t, aidl::android::hardware::common::fmq::SynchronizedReadWrite>
1635 descriptor;
1636 auto resultQueueRet = mSession->getCaptureResultMetadataQueue(&descriptor);
1637 ASSERT_TRUE(resultQueueRet.isOk());
1638 std::shared_ptr<ResultMetadataQueue> resultQueue =
1639 std::make_shared<ResultMetadataQueue>(descriptor);
1640 if (!resultQueue->isValid() || resultQueue->availableToWrite() <= 0) {
1641 ALOGE("%s: HAL returns empty result metadata fmq, not use it", __func__);
1642 resultQueue = nullptr;
1643 // Don't use the queue onwards.
1644 }
1645
1646 std::shared_ptr<InFlightRequest> inflightReq = std::make_shared<InFlightRequest>(
1647 static_cast<ssize_t>(halStreams.size()), false, supportsPartialResults,
1648 partialResultCount, physicalIds, resultQueue);
1649
1650 std::vector<CaptureRequest> requests(1);
1651 CaptureRequest& request = requests[0];
1652 request.frameNumber = frameNumber;
1653 request.fmqSettingsSize = 0;
Emilian Peev3d919f92022-04-20 13:50:59 -07001654 request.settings = settingsMetadata;
Avichal Rakesh362242f2022-02-08 12:40:53 -08001655
1656 std::vector<StreamBuffer>& outputBuffers = request.outputBuffers;
1657
1658 std::vector<buffer_handle_t> graphicBuffers;
1659 graphicBuffers.reserve(halStreams.size());
1660 outputBuffers.resize(halStreams.size());
1661 size_t k = 0;
1662 for (const auto& halStream : halStreams) {
1663 buffer_handle_t buffer_handle;
Jayant Chowdhary4869ae72023-12-18 05:36:14 +00001664 bool useHalBufManagerForStream =
1665 halBufManagedStreamIds.find(halStream.id) != halBufManagedStreamIds.end();
1666 if (useHalBufManagerForStream) {
Avichal Rakesh362242f2022-02-08 12:40:53 -08001667 outputBuffers[k] = {halStream.id, /*bufferId*/ 0, NativeHandle(),
1668 BufferStatus::OK, NativeHandle(), NativeHandle()};
1669 } else {
1670 allocateGraphicBuffer(previewStream.width, previewStream.height,
1671 android_convertGralloc1To0Usage(
1672 static_cast<uint64_t>(halStream.producerUsage),
1673 static_cast<uint64_t>(halStream.consumerUsage)),
1674 halStream.overrideFormat, &buffer_handle);
1675 graphicBuffers.push_back(buffer_handle);
1676 outputBuffers[k] = {
1677 halStream.id, bufferId, ::android::makeToAidl(buffer_handle),
1678 BufferStatus::OK, NativeHandle(), NativeHandle()};
1679 bufferId++;
1680 }
1681 k++;
1682 }
1683
1684 std::vector<PhysicalCameraSetting> camSettings(1);
1685 const camera_metadata_t* filteredSettingsBuffer = filteredSettings.getAndLock();
1686 uint8_t* rawFilteredSettingsBuffer = (uint8_t*)filteredSettingsBuffer;
1687 camSettings[0].settings = {std::vector(
1688 rawFilteredSettingsBuffer,
1689 rawFilteredSettingsBuffer + get_camera_metadata_size(filteredSettingsBuffer))};
1690 overrideRotateAndCrop(&camSettings[0].settings);
1691 camSettings[0].fmqSettingsSize = 0;
1692 camSettings[0].physicalCameraId = physicalDeviceId;
1693
1694 request.inputBuffer = {
1695 -1, 0, NativeHandle(), BufferStatus::ERROR, NativeHandle(), NativeHandle()};
1696 request.physicalCameraSettings = camSettings;
1697
1698 {
1699 std::unique_lock<std::mutex> l(mLock);
1700 mInflightMap.clear();
1701 mInflightMap[frameNumber] = inflightReq;
1702 }
1703
1704 int32_t numRequestProcessed = 0;
1705 std::vector<BufferCache> cachesToRemove;
1706 ndk::ScopedAStatus returnStatus =
1707 mSession->processCaptureRequest(requests, cachesToRemove, &numRequestProcessed);
1708 ASSERT_TRUE(returnStatus.isOk());
1709 ASSERT_EQ(numRequestProcessed, 1u);
1710
1711 {
1712 std::unique_lock<std::mutex> l(mLock);
1713 while (!inflightReq->errorCodeValid &&
1714 ((0 < inflightReq->numBuffersLeft) || (!inflightReq->haveResultMetadata))) {
1715 auto timeout = std::chrono::system_clock::now() +
1716 std::chrono::seconds(kStreamBufferTimeoutSec);
1717 ASSERT_NE(std::cv_status::timeout, mResultCondition.wait_until(l, timeout));
1718 }
1719
1720 ASSERT_FALSE(inflightReq->errorCodeValid);
1721 ASSERT_NE(inflightReq->resultOutputBuffers.size(), 0u);
1722
1723 request.frameNumber++;
1724 // Empty settings should be supported after the first call
1725 // for repeating requests.
1726 request.settings.metadata.clear();
1727 request.physicalCameraSettings[0].settings.metadata.clear();
1728 // The buffer has been registered to HAL by bufferId, so per
1729 // API contract we should send a null handle for this buffer
1730 request.outputBuffers[0].buffer = NativeHandle();
1731 mInflightMap.clear();
1732 inflightReq = std::make_shared<InFlightRequest>(
1733 static_cast<ssize_t>(physicalIds.size()), false, supportsPartialResults,
1734 partialResultCount, physicalIds, resultQueue);
1735 mInflightMap[request.frameNumber] = inflightReq;
1736 }
1737
1738 returnStatus =
1739 mSession->processCaptureRequest(requests, cachesToRemove, &numRequestProcessed);
1740 ASSERT_TRUE(returnStatus.isOk());
1741 ASSERT_EQ(numRequestProcessed, 1u);
1742
1743 {
1744 std::unique_lock<std::mutex> l(mLock);
1745 while (!inflightReq->errorCodeValid &&
1746 ((0 < inflightReq->numBuffersLeft) || (!inflightReq->haveResultMetadata))) {
1747 auto timeout = std::chrono::system_clock::now() +
1748 std::chrono::seconds(kStreamBufferTimeoutSec);
1749 ASSERT_NE(std::cv_status::timeout, mResultCondition.wait_until(l, timeout));
1750 }
1751
1752 ASSERT_FALSE(inflightReq->errorCodeValid);
1753 ASSERT_NE(inflightReq->resultOutputBuffers.size(), 0u);
1754 }
1755
1756 // Invalid physical camera id should fail process requests
1757 frameNumber++;
1758 camSettings[0].physicalCameraId = invalidPhysicalId;
1759 camSettings[0].settings.metadata = settings;
1760
1761 request.physicalCameraSettings = camSettings; // Invalid camera settings
1762 returnStatus =
1763 mSession->processCaptureRequest(requests, cachesToRemove, &numRequestProcessed);
1764 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT),
1765 returnStatus.getServiceSpecificError());
1766
1767 defaultPreviewSettings.unlock(settingsBuffer);
1768 filteredSettings.unlock(filteredSettingsBuffer);
1769
Jayant Chowdhary4869ae72023-12-18 05:36:14 +00001770 if (halBufManagedStreamIds.size() != 0) {
1771 std::vector<int32_t> streamIds;
1772 for (size_t i = 0; i < halStreams.size(); i++) {
1773 int32_t streamId = halStreams[i].id;
1774 if (halBufManagedStreamIds.find(streamId) != halBufManagedStreamIds.end()) {
1775 streamIds.emplace_back(streamId);
1776 }
Avichal Rakesh362242f2022-02-08 12:40:53 -08001777 }
1778 verifyBuffersReturned(mSession, streamIds, cb);
1779 }
1780
1781 ret = mSession->close();
1782 mSession = nullptr;
1783 ASSERT_TRUE(ret.isOk());
1784 }
1785}
1786
1787// Generate and verify an ultra high resolution capture request
1788TEST_P(CameraAidlTest, processUltraHighResolutionRequest) {
1789 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
1790 int64_t bufferId = 1;
1791 int32_t frameNumber = 1;
1792 CameraMetadata settings;
1793
1794 for (const auto& name : cameraDeviceNames) {
1795 std::string version, deviceId;
1796 ASSERT_TRUE(matchDeviceName(name, mProviderType, &version, &deviceId));
1797 CameraMetadata meta;
1798
1799 std::shared_ptr<ICameraDevice> unusedDevice;
1800 openEmptyDeviceSession(name, mProvider, &mSession, &meta, &unusedDevice);
1801 camera_metadata_t* staticMeta = reinterpret_cast<camera_metadata_t*>(meta.metadata.data());
1802 if (!isUltraHighResolution(staticMeta)) {
1803 ndk::ScopedAStatus ret = mSession->close();
1804 mSession = nullptr;
1805 ASSERT_TRUE(ret.isOk());
1806 continue;
1807 }
1808 CameraMetadata req;
1809 android::hardware::camera::common::V1_0::helper::CameraMetadata defaultSettings;
1810 ndk::ScopedAStatus ret =
1811 mSession->constructDefaultRequestSettings(RequestTemplate::STILL_CAPTURE, &req);
1812 ASSERT_TRUE(ret.isOk());
1813
1814 const camera_metadata_t* metadata =
1815 reinterpret_cast<const camera_metadata_t*>(req.metadata.data());
1816 size_t expectedSize = req.metadata.size();
1817 int result = validate_camera_metadata_structure(metadata, &expectedSize);
1818 ASSERT_TRUE((result == 0) || (result == CAMERA_METADATA_VALIDATION_SHIFTED));
1819
1820 size_t entryCount = get_camera_metadata_entry_count(metadata);
1821 ASSERT_GT(entryCount, 0u);
1822 defaultSettings = metadata;
1823 uint8_t sensorPixelMode =
1824 static_cast<uint8_t>(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION);
1825 ASSERT_EQ(::android::OK,
1826 defaultSettings.update(ANDROID_SENSOR_PIXEL_MODE, &sensorPixelMode, 1));
1827
1828 const camera_metadata_t* settingsBuffer = defaultSettings.getAndLock();
1829 uint8_t* rawSettingsBuffer = (uint8_t*)settingsBuffer;
1830 settings.metadata = std::vector(
1831 rawSettingsBuffer, rawSettingsBuffer + get_camera_metadata_size(settingsBuffer));
1832 overrideRotateAndCrop(&settings);
1833
1834 ret = mSession->close();
1835 mSession = nullptr;
1836 ASSERT_TRUE(ret.isOk());
1837
1838 std::vector<HalStream> halStreams;
1839 bool supportsPartialResults = false;
Jayant Chowdhary4869ae72023-12-18 05:36:14 +00001840 std::set<int32_t> halBufManagedStreamIds;
Avichal Rakesh362242f2022-02-08 12:40:53 -08001841 int32_t partialResultCount = 0;
1842 Stream previewStream;
1843 std::shared_ptr<DeviceCb> cb;
1844
1845 std::list<PixelFormat> pixelFormats = {PixelFormat::YCBCR_420_888, PixelFormat::RAW16};
1846 for (PixelFormat format : pixelFormats) {
Emilian Peevdda1eb72022-07-28 16:37:40 -07001847 previewStream.usage =
1848 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
1849 GRALLOC1_CONSUMER_USAGE_CPU_READ);
1850 previewStream.dataSpace = Dataspace::UNKNOWN;
Avichal Rakesh362242f2022-02-08 12:40:53 -08001851 configureStreams(name, mProvider, format, &mSession, &previewStream, &halStreams,
Jayant Chowdhary4869ae72023-12-18 05:36:14 +00001852 &supportsPartialResults, &partialResultCount, &halBufManagedStreamIds,
1853 &cb, 0, /*maxResolution*/ true);
Avichal Rakesh362242f2022-02-08 12:40:53 -08001854 ASSERT_NE(mSession, nullptr);
1855
1856 ::aidl::android::hardware::common::fmq::MQDescriptor<
1857 int8_t, aidl::android::hardware::common::fmq::SynchronizedReadWrite>
1858 descriptor;
1859 auto resultQueueRet = mSession->getCaptureResultMetadataQueue(&descriptor);
1860 ASSERT_TRUE(resultQueueRet.isOk());
1861
1862 std::shared_ptr<ResultMetadataQueue> resultQueue =
1863 std::make_shared<ResultMetadataQueue>(descriptor);
1864 if (!resultQueue->isValid() || resultQueue->availableToWrite() <= 0) {
1865 ALOGE("%s: HAL returns empty result metadata fmq, not use it", __func__);
1866 resultQueue = nullptr;
1867 // Don't use the queue onwards.
1868 }
1869
1870 std::vector<buffer_handle_t> graphicBuffers;
1871 graphicBuffers.reserve(halStreams.size());
1872 std::shared_ptr<InFlightRequest> inflightReq = std::make_shared<InFlightRequest>(
1873 static_cast<ssize_t>(halStreams.size()), false, supportsPartialResults,
1874 partialResultCount, std::unordered_set<std::string>(), resultQueue);
1875
1876 std::vector<CaptureRequest> requests(1);
1877 CaptureRequest& request = requests[0];
1878 std::vector<StreamBuffer>& outputBuffers = request.outputBuffers;
1879 outputBuffers.resize(halStreams.size());
1880
1881 size_t k = 0;
1882 for (const auto& halStream : halStreams) {
1883 buffer_handle_t buffer_handle;
Jayant Chowdhary4869ae72023-12-18 05:36:14 +00001884 bool halBufManagerUsed =
1885 halBufManagedStreamIds.find(halStream.id) != halBufManagedStreamIds.end();
1886 if (halBufManagerUsed) {
Avichal Rakesh362242f2022-02-08 12:40:53 -08001887 outputBuffers[k] = {halStream.id, 0,
1888 NativeHandle(), BufferStatus::OK,
1889 NativeHandle(), NativeHandle()};
1890 } else {
1891 allocateGraphicBuffer(previewStream.width, previewStream.height,
1892 android_convertGralloc1To0Usage(
1893 static_cast<uint64_t>(halStream.producerUsage),
1894 static_cast<uint64_t>(halStream.consumerUsage)),
1895 halStream.overrideFormat, &buffer_handle);
1896 graphicBuffers.push_back(buffer_handle);
1897 outputBuffers[k] = {
1898 halStream.id, bufferId, ::android::makeToAidl(buffer_handle),
1899 BufferStatus::OK, NativeHandle(), NativeHandle()};
1900 bufferId++;
1901 }
1902 k++;
1903 }
1904
1905 request.inputBuffer = {
1906 -1, 0, NativeHandle(), BufferStatus::ERROR, NativeHandle(), NativeHandle()};
1907 request.frameNumber = frameNumber;
1908 request.fmqSettingsSize = 0;
1909 request.settings = settings;
1910 request.inputWidth = 0;
1911 request.inputHeight = 0;
1912
1913 {
1914 std::unique_lock<std::mutex> l(mLock);
1915 mInflightMap.clear();
1916 mInflightMap[frameNumber] = inflightReq;
1917 }
1918
1919 int32_t numRequestProcessed = 0;
1920 std::vector<BufferCache> cachesToRemove;
1921 ndk::ScopedAStatus returnStatus =
1922 mSession->processCaptureRequest(requests, cachesToRemove, &numRequestProcessed);
1923 ASSERT_TRUE(returnStatus.isOk());
1924 ASSERT_EQ(numRequestProcessed, 1u);
1925
1926 {
1927 std::unique_lock<std::mutex> l(mLock);
1928 while (!inflightReq->errorCodeValid &&
1929 ((0 < inflightReq->numBuffersLeft) || (!inflightReq->haveResultMetadata))) {
1930 auto timeout = std::chrono::system_clock::now() +
1931 std::chrono::seconds(kStreamBufferTimeoutSec);
1932 ASSERT_NE(std::cv_status::timeout, mResultCondition.wait_until(l, timeout));
1933 }
1934
1935 ASSERT_FALSE(inflightReq->errorCodeValid);
1936 ASSERT_NE(inflightReq->resultOutputBuffers.size(), 0u);
1937 }
Jayant Chowdhary4869ae72023-12-18 05:36:14 +00001938 if (halBufManagedStreamIds.size()) {
1939 std::vector<int32_t> streamIds;
1940 for (size_t i = 0; i < halStreams.size(); i++) {
1941 if (contains(halBufManagedStreamIds, halStreams[i].id)) {
1942 streamIds.emplace_back(halStreams[i].id);
1943 }
Avichal Rakesh362242f2022-02-08 12:40:53 -08001944 }
1945 verifyBuffersReturned(mSession, streamIds, cb);
1946 }
1947
1948 ret = mSession->close();
1949 mSession = nullptr;
1950 ASSERT_TRUE(ret.isOk());
1951 }
1952 }
1953}
1954
1955// Generate and verify 10-bit dynamic range request
1956TEST_P(CameraAidlTest, process10BitDynamicRangeRequest) {
1957 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
Avichal Rakesh362242f2022-02-08 12:40:53 -08001958 CameraMetadata settings;
1959
1960 for (const auto& name : cameraDeviceNames) {
1961 std::string version, deviceId;
1962 ASSERT_TRUE(matchDeviceName(name, mProviderType, &version, &deviceId));
1963 CameraMetadata meta;
1964 std::shared_ptr<ICameraDevice> device;
1965 openEmptyDeviceSession(name, mProvider, &mSession, &meta, &device);
1966 camera_metadata_t* staticMeta = reinterpret_cast<camera_metadata_t*>(meta.metadata.data());
1967 if (!is10BitDynamicRangeCapable(staticMeta)) {
1968 ndk::ScopedAStatus ret = mSession->close();
1969 mSession = nullptr;
1970 ASSERT_TRUE(ret.isOk());
1971 continue;
1972 }
Avichal Rakeshd3503a32022-02-25 06:23:14 +00001973 std::vector<RequestAvailableDynamicRangeProfilesMap> profileList;
Avichal Rakesh362242f2022-02-08 12:40:53 -08001974 get10BitDynamicRangeProfiles(staticMeta, &profileList);
1975 ASSERT_FALSE(profileList.empty());
1976
1977 CameraMetadata req;
1978 android::hardware::camera::common::V1_0::helper::CameraMetadata defaultSettings;
1979 ndk::ScopedAStatus ret =
Emilian Peevdda1eb72022-07-28 16:37:40 -07001980 mSession->constructDefaultRequestSettings(RequestTemplate::PREVIEW, &req);
Avichal Rakesh362242f2022-02-08 12:40:53 -08001981 ASSERT_TRUE(ret.isOk());
1982
1983 const camera_metadata_t* metadata =
1984 reinterpret_cast<const camera_metadata_t*>(req.metadata.data());
1985 size_t expectedSize = req.metadata.size();
1986 int result = validate_camera_metadata_structure(metadata, &expectedSize);
1987 ASSERT_TRUE((result == 0) || (result == CAMERA_METADATA_VALIDATION_SHIFTED));
1988
1989 size_t entryCount = get_camera_metadata_entry_count(metadata);
1990 ASSERT_GT(entryCount, 0u);
1991 defaultSettings = metadata;
1992
1993 const camera_metadata_t* settingsBuffer = defaultSettings.getAndLock();
1994 uint8_t* rawSettingsBuffer = (uint8_t*)settingsBuffer;
1995 settings.metadata = std::vector(
1996 rawSettingsBuffer, rawSettingsBuffer + get_camera_metadata_size(settingsBuffer));
1997 overrideRotateAndCrop(&settings);
1998
1999 ret = mSession->close();
2000 mSession = nullptr;
2001 ASSERT_TRUE(ret.isOk());
2002
2003 std::vector<HalStream> halStreams;
2004 bool supportsPartialResults = false;
Jayant Chowdhary4869ae72023-12-18 05:36:14 +00002005 std::set<int32_t> halBufManagedStreamIds;
Avichal Rakesh362242f2022-02-08 12:40:53 -08002006 int32_t partialResultCount = 0;
2007 Stream previewStream;
2008 std::shared_ptr<DeviceCb> cb;
2009 for (const auto& profile : profileList) {
Emilian Peevdda1eb72022-07-28 16:37:40 -07002010 previewStream.usage =
2011 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
2012 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER);
2013 previewStream.dataSpace = getDataspace(PixelFormat::IMPLEMENTATION_DEFINED);
Avichal Rakesh362242f2022-02-08 12:40:53 -08002014 configureStreams(name, mProvider, PixelFormat::IMPLEMENTATION_DEFINED, &mSession,
2015 &previewStream, &halStreams, &supportsPartialResults,
Jayant Chowdhary4869ae72023-12-18 05:36:14 +00002016 &partialResultCount, &halBufManagedStreamIds, &cb, 0,
Avichal Rakesh362242f2022-02-08 12:40:53 -08002017 /*maxResolution*/ false, profile);
2018 ASSERT_NE(mSession, nullptr);
2019
2020 ::aidl::android::hardware::common::fmq::MQDescriptor<
2021 int8_t, aidl::android::hardware::common::fmq::SynchronizedReadWrite>
2022 descriptor;
2023 auto resultQueueRet = mSession->getCaptureResultMetadataQueue(&descriptor);
2024 ASSERT_TRUE(resultQueueRet.isOk());
2025
2026 std::shared_ptr<ResultMetadataQueue> resultQueue =
2027 std::make_shared<ResultMetadataQueue>(descriptor);
2028 if (!resultQueue->isValid() || resultQueue->availableToWrite() <= 0) {
2029 ALOGE("%s: HAL returns empty result metadata fmq, not use it", __func__);
2030 resultQueue = nullptr;
2031 // Don't use the queue onwards.
2032 }
2033
Emilian Peevdda1eb72022-07-28 16:37:40 -07002034 mInflightMap.clear();
2035 // Stream as long as needed to fill the Hal inflight queue
2036 std::vector<CaptureRequest> requests(halStreams[0].maxBuffers);
Avichal Rakesh362242f2022-02-08 12:40:53 -08002037
Emilian Peev470d1382023-01-18 11:09:09 -08002038 for (int32_t requestId = 0; requestId < requests.size(); requestId++) {
Emilian Peevdda1eb72022-07-28 16:37:40 -07002039 std::shared_ptr<InFlightRequest> inflightReq = std::make_shared<InFlightRequest>(
2040 static_cast<ssize_t>(halStreams.size()), false, supportsPartialResults,
2041 partialResultCount, std::unordered_set<std::string>(), resultQueue);
Avichal Rakesh362242f2022-02-08 12:40:53 -08002042
Emilian Peev470d1382023-01-18 11:09:09 -08002043 CaptureRequest& request = requests[requestId];
Emilian Peevdda1eb72022-07-28 16:37:40 -07002044 std::vector<StreamBuffer>& outputBuffers = request.outputBuffers;
2045 outputBuffers.resize(halStreams.size());
Avichal Rakesh362242f2022-02-08 12:40:53 -08002046
Emilian Peevdda1eb72022-07-28 16:37:40 -07002047 size_t k = 0;
2048 inflightReq->mOutstandingBufferIds.resize(halStreams.size());
2049 std::vector<buffer_handle_t> graphicBuffers;
2050 graphicBuffers.reserve(halStreams.size());
Avichal Rakesh362242f2022-02-08 12:40:53 -08002051
Emilian Peev470d1382023-01-18 11:09:09 -08002052 auto bufferId = requestId + 1; // Buffer id value 0 is not valid
Emilian Peevdda1eb72022-07-28 16:37:40 -07002053 for (const auto& halStream : halStreams) {
2054 buffer_handle_t buffer_handle;
Jayant Chowdhary4869ae72023-12-18 05:36:14 +00002055 if (contains(halBufManagedStreamIds, halStream.id)) {
Emilian Peevdda1eb72022-07-28 16:37:40 -07002056 outputBuffers[k] = {halStream.id, 0,
2057 NativeHandle(), BufferStatus::OK,
2058 NativeHandle(), NativeHandle()};
2059 } else {
2060 auto usage = android_convertGralloc1To0Usage(
2061 static_cast<uint64_t>(halStream.producerUsage),
2062 static_cast<uint64_t>(halStream.consumerUsage));
2063 allocateGraphicBuffer(previewStream.width, previewStream.height, usage,
2064 halStream.overrideFormat, &buffer_handle);
2065
2066 inflightReq->mOutstandingBufferIds[halStream.id][bufferId] = buffer_handle;
2067 graphicBuffers.push_back(buffer_handle);
2068 outputBuffers[k] = {halStream.id, bufferId,
2069 android::makeToAidl(buffer_handle), BufferStatus::OK, NativeHandle(),
2070 NativeHandle()};
Emilian Peevdda1eb72022-07-28 16:37:40 -07002071 }
2072 k++;
Avichal Rakesh362242f2022-02-08 12:40:53 -08002073 }
Avichal Rakesh362242f2022-02-08 12:40:53 -08002074
Emilian Peevdda1eb72022-07-28 16:37:40 -07002075 request.inputBuffer = {
2076 -1, 0, NativeHandle(), BufferStatus::ERROR, NativeHandle(), NativeHandle()};
Emilian Peev470d1382023-01-18 11:09:09 -08002077 request.frameNumber = bufferId;
Emilian Peevdda1eb72022-07-28 16:37:40 -07002078 request.fmqSettingsSize = 0;
2079 request.settings = settings;
2080 request.inputWidth = 0;
2081 request.inputHeight = 0;
Avichal Rakesh362242f2022-02-08 12:40:53 -08002082
Emilian Peevdda1eb72022-07-28 16:37:40 -07002083 {
2084 std::unique_lock<std::mutex> l(mLock);
Emilian Peev470d1382023-01-18 11:09:09 -08002085 mInflightMap[bufferId] = inflightReq;
Emilian Peevdda1eb72022-07-28 16:37:40 -07002086 }
2087
Avichal Rakesh362242f2022-02-08 12:40:53 -08002088 }
2089
2090 int32_t numRequestProcessed = 0;
2091 std::vector<BufferCache> cachesToRemove;
2092 ndk::ScopedAStatus returnStatus =
Emilian Peevdda1eb72022-07-28 16:37:40 -07002093 mSession->processCaptureRequest(requests, cachesToRemove, &numRequestProcessed);
Avichal Rakesh362242f2022-02-08 12:40:53 -08002094 ASSERT_TRUE(returnStatus.isOk());
Emilian Peevdda1eb72022-07-28 16:37:40 -07002095 ASSERT_EQ(numRequestProcessed, requests.size());
Avichal Rakesh362242f2022-02-08 12:40:53 -08002096
Emilian Peevdda1eb72022-07-28 16:37:40 -07002097 returnStatus = mSession->repeatingRequestEnd(requests.size() - 1,
2098 std::vector<int32_t> {halStreams[0].id});
2099 ASSERT_TRUE(returnStatus.isOk());
2100
Emilian Peev470d1382023-01-18 11:09:09 -08002101 // We are keeping frame numbers and buffer ids consistent. Buffer id value of 0
2102 // is used to indicate a buffer that is not present/available so buffer ids as well
2103 // as frame numbers begin with 1.
2104 for (int32_t frameNumber = 1; frameNumber <= requests.size(); frameNumber++) {
Emilian Peevdda1eb72022-07-28 16:37:40 -07002105 const auto& inflightReq = mInflightMap[frameNumber];
Avichal Rakesh362242f2022-02-08 12:40:53 -08002106 std::unique_lock<std::mutex> l(mLock);
2107 while (!inflightReq->errorCodeValid &&
2108 ((0 < inflightReq->numBuffersLeft) || (!inflightReq->haveResultMetadata))) {
2109 auto timeout = std::chrono::system_clock::now() +
2110 std::chrono::seconds(kStreamBufferTimeoutSec);
2111 ASSERT_NE(std::cv_status::timeout, mResultCondition.wait_until(l, timeout));
2112 }
2113
Shuzhen Wang0f56c562023-04-03 16:58:59 -07002114 waitForReleaseFence(inflightReq->resultOutputBuffers);
2115
Avichal Rakesh362242f2022-02-08 12:40:53 -08002116 ASSERT_FALSE(inflightReq->errorCodeValid);
2117 ASSERT_NE(inflightReq->resultOutputBuffers.size(), 0u);
2118 verify10BitMetadata(mHandleImporter, *inflightReq, profile);
2119 }
Emilian Peevdda1eb72022-07-28 16:37:40 -07002120
Jayant Chowdhary4869ae72023-12-18 05:36:14 +00002121 if (halBufManagedStreamIds.size() != 0) {
2122 std::vector<int32_t> streamIds;
2123 for (size_t i = 0; i < halStreams.size(); i++) {
2124 if (contains(halBufManagedStreamIds, halStreams[i].id)) {
2125 streamIds.emplace_back(halStreams[i].id);
2126 }
Avichal Rakesh362242f2022-02-08 12:40:53 -08002127 }
2128 mSession->signalStreamFlush(streamIds, /*streamConfigCounter*/ 0);
2129 cb->waitForBuffersReturned();
2130 }
2131
2132 ret = mSession->close();
2133 mSession = nullptr;
2134 ASSERT_TRUE(ret.isOk());
2135 }
2136 }
2137}
2138
Austin Borger4728fc42022-07-15 11:27:53 -07002139TEST_P(CameraAidlTest, process8BitColorSpaceRequests) {
Austin Borger54b22362023-03-22 11:25:06 -07002140 static int profiles[] = {ColorSpaceNamed::DISPLAY_P3, ColorSpaceNamed::SRGB};
Austin Borger4728fc42022-07-15 11:27:53 -07002141
2142 for (int32_t i = 0; i < sizeof(profiles) / sizeof(profiles[0]); i++) {
2143 processColorSpaceRequest(static_cast<RequestAvailableColorSpaceProfilesMap>(profiles[i]),
2144 static_cast<RequestAvailableDynamicRangeProfilesMap>(
2145 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD));
2146 }
2147}
2148
2149TEST_P(CameraAidlTest, process10BitColorSpaceRequests) {
2150 static const camera_metadata_enum_android_request_available_dynamic_range_profiles_map
2151 dynamicRangeProfiles[] = {
2152 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HLG10,
2153 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10,
2154 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10_PLUS,
2155 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF,
2156 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF_PO,
2157 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM,
2158 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM_PO,
2159 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_REF,
2160 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_REF_PO,
2161 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_OEM,
2162 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_OEM_PO
2163 };
2164
Austin Borger54b22362023-03-22 11:25:06 -07002165 // Process all dynamic range profiles with BT2020_HLG
Austin Borger4728fc42022-07-15 11:27:53 -07002166 for (int32_t i = 0; i < sizeof(dynamicRangeProfiles) / sizeof(dynamicRangeProfiles[0]); i++) {
2167 processColorSpaceRequest(
Austin Borger54b22362023-03-22 11:25:06 -07002168 static_cast<RequestAvailableColorSpaceProfilesMap>(ColorSpaceNamed::BT2020_HLG),
Austin Borger4728fc42022-07-15 11:27:53 -07002169 static_cast<RequestAvailableDynamicRangeProfilesMap>(dynamicRangeProfiles[i]));
2170 }
2171}
2172
Shuzhen Wang4dd6a512022-11-08 20:47:20 +00002173TEST_P(CameraAidlTest, processZoomSettingsOverrideRequests) {
2174 const int32_t kFrameCount = 5;
2175 const int32_t kTestCases = 2;
Shuzhen Wang38ddb272023-05-22 09:40:28 -07002176 const bool kOverrideSequence[kTestCases][kFrameCount] = {// ZOOM, ZOOM, ZOOM, ZOOM, ZOOM;
2177 {true, true, true, true, true},
2178 // OFF, ZOOM, ZOOM, ZOOM, OFF;
2179 {false, true, true, true, false}};
Shuzhen Wang4dd6a512022-11-08 20:47:20 +00002180 const bool kExpectedOverrideResults[kTestCases][kFrameCount] = {
Shuzhen Wang38ddb272023-05-22 09:40:28 -07002181 // All resuls should be overridden except the last one. The last result's
2182 // zoom doesn't have speed-up.
2183 {true, true, true, true, false},
2184 // Because we require at least 1 frame speed-up, request #1, #2 and #3
2185 // will be overridden.
2186 {true, true, true, false, false}};
Shuzhen Wang4dd6a512022-11-08 20:47:20 +00002187
2188 for (int i = 0; i < kTestCases; i++) {
2189 processZoomSettingsOverrideRequests(kFrameCount, kOverrideSequence[i],
2190 kExpectedOverrideResults[i]);
2191 }
2192}
2193
Avichal Rakesh362242f2022-02-08 12:40:53 -08002194// Generate and verify a burst containing alternating sensor sensitivity values
2195TEST_P(CameraAidlTest, processCaptureRequestBurstISO) {
2196 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
2197 AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
2198 static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
2199 int64_t bufferId = 1;
2200 int32_t frameNumber = 1;
2201 float isoTol = .03f;
2202 CameraMetadata settings;
2203
2204 for (const auto& name : cameraDeviceNames) {
2205 CameraMetadata meta;
2206 settings.metadata.clear();
2207 std::shared_ptr<ICameraDevice> unusedDevice;
2208 openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/,
2209 &unusedDevice /*out*/);
2210 camera_metadata_t* staticMetaBuffer =
2211 clone_camera_metadata(reinterpret_cast<camera_metadata_t*>(meta.metadata.data()));
2212 ::android::hardware::camera::common::V1_0::helper::CameraMetadata staticMeta(
2213 staticMetaBuffer);
2214
2215 camera_metadata_entry_t hwLevel = staticMeta.find(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL);
2216 ASSERT_TRUE(0 < hwLevel.count);
2217 if (ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED == hwLevel.data.u8[0] ||
2218 ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL == hwLevel.data.u8[0]) {
2219 // Limited/External devices can skip this test
2220 ndk::ScopedAStatus ret = mSession->close();
2221 mSession = nullptr;
2222 ASSERT_TRUE(ret.isOk());
2223 continue;
2224 }
2225
2226 camera_metadata_entry_t isoRange = staticMeta.find(ANDROID_SENSOR_INFO_SENSITIVITY_RANGE);
2227 ASSERT_EQ(isoRange.count, 2u);
2228
2229 ndk::ScopedAStatus ret = mSession->close();
2230 mSession = nullptr;
2231 ASSERT_TRUE(ret.isOk());
2232
2233 bool supportsPartialResults = false;
2234 bool useHalBufManager = false;
2235 int32_t partialResultCount = 0;
2236 Stream previewStream;
2237 std::vector<HalStream> halStreams;
2238 std::shared_ptr<DeviceCb> cb;
2239 configurePreviewStream(name, mProvider, &previewThreshold, &mSession /*out*/,
2240 &previewStream /*out*/, &halStreams /*out*/,
2241 &supportsPartialResults /*out*/, &partialResultCount /*out*/,
2242 &useHalBufManager /*out*/, &cb /*out*/);
2243
2244 ::aidl::android::hardware::common::fmq::MQDescriptor<
2245 int8_t, aidl::android::hardware::common::fmq::SynchronizedReadWrite>
2246 descriptor;
2247 auto resultQueueRet = mSession->getCaptureResultMetadataQueue(&descriptor);
2248 std::shared_ptr<ResultMetadataQueue> resultQueue =
2249 std::make_shared<ResultMetadataQueue>(descriptor);
2250 ASSERT_TRUE(resultQueueRet.isOk());
2251 if (!resultQueue->isValid() || resultQueue->availableToWrite() <= 0) {
2252 ALOGE("%s: HAL returns empty result metadata fmq, not use it", __func__);
2253 resultQueue = nullptr;
2254 // Don't use the queue onwards.
2255 }
2256
2257 ret = mSession->constructDefaultRequestSettings(RequestTemplate::PREVIEW, &settings);
2258 ASSERT_TRUE(ret.isOk());
2259
2260 ::android::hardware::camera::common::V1_0::helper::CameraMetadata requestMeta;
2261 std::vector<CaptureRequest> requests(kBurstFrameCount);
2262 std::vector<buffer_handle_t> buffers(kBurstFrameCount);
2263 std::vector<std::shared_ptr<InFlightRequest>> inflightReqs(kBurstFrameCount);
2264 std::vector<int32_t> isoValues(kBurstFrameCount);
2265 std::vector<CameraMetadata> requestSettings(kBurstFrameCount);
2266
2267 for (int32_t i = 0; i < kBurstFrameCount; i++) {
2268 std::unique_lock<std::mutex> l(mLock);
2269 CaptureRequest& request = requests[i];
2270 std::vector<StreamBuffer>& outputBuffers = request.outputBuffers;
2271 outputBuffers.resize(1);
2272 StreamBuffer& outputBuffer = outputBuffers[0];
2273
2274 isoValues[i] = ((i % 2) == 0) ? isoRange.data.i32[0] : isoRange.data.i32[1];
2275 if (useHalBufManager) {
2276 outputBuffer = {halStreams[0].id, 0,
2277 NativeHandle(), BufferStatus::OK,
2278 NativeHandle(), NativeHandle()};
2279 } else {
2280 allocateGraphicBuffer(previewStream.width, previewStream.height,
2281 android_convertGralloc1To0Usage(
2282 static_cast<uint64_t>(halStreams[0].producerUsage),
2283 static_cast<uint64_t>(halStreams[0].consumerUsage)),
2284 halStreams[0].overrideFormat, &buffers[i]);
2285 outputBuffer = {halStreams[0].id, bufferId + i, ::android::makeToAidl(buffers[i]),
2286 BufferStatus::OK, NativeHandle(), NativeHandle()};
2287 }
2288
2289 requestMeta.append(reinterpret_cast<camera_metadata_t*>(settings.metadata.data()));
2290
2291 // Disable all 3A routines
2292 uint8_t mode = static_cast<uint8_t>(ANDROID_CONTROL_MODE_OFF);
2293 ASSERT_EQ(::android::OK, requestMeta.update(ANDROID_CONTROL_MODE, &mode, 1));
2294 ASSERT_EQ(::android::OK,
2295 requestMeta.update(ANDROID_SENSOR_SENSITIVITY, &isoValues[i], 1));
2296 camera_metadata_t* metaBuffer = requestMeta.release();
2297 uint8_t* rawMetaBuffer = reinterpret_cast<uint8_t*>(metaBuffer);
2298 requestSettings[i].metadata = std::vector(
2299 rawMetaBuffer, rawMetaBuffer + get_camera_metadata_size(metaBuffer));
2300 overrideRotateAndCrop(&(requestSettings[i]));
2301
2302 request.frameNumber = frameNumber + i;
2303 request.fmqSettingsSize = 0;
2304 request.settings = requestSettings[i];
2305 request.inputBuffer = {
2306 -1, 0, NativeHandle(), BufferStatus::ERROR, NativeHandle(), NativeHandle()};
2307
2308 inflightReqs[i] = std::make_shared<InFlightRequest>(1, false, supportsPartialResults,
2309 partialResultCount, resultQueue);
2310 mInflightMap[frameNumber + i] = inflightReqs[i];
2311 }
2312
2313 int32_t numRequestProcessed = 0;
2314 std::vector<BufferCache> cachesToRemove;
2315
2316 ndk::ScopedAStatus returnStatus =
2317 mSession->processCaptureRequest(requests, cachesToRemove, &numRequestProcessed);
2318 ASSERT_TRUE(returnStatus.isOk());
2319 ASSERT_EQ(numRequestProcessed, kBurstFrameCount);
2320
2321 for (size_t i = 0; i < kBurstFrameCount; i++) {
2322 std::unique_lock<std::mutex> l(mLock);
2323 while (!inflightReqs[i]->errorCodeValid && ((0 < inflightReqs[i]->numBuffersLeft) ||
2324 (!inflightReqs[i]->haveResultMetadata))) {
2325 auto timeout = std::chrono::system_clock::now() +
2326 std::chrono::seconds(kStreamBufferTimeoutSec);
2327 ASSERT_NE(std::cv_status::timeout, mResultCondition.wait_until(l, timeout));
2328 }
2329
2330 ASSERT_FALSE(inflightReqs[i]->errorCodeValid);
2331 ASSERT_NE(inflightReqs[i]->resultOutputBuffers.size(), 0u);
2332 ASSERT_EQ(previewStream.id, inflightReqs[i]->resultOutputBuffers[0].buffer.streamId);
2333 ASSERT_FALSE(inflightReqs[i]->collectedResult.isEmpty());
2334 ASSERT_TRUE(inflightReqs[i]->collectedResult.exists(ANDROID_SENSOR_SENSITIVITY));
2335 camera_metadata_entry_t isoResult =
2336 inflightReqs[i]->collectedResult.find(ANDROID_SENSOR_SENSITIVITY);
2337 ASSERT_TRUE(std::abs(isoResult.data.i32[0] - isoValues[i]) <=
2338 std::round(isoValues[i] * isoTol));
2339 }
2340
2341 if (useHalBufManager) {
2342 verifyBuffersReturned(mSession, previewStream.id, cb);
2343 }
2344 ret = mSession->close();
2345 mSession = nullptr;
2346 ASSERT_TRUE(ret.isOk());
2347 }
2348}
2349
2350// Test whether an incorrect capture request with missing settings will
2351// be reported correctly.
2352TEST_P(CameraAidlTest, processCaptureRequestInvalidSinglePreview) {
2353 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
2354 std::vector<AvailableStream> outputPreviewStreams;
2355 AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
2356 static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
2357 int64_t bufferId = 1;
2358 int32_t frameNumber = 1;
2359 CameraMetadata settings;
2360
2361 for (const auto& name : cameraDeviceNames) {
2362 Stream previewStream;
2363 std::vector<HalStream> halStreams;
2364 std::shared_ptr<DeviceCb> cb;
2365 bool supportsPartialResults = false;
2366 bool useHalBufManager = false;
2367 int32_t partialResultCount = 0;
2368 configurePreviewStream(name, mProvider, &previewThreshold, &mSession /*out*/,
2369 &previewStream /*out*/, &halStreams /*out*/,
2370 &supportsPartialResults /*out*/, &partialResultCount /*out*/,
2371 &useHalBufManager /*out*/, &cb /*out*/);
2372 ASSERT_NE(mSession, nullptr);
2373 ASSERT_FALSE(halStreams.empty());
2374
2375 buffer_handle_t buffer_handle = nullptr;
2376
2377 if (useHalBufManager) {
2378 bufferId = 0;
2379 } else {
2380 allocateGraphicBuffer(previewStream.width, previewStream.height,
2381 android_convertGralloc1To0Usage(
2382 static_cast<uint64_t>(halStreams[0].producerUsage),
2383 static_cast<uint64_t>(halStreams[0].consumerUsage)),
2384 halStreams[0].overrideFormat, &buffer_handle);
2385 }
2386
2387 std::vector<CaptureRequest> requests(1);
2388 CaptureRequest& request = requests[0];
2389 std::vector<StreamBuffer>& outputBuffers = request.outputBuffers;
2390 outputBuffers.resize(1);
2391 StreamBuffer& outputBuffer = outputBuffers[0];
2392
2393 outputBuffer = {
2394 halStreams[0].id,
2395 bufferId,
2396 buffer_handle == nullptr ? NativeHandle() : ::android::makeToAidl(buffer_handle),
2397 BufferStatus::OK,
2398 NativeHandle(),
2399 NativeHandle()};
2400
2401 request.inputBuffer = {
2402 -1, 0, NativeHandle(), BufferStatus::ERROR, NativeHandle(), NativeHandle()};
2403 request.frameNumber = frameNumber;
2404 request.fmqSettingsSize = 0;
2405 request.settings = settings;
2406
2407 // Settings were not correctly initialized, we should fail here
2408 int32_t numRequestProcessed = 0;
2409 std::vector<BufferCache> cachesToRemove;
2410 ndk::ScopedAStatus ret =
2411 mSession->processCaptureRequest(requests, cachesToRemove, &numRequestProcessed);
2412 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT), ret.getServiceSpecificError());
2413 ASSERT_EQ(numRequestProcessed, 0u);
2414
2415 ret = mSession->close();
2416 mSession = nullptr;
2417 ASSERT_TRUE(ret.isOk());
2418 }
2419}
2420
2421// Verify camera offline session behavior
2422TEST_P(CameraAidlTest, switchToOffline) {
2423 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
2424 AvailableStream threshold = {kMaxStillWidth, kMaxStillHeight,
2425 static_cast<int32_t>(PixelFormat::BLOB)};
2426 int64_t bufferId = 1;
2427 int32_t frameNumber = 1;
2428 CameraMetadata settings;
2429
2430 for (const auto& name : cameraDeviceNames) {
2431 CameraMetadata meta;
2432 {
2433 std::shared_ptr<ICameraDevice> unusedDevice;
2434 openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/,
2435 &unusedDevice);
2436 camera_metadata_t* staticMetaBuffer = clone_camera_metadata(
2437 reinterpret_cast<camera_metadata_t*>(meta.metadata.data()));
2438 ::android::hardware::camera::common::V1_0::helper::CameraMetadata staticMeta(
2439 staticMetaBuffer);
2440
2441 if (isOfflineSessionSupported(staticMetaBuffer) != Status::OK) {
2442 ndk::ScopedAStatus ret = mSession->close();
2443 mSession = nullptr;
2444 ASSERT_TRUE(ret.isOk());
2445 continue;
2446 }
2447 ndk::ScopedAStatus ret = mSession->close();
2448 mSession = nullptr;
2449 ASSERT_TRUE(ret.isOk());
2450 }
2451
2452 bool supportsPartialResults = false;
2453 int32_t partialResultCount = 0;
2454 Stream stream;
2455 std::vector<HalStream> halStreams;
2456 std::shared_ptr<DeviceCb> cb;
2457 int32_t jpegBufferSize;
Jayant Chowdhary4869ae72023-12-18 05:36:14 +00002458 std::set<int32_t> halBufManagedStreamIds;
Avichal Rakesh362242f2022-02-08 12:40:53 -08002459 configureOfflineStillStream(name, mProvider, &threshold, &mSession /*out*/, &stream /*out*/,
2460 &halStreams /*out*/, &supportsPartialResults /*out*/,
2461 &partialResultCount /*out*/, &cb /*out*/,
Jayant Chowdhary4869ae72023-12-18 05:36:14 +00002462 &jpegBufferSize /*out*/, &halBufManagedStreamIds /*out*/);
Avichal Rakesh362242f2022-02-08 12:40:53 -08002463
2464 auto ret = mSession->constructDefaultRequestSettings(RequestTemplate::STILL_CAPTURE,
2465 &settings);
2466 ASSERT_TRUE(ret.isOk());
2467
2468 ::aidl::android::hardware::common::fmq::MQDescriptor<
2469 int8_t, aidl::android::hardware::common::fmq::SynchronizedReadWrite>
2470 descriptor;
2471
2472 ndk::ScopedAStatus resultQueueRet = mSession->getCaptureResultMetadataQueue(&descriptor);
2473 ASSERT_TRUE(resultQueueRet.isOk());
2474 std::shared_ptr<ResultMetadataQueue> resultQueue =
2475 std::make_shared<ResultMetadataQueue>(descriptor);
2476 if (!resultQueue->isValid() || resultQueue->availableToWrite() <= 0) {
2477 ALOGE("%s: HAL returns empty result metadata fmq, not use it", __func__);
2478 resultQueue = nullptr;
2479 // Don't use the queue onwards.
2480 }
2481
2482 ::android::hardware::camera::common::V1_0::helper::CameraMetadata requestMeta;
2483
2484 std::vector<buffer_handle_t> buffers(kBurstFrameCount);
2485 std::vector<std::shared_ptr<InFlightRequest>> inflightReqs(kBurstFrameCount);
2486 std::vector<CameraMetadata> requestSettings(kBurstFrameCount);
2487
2488 std::vector<CaptureRequest> requests(kBurstFrameCount);
2489
2490 HalStream halStream = halStreams[0];
2491 for (uint32_t i = 0; i < kBurstFrameCount; i++) {
2492 CaptureRequest& request = requests[i];
2493 std::vector<StreamBuffer>& outputBuffers = request.outputBuffers;
2494 outputBuffers.resize(1);
2495 StreamBuffer& outputBuffer = outputBuffers[0];
2496
2497 std::unique_lock<std::mutex> l(mLock);
Jayant Chowdhary4869ae72023-12-18 05:36:14 +00002498 if (contains(halBufManagedStreamIds, halStream.id)) {
Avichal Rakesh362242f2022-02-08 12:40:53 -08002499 outputBuffer = {halStream.id, 0, NativeHandle(), BufferStatus::OK, NativeHandle(),
2500 NativeHandle()};
2501 } else {
2502 // jpeg buffer (w,h) = (blobLen, 1)
2503 allocateGraphicBuffer(jpegBufferSize, /*height*/ 1,
2504 android_convertGralloc1To0Usage(
2505 static_cast<uint64_t>(halStream.producerUsage),
2506 static_cast<uint64_t>(halStream.consumerUsage)),
2507 halStream.overrideFormat, &buffers[i]);
2508 outputBuffer = {halStream.id, bufferId + i, ::android::makeToAidl(buffers[i]),
2509 BufferStatus::OK, NativeHandle(), NativeHandle()};
2510 }
2511
2512 requestMeta.clear();
2513 requestMeta.append(reinterpret_cast<camera_metadata_t*>(settings.metadata.data()));
2514
2515 camera_metadata_t* metaBuffer = requestMeta.release();
2516 uint8_t* rawMetaBuffer = reinterpret_cast<uint8_t*>(metaBuffer);
2517 requestSettings[i].metadata = std::vector(
2518 rawMetaBuffer, rawMetaBuffer + get_camera_metadata_size(metaBuffer));
2519 overrideRotateAndCrop(&requestSettings[i]);
2520
2521 request.frameNumber = frameNumber + i;
2522 request.fmqSettingsSize = 0;
2523 request.settings = requestSettings[i];
2524 request.inputBuffer = {/*streamId*/ -1,
2525 /*bufferId*/ 0, NativeHandle(),
2526 BufferStatus::ERROR, NativeHandle(),
2527 NativeHandle()};
2528
2529 inflightReqs[i] = std::make_shared<InFlightRequest>(1, false, supportsPartialResults,
2530 partialResultCount, resultQueue);
2531 mInflightMap[frameNumber + i] = inflightReqs[i];
2532 }
2533
2534 int32_t numRequestProcessed = 0;
2535 std::vector<BufferCache> cachesToRemove;
2536
2537 ndk::ScopedAStatus returnStatus =
2538 mSession->processCaptureRequest(requests, cachesToRemove, &numRequestProcessed);
2539 ASSERT_TRUE(returnStatus.isOk());
2540 ASSERT_EQ(numRequestProcessed, kBurstFrameCount);
2541
2542 std::vector<int32_t> offlineStreamIds = {halStream.id};
2543 CameraOfflineSessionInfo offlineSessionInfo;
2544 std::shared_ptr<ICameraOfflineSession> offlineSession;
2545 returnStatus =
2546 mSession->switchToOffline(offlineStreamIds, &offlineSessionInfo, &offlineSession);
2547
2548 if (!halStreams[0].supportOffline) {
2549 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT),
2550 returnStatus.getServiceSpecificError());
2551 ret = mSession->close();
2552 mSession = nullptr;
2553 ASSERT_TRUE(ret.isOk());
2554 continue;
2555 }
2556
2557 ASSERT_TRUE(returnStatus.isOk());
2558 // Hal might be unable to find any requests qualified for offline mode.
2559 if (offlineSession == nullptr) {
2560 ret = mSession->close();
2561 mSession = nullptr;
2562 ASSERT_TRUE(ret.isOk());
2563 continue;
2564 }
2565
2566 ASSERT_EQ(offlineSessionInfo.offlineStreams.size(), 1u);
2567 ASSERT_EQ(offlineSessionInfo.offlineStreams[0].id, halStream.id);
2568 ASSERT_NE(offlineSessionInfo.offlineRequests.size(), 0u);
2569
2570 // close device session to make sure offline session does not rely on it
2571 ret = mSession->close();
2572 mSession = nullptr;
2573 ASSERT_TRUE(ret.isOk());
2574
2575 ::aidl::android::hardware::common::fmq::MQDescriptor<
2576 int8_t, aidl::android::hardware::common::fmq::SynchronizedReadWrite>
2577 offlineResultDescriptor;
2578
2579 auto offlineResultQueueRet =
2580 offlineSession->getCaptureResultMetadataQueue(&offlineResultDescriptor);
2581 std::shared_ptr<ResultMetadataQueue> offlineResultQueue =
2582 std::make_shared<ResultMetadataQueue>(descriptor);
2583 if (!offlineResultQueue->isValid() || offlineResultQueue->availableToWrite() <= 0) {
2584 ALOGE("%s: offline session returns empty result metadata fmq, not use it", __func__);
2585 offlineResultQueue = nullptr;
2586 // Don't use the queue onwards.
2587 }
2588 ASSERT_TRUE(offlineResultQueueRet.isOk());
2589
2590 updateInflightResultQueue(offlineResultQueue);
2591
2592 ret = offlineSession->setCallback(cb);
2593 ASSERT_TRUE(ret.isOk());
2594
2595 for (size_t i = 0; i < kBurstFrameCount; i++) {
2596 std::unique_lock<std::mutex> l(mLock);
2597 while (!inflightReqs[i]->errorCodeValid && ((0 < inflightReqs[i]->numBuffersLeft) ||
2598 (!inflightReqs[i]->haveResultMetadata))) {
2599 auto timeout = std::chrono::system_clock::now() +
2600 std::chrono::seconds(kStreamBufferTimeoutSec);
2601 ASSERT_NE(std::cv_status::timeout, mResultCondition.wait_until(l, timeout));
2602 }
2603
2604 ASSERT_FALSE(inflightReqs[i]->errorCodeValid);
2605 ASSERT_NE(inflightReqs[i]->resultOutputBuffers.size(), 0u);
2606 ASSERT_EQ(stream.id, inflightReqs[i]->resultOutputBuffers[0].buffer.streamId);
2607 ASSERT_FALSE(inflightReqs[i]->collectedResult.isEmpty());
2608 }
2609
2610 ret = offlineSession->close();
2611 ASSERT_TRUE(ret.isOk());
2612 }
2613}
2614
2615// Check whether an invalid capture request with missing output buffers
2616// will be reported correctly.
2617TEST_P(CameraAidlTest, processCaptureRequestInvalidBuffer) {
2618 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
2619 std::vector<AvailableStream> outputBlobStreams;
2620 AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
2621 static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
2622 int32_t frameNumber = 1;
2623 CameraMetadata settings;
2624
2625 for (const auto& name : cameraDeviceNames) {
2626 Stream previewStream;
2627 std::vector<HalStream> halStreams;
2628 std::shared_ptr<DeviceCb> cb;
2629 bool supportsPartialResults = false;
2630 bool useHalBufManager = false;
2631 int32_t partialResultCount = 0;
2632 configurePreviewStream(name, mProvider, &previewThreshold, &mSession /*out*/,
2633 &previewStream /*out*/, &halStreams /*out*/,
2634 &supportsPartialResults /*out*/, &partialResultCount /*out*/,
2635 &useHalBufManager /*out*/, &cb /*out*/);
2636
2637 RequestTemplate reqTemplate = RequestTemplate::PREVIEW;
2638 ndk::ScopedAStatus ret = mSession->constructDefaultRequestSettings(reqTemplate, &settings);
2639 ASSERT_TRUE(ret.isOk());
2640 overrideRotateAndCrop(&settings);
2641
2642 std::vector<CaptureRequest> requests(1);
2643 CaptureRequest& request = requests[0];
2644 std::vector<StreamBuffer>& outputBuffers = request.outputBuffers;
2645 outputBuffers.resize(1);
2646 // Empty output buffer
2647 outputBuffers[0] = {
2648 -1, 0, NativeHandle(), BufferStatus::ERROR, NativeHandle(), NativeHandle()};
2649
2650 request.inputBuffer = {
2651 -1, 0, NativeHandle(), BufferStatus::ERROR, NativeHandle(), NativeHandle()};
2652 request.frameNumber = frameNumber;
2653 request.fmqSettingsSize = 0;
2654 request.settings = settings;
2655
2656 // Output buffers are missing, we should fail here
2657 int32_t numRequestProcessed = 0;
2658 std::vector<BufferCache> cachesToRemove;
2659 ret = mSession->processCaptureRequest(requests, cachesToRemove, &numRequestProcessed);
2660 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT), ret.getServiceSpecificError());
2661 ASSERT_EQ(numRequestProcessed, 0u);
2662
2663 ret = mSession->close();
2664 mSession = nullptr;
2665 ASSERT_TRUE(ret.isOk());
2666 }
2667}
2668
2669// Generate, trigger and flush a preview request
2670TEST_P(CameraAidlTest, flushPreviewRequest) {
2671 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
2672 std::vector<AvailableStream> outputPreviewStreams;
2673 AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
2674 static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
2675 int64_t bufferId = 1;
2676 int32_t frameNumber = 1;
2677 CameraMetadata settings;
2678
2679 for (const auto& name : cameraDeviceNames) {
2680 Stream previewStream;
2681 std::vector<HalStream> halStreams;
2682 std::shared_ptr<DeviceCb> cb;
2683 bool supportsPartialResults = false;
2684 bool useHalBufManager = false;
2685 int32_t partialResultCount = 0;
2686
2687 configurePreviewStream(name, mProvider, &previewThreshold, &mSession /*out*/,
2688 &previewStream /*out*/, &halStreams /*out*/,
2689 &supportsPartialResults /*out*/, &partialResultCount /*out*/,
2690 &useHalBufManager /*out*/, &cb /*out*/);
2691
2692 ASSERT_NE(mSession, nullptr);
2693 ASSERT_NE(cb, nullptr);
2694 ASSERT_FALSE(halStreams.empty());
2695
2696 ::aidl::android::hardware::common::fmq::MQDescriptor<
2697 int8_t, aidl::android::hardware::common::fmq::SynchronizedReadWrite>
2698 descriptor;
2699
2700 auto resultQueueRet = mSession->getCaptureResultMetadataQueue(&descriptor);
2701 std::shared_ptr<ResultMetadataQueue> resultQueue =
2702 std::make_shared<ResultMetadataQueue>(descriptor);
2703 ASSERT_TRUE(resultQueueRet.isOk());
2704 if (!resultQueue->isValid() || resultQueue->availableToWrite() <= 0) {
2705 ALOGE("%s: HAL returns empty result metadata fmq, not use it", __func__);
2706 resultQueue = nullptr;
2707 // Don't use the queue onwards.
2708 }
2709
2710 std::shared_ptr<InFlightRequest> inflightReq = std::make_shared<InFlightRequest>(
2711 1, false, supportsPartialResults, partialResultCount, resultQueue);
2712 RequestTemplate reqTemplate = RequestTemplate::PREVIEW;
2713
2714 ndk::ScopedAStatus ret = mSession->constructDefaultRequestSettings(reqTemplate, &settings);
2715 ASSERT_TRUE(ret.isOk());
2716 overrideRotateAndCrop(&settings);
2717
2718 buffer_handle_t buffer_handle;
2719 std::vector<CaptureRequest> requests(1);
2720 CaptureRequest& request = requests[0];
2721 std::vector<StreamBuffer>& outputBuffers = request.outputBuffers;
2722 outputBuffers.resize(1);
2723 StreamBuffer& outputBuffer = outputBuffers[0];
2724 if (useHalBufManager) {
2725 bufferId = 0;
2726 outputBuffer = {halStreams[0].id, bufferId, NativeHandle(),
2727 BufferStatus::OK, NativeHandle(), NativeHandle()};
2728 } else {
2729 allocateGraphicBuffer(previewStream.width, previewStream.height,
2730 android_convertGralloc1To0Usage(
2731 static_cast<uint64_t>(halStreams[0].producerUsage),
2732 static_cast<uint64_t>(halStreams[0].consumerUsage)),
2733 halStreams[0].overrideFormat, &buffer_handle);
2734 outputBuffer = {halStreams[0].id, bufferId, ::android::makeToAidl(buffer_handle),
2735 BufferStatus::OK, NativeHandle(), NativeHandle()};
2736 }
2737
2738 request.frameNumber = frameNumber;
2739 request.fmqSettingsSize = 0;
2740 request.settings = settings;
2741 request.inputBuffer = {
2742 -1, 0, NativeHandle(), BufferStatus::ERROR, NativeHandle(), NativeHandle()};
2743
2744 {
2745 std::unique_lock<std::mutex> l(mLock);
2746 mInflightMap.clear();
2747 mInflightMap[frameNumber] = inflightReq;
2748 }
2749
2750 int32_t numRequestProcessed = 0;
2751 std::vector<BufferCache> cachesToRemove;
2752 ret = mSession->processCaptureRequest(requests, cachesToRemove, &numRequestProcessed);
2753 ASSERT_TRUE(ret.isOk());
2754 ASSERT_EQ(numRequestProcessed, 1u);
2755
2756 // Flush before waiting for request to complete.
2757 ndk::ScopedAStatus returnStatus = mSession->flush();
2758 ASSERT_TRUE(returnStatus.isOk());
2759
2760 {
2761 std::unique_lock<std::mutex> l(mLock);
2762 while (!inflightReq->errorCodeValid &&
2763 ((0 < inflightReq->numBuffersLeft) || (!inflightReq->haveResultMetadata))) {
2764 auto timeout = std::chrono::system_clock::now() +
2765 std::chrono::seconds(kStreamBufferTimeoutSec);
2766 ASSERT_NE(std::cv_status::timeout, mResultCondition.wait_until(l, timeout));
2767 }
2768
2769 if (!inflightReq->errorCodeValid) {
2770 ASSERT_NE(inflightReq->resultOutputBuffers.size(), 0u);
2771 ASSERT_EQ(previewStream.id, inflightReq->resultOutputBuffers[0].buffer.streamId);
2772 } else {
2773 switch (inflightReq->errorCode) {
2774 case ErrorCode::ERROR_REQUEST:
2775 case ErrorCode::ERROR_RESULT:
2776 case ErrorCode::ERROR_BUFFER:
2777 // Expected
2778 break;
2779 case ErrorCode::ERROR_DEVICE:
2780 default:
2781 FAIL() << "Unexpected error:"
2782 << static_cast<uint32_t>(inflightReq->errorCode);
2783 }
2784 }
2785 }
2786
2787 if (useHalBufManager) {
2788 verifyBuffersReturned(mSession, previewStream.id, cb);
2789 }
2790
2791 ret = mSession->close();
2792 mSession = nullptr;
2793 ASSERT_TRUE(ret.isOk());
2794 }
2795}
2796
2797// Verify that camera flushes correctly without any pending requests.
2798TEST_P(CameraAidlTest, flushEmpty) {
2799 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
2800 std::vector<AvailableStream> outputPreviewStreams;
2801 AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
2802 static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
2803
2804 for (const auto& name : cameraDeviceNames) {
2805 Stream previewStream;
2806 std::vector<HalStream> halStreams;
2807 std::shared_ptr<DeviceCb> cb;
2808 bool supportsPartialResults = false;
2809 bool useHalBufManager = false;
2810
2811 int32_t partialResultCount = 0;
2812 configurePreviewStream(name, mProvider, &previewThreshold, &mSession /*out*/,
2813 &previewStream /*out*/, &halStreams /*out*/,
2814 &supportsPartialResults /*out*/, &partialResultCount /*out*/,
2815 &useHalBufManager /*out*/, &cb /*out*/);
2816
2817 ndk::ScopedAStatus returnStatus = mSession->flush();
2818 ASSERT_TRUE(returnStatus.isOk());
2819
2820 {
2821 std::unique_lock<std::mutex> l(mLock);
2822 auto timeout = std::chrono::system_clock::now() +
2823 std::chrono::milliseconds(kEmptyFlushTimeoutMSec);
2824 ASSERT_EQ(std::cv_status::timeout, mResultCondition.wait_until(l, timeout));
2825 }
2826
2827 ndk::ScopedAStatus ret = mSession->close();
2828 mSession = nullptr;
2829 ASSERT_TRUE(ret.isOk());
2830 }
2831}
2832
2833// Test camera provider notify method
2834TEST_P(CameraAidlTest, providerDeviceStateNotification) {
2835 notifyDeviceState(ICameraProvider::DEVICE_STATE_BACK_COVERED);
2836 notifyDeviceState(ICameraProvider::DEVICE_STATE_NORMAL);
2837}
2838
2839// Verify that all supported stream formats and sizes can be configured
2840// successfully for injection camera.
2841TEST_P(CameraAidlTest, configureInjectionStreamsAvailableOutputs) {
2842 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
2843 std::vector<AvailableStream> outputStreams;
2844
2845 for (const auto& name : cameraDeviceNames) {
2846 CameraMetadata metadata;
2847
2848 std::shared_ptr<ICameraInjectionSession> injectionSession;
2849 std::shared_ptr<ICameraDevice> unusedDevice;
2850 openEmptyInjectionSession(name, mProvider, &injectionSession /*out*/, &metadata /*out*/,
2851 &unusedDevice /*out*/);
2852 if (injectionSession == nullptr) {
2853 continue;
2854 }
2855
2856 camera_metadata_t* staticMetaBuffer =
2857 reinterpret_cast<camera_metadata_t*>(metadata.metadata.data());
2858 CameraMetadata chars;
2859 chars.metadata = metadata.metadata;
2860
2861 outputStreams.clear();
2862 ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMetaBuffer, outputStreams));
2863 ASSERT_NE(0u, outputStreams.size());
2864
2865 int32_t jpegBufferSize = 0;
2866 ASSERT_EQ(Status::OK, getJpegBufferSize(staticMetaBuffer, &jpegBufferSize));
2867 ASSERT_NE(0u, jpegBufferSize);
2868
2869 int32_t streamId = 0;
2870 int32_t streamConfigCounter = 0;
2871 for (auto& it : outputStreams) {
2872 Dataspace dataspace = getDataspace(static_cast<PixelFormat>(it.format));
2873 Stream stream = {streamId,
2874 StreamType::OUTPUT,
2875 it.width,
2876 it.height,
2877 static_cast<PixelFormat>(it.format),
2878 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
2879 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
2880 dataspace,
2881 StreamRotation::ROTATION_0,
2882 std::string(),
2883 jpegBufferSize,
2884 0,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00002885 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
2886 RequestAvailableDynamicRangeProfilesMap::
2887 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08002888
2889 std::vector<Stream> streams = {stream};
2890 StreamConfiguration config;
2891 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
2892 jpegBufferSize);
2893
2894 config.streamConfigCounter = streamConfigCounter++;
2895 ndk::ScopedAStatus s = injectionSession->configureInjectionStreams(config, chars);
2896 ASSERT_TRUE(s.isOk());
2897 streamId++;
2898 }
2899
2900 std::shared_ptr<ICameraDeviceSession> session;
2901 ndk::ScopedAStatus ret = injectionSession->getCameraDeviceSession(&session);
2902 ASSERT_TRUE(ret.isOk());
2903 ASSERT_NE(session, nullptr);
2904 ret = session->close();
2905 ASSERT_TRUE(ret.isOk());
2906 }
2907}
2908
2909// Check for correct handling of invalid/incorrect configuration parameters for injection camera.
2910TEST_P(CameraAidlTest, configureInjectionStreamsInvalidOutputs) {
2911 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
2912 std::vector<AvailableStream> outputStreams;
2913
2914 for (const auto& name : cameraDeviceNames) {
2915 CameraMetadata metadata;
2916 std::shared_ptr<ICameraInjectionSession> injectionSession;
2917 std::shared_ptr<ICameraDevice> unusedDevice;
2918 openEmptyInjectionSession(name, mProvider, &injectionSession /*out*/, &metadata /*out*/,
2919 &unusedDevice);
2920 if (injectionSession == nullptr) {
2921 continue;
2922 }
2923
2924 camera_metadata_t* staticMetaBuffer =
2925 reinterpret_cast<camera_metadata_t*>(metadata.metadata.data());
2926 std::shared_ptr<ICameraDeviceSession> session;
2927 ndk::ScopedAStatus ret = injectionSession->getCameraDeviceSession(&session);
2928 ASSERT_TRUE(ret.isOk());
2929 ASSERT_NE(session, nullptr);
2930
2931 CameraMetadata chars;
2932 chars.metadata = metadata.metadata;
2933
2934 outputStreams.clear();
2935 ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMetaBuffer, outputStreams));
2936 ASSERT_NE(0u, outputStreams.size());
2937
2938 int32_t jpegBufferSize = 0;
2939 ASSERT_EQ(Status::OK, getJpegBufferSize(staticMetaBuffer, &jpegBufferSize));
2940 ASSERT_NE(0u, jpegBufferSize);
2941
2942 int32_t streamId = 0;
2943 Stream stream = {streamId++,
2944 StreamType::OUTPUT,
2945 0,
2946 0,
2947 static_cast<PixelFormat>(outputStreams[0].format),
2948 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
2949 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
2950 Dataspace::UNKNOWN,
2951 StreamRotation::ROTATION_0,
2952 std::string(),
2953 jpegBufferSize,
2954 0,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00002955 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
2956 RequestAvailableDynamicRangeProfilesMap::
2957 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08002958
2959 int32_t streamConfigCounter = 0;
2960 std::vector<Stream> streams = {stream};
2961 StreamConfiguration config;
2962 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
2963 jpegBufferSize);
2964
2965 config.streamConfigCounter = streamConfigCounter++;
2966 ndk::ScopedAStatus s = injectionSession->configureInjectionStreams(config, chars);
2967 ASSERT_TRUE(
2968 (static_cast<int32_t>(Status::ILLEGAL_ARGUMENT) == s.getServiceSpecificError()) ||
2969 (static_cast<int32_t>(Status::INTERNAL_ERROR) == s.getServiceSpecificError()));
2970
2971 stream = {streamId++,
2972 StreamType::OUTPUT,
2973 INT32_MAX,
2974 INT32_MAX,
2975 static_cast<PixelFormat>(outputStreams[0].format),
2976 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
2977 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
2978 Dataspace::UNKNOWN,
2979 StreamRotation::ROTATION_0,
2980 std::string(),
2981 jpegBufferSize,
2982 0,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00002983 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
2984 RequestAvailableDynamicRangeProfilesMap::
2985 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
2986
Avichal Rakesh362242f2022-02-08 12:40:53 -08002987 streams[0] = stream;
2988 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
2989 jpegBufferSize);
2990 config.streamConfigCounter = streamConfigCounter++;
2991 s = injectionSession->configureInjectionStreams(config, chars);
2992 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT), s.getServiceSpecificError());
2993
2994 for (auto& it : outputStreams) {
2995 stream = {streamId++,
2996 StreamType::OUTPUT,
2997 it.width,
2998 it.height,
2999 static_cast<PixelFormat>(INT32_MAX),
3000 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
3001 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
3002 Dataspace::UNKNOWN,
3003 StreamRotation::ROTATION_0,
3004 std::string(),
3005 jpegBufferSize,
3006 0,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00003007 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
3008 RequestAvailableDynamicRangeProfilesMap::
3009 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08003010 streams[0] = stream;
3011 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
3012 jpegBufferSize);
3013 config.streamConfigCounter = streamConfigCounter++;
3014 s = injectionSession->configureInjectionStreams(config, chars);
3015 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT), s.getServiceSpecificError());
3016
3017 stream = {streamId++,
3018 StreamType::OUTPUT,
3019 it.width,
3020 it.height,
3021 static_cast<PixelFormat>(it.format),
3022 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
3023 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
3024 Dataspace::UNKNOWN,
3025 static_cast<StreamRotation>(INT32_MAX),
3026 std::string(),
3027 jpegBufferSize,
3028 0,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00003029 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
3030 RequestAvailableDynamicRangeProfilesMap::
3031 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08003032 streams[0] = stream;
3033 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
3034 jpegBufferSize);
3035 config.streamConfigCounter = streamConfigCounter++;
3036 s = injectionSession->configureInjectionStreams(config, chars);
3037 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT), s.getServiceSpecificError());
3038 }
3039
3040 ret = session->close();
3041 ASSERT_TRUE(ret.isOk());
3042 }
3043}
3044
3045// Check whether session parameters are supported for injection camera. If Hal support for them
3046// exist, then try to configure a preview stream using them.
3047TEST_P(CameraAidlTest, configureInjectionStreamsWithSessionParameters) {
3048 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
3049 std::vector<AvailableStream> outputPreviewStreams;
3050 AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
3051 static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
3052
3053 for (const auto& name : cameraDeviceNames) {
3054 CameraMetadata metadata;
3055 std::shared_ptr<ICameraInjectionSession> injectionSession;
3056 std::shared_ptr<ICameraDevice> unusedDevice;
3057 openEmptyInjectionSession(name, mProvider, &injectionSession /*out*/, &metadata /*out*/,
3058 &unusedDevice /*out*/);
3059 if (injectionSession == nullptr) {
3060 continue;
3061 }
3062
3063 std::shared_ptr<ICameraDeviceSession> session;
3064 ndk::ScopedAStatus ret = injectionSession->getCameraDeviceSession(&session);
3065 ASSERT_TRUE(ret.isOk());
3066 ASSERT_NE(session, nullptr);
3067
3068 camera_metadata_t* staticMetaBuffer =
3069 reinterpret_cast<camera_metadata_t*>(metadata.metadata.data());
3070 CameraMetadata chars;
3071 chars.metadata = metadata.metadata;
3072
3073 std::unordered_set<int32_t> availableSessionKeys;
3074 Status rc = getSupportedKeys(staticMetaBuffer, ANDROID_REQUEST_AVAILABLE_SESSION_KEYS,
3075 &availableSessionKeys);
3076 ASSERT_EQ(Status::OK, rc);
3077 if (availableSessionKeys.empty()) {
3078 ret = session->close();
3079 ASSERT_TRUE(ret.isOk());
3080 continue;
3081 }
3082
3083 android::hardware::camera::common::V1_0::helper::CameraMetadata previewRequestSettings;
3084 android::hardware::camera::common::V1_0::helper::CameraMetadata sessionParams,
3085 modifiedSessionParams;
3086 constructFilteredSettings(session, availableSessionKeys, RequestTemplate::PREVIEW,
3087 &previewRequestSettings, &sessionParams);
3088 if (sessionParams.isEmpty()) {
3089 ret = session->close();
3090 ASSERT_TRUE(ret.isOk());
3091 continue;
3092 }
3093
3094 outputPreviewStreams.clear();
3095
3096 ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMetaBuffer, outputPreviewStreams,
3097 &previewThreshold));
3098 ASSERT_NE(0u, outputPreviewStreams.size());
3099
3100 Stream previewStream = {
3101 0,
3102 StreamType::OUTPUT,
3103 outputPreviewStreams[0].width,
3104 outputPreviewStreams[0].height,
3105 static_cast<PixelFormat>(outputPreviewStreams[0].format),
3106 static_cast<::aidl::android::hardware::graphics::common::BufferUsage>(
3107 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
3108 Dataspace::UNKNOWN,
3109 StreamRotation::ROTATION_0,
3110 std::string(),
3111 0,
3112 -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00003113 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
3114 RequestAvailableDynamicRangeProfilesMap::
3115 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08003116 std::vector<Stream> streams = {previewStream};
3117 StreamConfiguration config;
3118 config.streams = streams;
3119 config.operationMode = StreamConfigurationMode::NORMAL_MODE;
3120
3121 modifiedSessionParams = sessionParams;
3122 camera_metadata_t* sessionParamsBuffer = sessionParams.release();
3123 uint8_t* rawSessionParamsBuffer = reinterpret_cast<uint8_t*>(sessionParamsBuffer);
3124 config.sessionParams.metadata =
3125 std::vector(rawSessionParamsBuffer,
3126 rawSessionParamsBuffer + get_camera_metadata_size(sessionParamsBuffer));
3127
3128 config.streamConfigCounter = 0;
3129 config.streamConfigCounter = 0;
3130 config.multiResolutionInputImage = false;
3131
3132 ndk::ScopedAStatus s = injectionSession->configureInjectionStreams(config, chars);
3133 ASSERT_TRUE(s.isOk());
3134
3135 sessionParams.acquire(sessionParamsBuffer);
3136 free_camera_metadata(staticMetaBuffer);
3137 ret = session->close();
3138 ASSERT_TRUE(ret.isOk());
3139 }
3140}
3141
Jayant Chowdharyde1909e2022-11-23 17:18:38 +00003142TEST_P(CameraAidlTest, configureStreamsUseCasesCroppedRaw) {
3143 AvailableStream rawStreamThreshold =
3144 {INT_MAX, INT_MAX, static_cast<int32_t>(PixelFormat::RAW16)};
3145 configureStreamUseCaseInternal(rawStreamThreshold);
3146}
3147
Avichal Rakesh362242f2022-02-08 12:40:53 -08003148// Verify that valid stream use cases can be configured successfully, and invalid use cases
3149// fail stream configuration.
3150TEST_P(CameraAidlTest, configureStreamsUseCases) {
Jayant Chowdharyde1909e2022-11-23 17:18:38 +00003151 AvailableStream previewStreamThreshold =
3152 {kMaxPreviewWidth, kMaxPreviewHeight, static_cast<int32_t>(PixelFormat::YCBCR_420_888)};
3153 configureStreamUseCaseInternal(previewStreamThreshold);
Avichal Rakesh362242f2022-02-08 12:40:53 -08003154}
3155
Austin Borger0918fc82023-03-21 18:48:18 -07003156// Validate the integrity of stream configuration metadata
3157TEST_P(CameraAidlTest, validateStreamConfigurations) {
3158 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
3159 std::vector<AvailableStream> outputStreams;
3160
3161 const int32_t scalerSizesTag = ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS;
3162 const int32_t scalerMinFrameDurationsTag = ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS;
3163 const int32_t scalerStallDurationsTag = ANDROID_SCALER_AVAILABLE_STALL_DURATIONS;
3164
3165 for (const auto& name : cameraDeviceNames) {
3166 CameraMetadata meta;
3167 std::shared_ptr<ICameraDevice> cameraDevice;
3168
3169 openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/,
3170 &cameraDevice /*out*/);
3171 camera_metadata_t* staticMeta = reinterpret_cast<camera_metadata_t*>(meta.metadata.data());
3172
3173 if (is10BitDynamicRangeCapable(staticMeta)) {
3174 std::vector<std::tuple<size_t, size_t>> supportedP010Sizes, supportedBlobSizes;
3175
3176 getSupportedSizes(staticMeta, scalerSizesTag, HAL_PIXEL_FORMAT_BLOB,
3177 &supportedBlobSizes);
3178 getSupportedSizes(staticMeta, scalerSizesTag, HAL_PIXEL_FORMAT_YCBCR_P010,
3179 &supportedP010Sizes);
3180 ASSERT_FALSE(supportedP010Sizes.empty());
3181
3182 std::vector<int64_t> blobMinDurations, blobStallDurations;
3183 getSupportedDurations(staticMeta, scalerMinFrameDurationsTag, HAL_PIXEL_FORMAT_BLOB,
3184 supportedP010Sizes, &blobMinDurations);
3185 getSupportedDurations(staticMeta, scalerStallDurationsTag, HAL_PIXEL_FORMAT_BLOB,
3186 supportedP010Sizes, &blobStallDurations);
3187 ASSERT_FALSE(blobStallDurations.empty());
3188 ASSERT_FALSE(blobMinDurations.empty());
3189 ASSERT_EQ(supportedP010Sizes.size(), blobMinDurations.size());
3190 ASSERT_EQ(blobMinDurations.size(), blobStallDurations.size());
3191 }
3192
Austin Borger8e9ac022023-05-04 11:17:26 -07003193 // TODO (b/280887191): Validate other aspects of stream configuration metadata...
3194
3195 ndk::ScopedAStatus ret = mSession->close();
3196 mSession = nullptr;
3197 ASSERT_TRUE(ret.isOk());
Austin Borger0918fc82023-03-21 18:48:18 -07003198 }
3199}
3200
Avichal Rakesh362242f2022-02-08 12:40:53 -08003201GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(CameraAidlTest);
3202INSTANTIATE_TEST_SUITE_P(
3203 PerInstance, CameraAidlTest,
3204 testing::ValuesIn(android::getAidlHalInstanceNames(ICameraProvider::descriptor)),
Jayant Chowdharyde1909e2022-11-23 17:18:38 +00003205 android::hardware::PrintInstanceNameToString);