blob: 31e8014a841e0a4fd6a38cd8b0920979acd4e681 [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);
Rucha Katakwar0cea5232024-04-10 14:28:08 -0700180 ret = mSession->close();
181 mSession = nullptr;
182 ASSERT_TRUE(ret.isOk());
Rucha Katakward08a0152023-10-13 15:47:58 -0700183 }
184 } else {
185 ALOGI("validateManualFlashStrengthControlKeys: Test skipped.\n");
186 GTEST_SKIP();
187 }
188}
189
Avichal Rakesh362242f2022-02-08 12:40:53 -0800190TEST_P(CameraAidlTest, systemCameraTest) {
191 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
192 std::map<std::string, std::vector<SystemCameraKind>> hiddenPhysicalIdToLogicalMap;
193 for (const auto& name : cameraDeviceNames) {
194 std::shared_ptr<ICameraDevice> device;
Avichal Rakeshfbcf7ea2022-03-09 01:00:34 +0000195 ALOGI("systemCameraTest: Testing camera device %s", name.c_str());
Avichal Rakesh362242f2022-02-08 12:40:53 -0800196 ndk::ScopedAStatus ret = mProvider->getCameraDeviceInterface(name, &device);
197 ASSERT_TRUE(ret.isOk());
198 ASSERT_NE(device, nullptr);
199
200 CameraMetadata cameraCharacteristics;
201 ret = device->getCameraCharacteristics(&cameraCharacteristics);
202 ASSERT_TRUE(ret.isOk());
203
204 const camera_metadata_t* staticMeta =
205 reinterpret_cast<const camera_metadata_t*>(cameraCharacteristics.metadata.data());
206 Status rc = isLogicalMultiCamera(staticMeta);
207 if (rc == Status::OPERATION_NOT_SUPPORTED) {
208 return;
209 }
210
211 ASSERT_EQ(rc, Status::OK);
212 std::unordered_set<std::string> physicalIds;
213 ASSERT_EQ(getPhysicalCameraIds(staticMeta, &physicalIds), Status::OK);
214 SystemCameraKind systemCameraKind = SystemCameraKind::PUBLIC;
215 Status retStatus = getSystemCameraKind(staticMeta, &systemCameraKind);
216 ASSERT_EQ(retStatus, Status::OK);
217
218 for (auto physicalId : physicalIds) {
219 bool isPublicId = false;
220 for (auto& deviceName : cameraDeviceNames) {
221 std::string publicVersion, publicId;
222 ASSERT_TRUE(matchDeviceName(deviceName, mProviderType, &publicVersion, &publicId));
223 if (physicalId == publicId) {
224 isPublicId = true;
225 break;
226 }
227 }
Avichal Rakeshfbcf7ea2022-03-09 01:00:34 +0000228
Avichal Rakesh362242f2022-02-08 12:40:53 -0800229 // For hidden physical cameras, collect their associated logical cameras
230 // and store the system camera kind.
231 if (!isPublicId) {
232 auto it = hiddenPhysicalIdToLogicalMap.find(physicalId);
233 if (it == hiddenPhysicalIdToLogicalMap.end()) {
234 hiddenPhysicalIdToLogicalMap.insert(std::make_pair(
Avichal Rakeshfbcf7ea2022-03-09 01:00:34 +0000235 physicalId, std::vector<SystemCameraKind>({systemCameraKind})));
Avichal Rakesh362242f2022-02-08 12:40:53 -0800236 } else {
237 it->second.push_back(systemCameraKind);
238 }
239 }
240 }
241 }
242
243 // Check that the system camera kind of the logical cameras associated with
244 // each hidden physical camera is the same.
245 for (const auto& it : hiddenPhysicalIdToLogicalMap) {
246 SystemCameraKind neededSystemCameraKind = it.second.front();
247 for (auto foundSystemCamera : it.second) {
248 ASSERT_EQ(neededSystemCameraKind, foundSystemCamera);
249 }
250 }
251}
252
253// Verify that the static camera characteristics can be retrieved
254// successfully.
255TEST_P(CameraAidlTest, getCameraCharacteristics) {
256 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
257
258 for (const auto& name : cameraDeviceNames) {
259 std::shared_ptr<ICameraDevice> device;
260 ALOGI("getCameraCharacteristics: Testing camera device %s", name.c_str());
261 ndk::ScopedAStatus ret = mProvider->getCameraDeviceInterface(name, &device);
262 ALOGI("getCameraDeviceInterface returns: %d:%d", ret.getExceptionCode(),
263 ret.getServiceSpecificError());
264 ASSERT_TRUE(ret.isOk());
265 ASSERT_NE(device, nullptr);
266
267 CameraMetadata chars;
268 ret = device->getCameraCharacteristics(&chars);
269 ASSERT_TRUE(ret.isOk());
270 verifyCameraCharacteristics(chars);
271 verifyMonochromeCharacteristics(chars);
272 verifyRecommendedConfigs(chars);
Kwangkyu Park4b7fd452023-05-12 00:22:22 +0900273 verifyHighSpeedRecordingCharacteristics(name, chars);
Avichal Rakesh362242f2022-02-08 12:40:53 -0800274 verifyLogicalOrUltraHighResCameraMetadata(name, device, chars, cameraDeviceNames);
275
276 ASSERT_TRUE(ret.isOk());
277
278 // getPhysicalCameraCharacteristics will fail for publicly
279 // advertised camera IDs.
280 std::string version, cameraId;
281 ASSERT_TRUE(matchDeviceName(name, mProviderType, &version, &cameraId));
282 CameraMetadata devChars;
283 ret = device->getPhysicalCameraCharacteristics(cameraId, &devChars);
284 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT), ret.getServiceSpecificError());
285 ASSERT_EQ(0, devChars.metadata.size());
286 }
287}
288
Bharatt Kukreja48c35ba2023-12-14 20:55:17 +0000289TEST_P(CameraAidlTest, getSessionCharacteristics) {
290 if (flags::feature_combination_query()) {
291 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
292
293 for (const auto& name : cameraDeviceNames) {
294 std::shared_ptr<ICameraDevice> device;
295 ALOGI("getSessionCharacteristics: Testing camera device %s", name.c_str());
296 ndk::ScopedAStatus ret = mProvider->getCameraDeviceInterface(name, &device);
297 ALOGI("getCameraDeviceInterface returns: %d:%d", ret.getExceptionCode(),
298 ret.getServiceSpecificError());
299 ASSERT_TRUE(ret.isOk());
300 ASSERT_NE(device, nullptr);
301
302 CameraMetadata meta;
303 openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/,
304 &device /*out*/);
305
306 std::vector<AvailableStream> outputStreams;
307 camera_metadata_t* staticMeta =
308 reinterpret_cast<camera_metadata_t*>(meta.metadata.data());
309 outputStreams.clear();
310 ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta, outputStreams));
311 ASSERT_NE(0u, outputStreams.size());
312
313 AvailableStream sampleStream = outputStreams[0];
314
315 int32_t streamId = 0;
316 Stream stream = {streamId,
317 StreamType::OUTPUT,
318 sampleStream.width,
319 sampleStream.height,
320 static_cast<PixelFormat>(sampleStream.format),
321 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
322 GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER),
323 Dataspace::UNKNOWN,
324 StreamRotation::ROTATION_0,
325 std::string(),
326 /*bufferSize*/ 0,
327 /*groupId*/ -1,
328 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
329 RequestAvailableDynamicRangeProfilesMap::
330 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
331
332 std::vector<Stream> streams = {stream};
333 StreamConfiguration config;
334 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config);
335
Bharatt Kukrejaa343d982024-01-11 21:19:41 +0000336 CameraMetadata camera_chars;
337 ret = device->getCameraCharacteristics(&camera_chars);
Bharatt Kukreja48c35ba2023-12-14 20:55:17 +0000338 ASSERT_TRUE(ret.isOk());
Bharatt Kukrejaa343d982024-01-11 21:19:41 +0000339
340 CameraMetadata session_chars;
341 ret = device->getSessionCharacteristics(config, &session_chars);
342 ASSERT_TRUE(ret.isOk());
343 verifySessionCharacteristics(session_chars, camera_chars);
Golden Hsuc6589f92024-04-25 19:13:18 +0800344
345 ret = mSession->close();
346 mSession = nullptr;
347 ASSERT_TRUE(ret.isOk());
Bharatt Kukreja48c35ba2023-12-14 20:55:17 +0000348 }
349 } else {
350 ALOGI("getSessionCharacteristics: Test skipped.\n");
351 GTEST_SKIP();
352 }
353}
354
Avichal Rakesh362242f2022-02-08 12:40:53 -0800355// Verify that the torch strength level can be set and retrieved successfully.
356TEST_P(CameraAidlTest, turnOnTorchWithStrengthLevel) {
357 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
358
359 std::shared_ptr<TorchProviderCb> cb = ndk::SharedRefBase::make<TorchProviderCb>(this);
360 ndk::ScopedAStatus ret = mProvider->setCallback(cb);
361 ASSERT_TRUE(ret.isOk());
362
363 for (const auto& name : cameraDeviceNames) {
364 int32_t defaultLevel;
365 std::shared_ptr<ICameraDevice> device;
366 ALOGI("%s: Testing camera device %s", __FUNCTION__, name.c_str());
367
368 ret = mProvider->getCameraDeviceInterface(name, &device);
369 ASSERT_TRUE(ret.isOk());
370 ASSERT_NE(device, nullptr);
371
372 CameraMetadata chars;
373 ret = device->getCameraCharacteristics(&chars);
374 ASSERT_TRUE(ret.isOk());
375
376 const camera_metadata_t* staticMeta =
377 reinterpret_cast<const camera_metadata_t*>(chars.metadata.data());
378 bool torchStrengthControlSupported = isTorchStrengthControlSupported(staticMeta);
379 camera_metadata_ro_entry entry;
380 int rc = find_camera_metadata_ro_entry(staticMeta,
381 ANDROID_FLASH_INFO_STRENGTH_DEFAULT_LEVEL, &entry);
382 if (torchStrengthControlSupported) {
383 ASSERT_EQ(rc, 0);
384 ASSERT_GT(entry.count, 0);
385 defaultLevel = *entry.data.i32;
386 ALOGI("Default level is:%d", defaultLevel);
387 }
388
389 mTorchStatus = TorchModeStatus::NOT_AVAILABLE;
390 ret = device->turnOnTorchWithStrengthLevel(2);
391 ALOGI("turnOnTorchWithStrengthLevel returns status: %d", ret.getServiceSpecificError());
392 // OPERATION_NOT_SUPPORTED check
393 if (!torchStrengthControlSupported) {
394 ALOGI("Torch strength control not supported.");
395 ASSERT_EQ(static_cast<int32_t>(Status::OPERATION_NOT_SUPPORTED),
396 ret.getServiceSpecificError());
397 } else {
398 {
399 ASSERT_TRUE(ret.isOk());
400 std::unique_lock<std::mutex> l(mTorchLock);
401 while (TorchModeStatus::NOT_AVAILABLE == mTorchStatus) {
402 auto timeout = std::chrono::system_clock::now() +
403 std::chrono::seconds(kTorchTimeoutSec);
404 ASSERT_NE(std::cv_status::timeout, mTorchCond.wait_until(l, timeout));
405 }
406 ASSERT_EQ(TorchModeStatus::AVAILABLE_ON, mTorchStatus);
407 mTorchStatus = TorchModeStatus::NOT_AVAILABLE;
408 }
409 ALOGI("getTorchStrengthLevel: Testing");
410 int32_t strengthLevel;
411 ret = device->getTorchStrengthLevel(&strengthLevel);
412 ASSERT_TRUE(ret.isOk());
413 ALOGI("Torch strength level is : %d", strengthLevel);
414 ASSERT_EQ(strengthLevel, 2);
415
416 // Turn OFF the torch and verify torch strength level is reset to default level.
417 ALOGI("Testing torch strength level reset after turning the torch OFF.");
418 ret = device->setTorchMode(false);
419 ASSERT_TRUE(ret.isOk());
420 {
421 std::unique_lock<std::mutex> l(mTorchLock);
422 while (TorchModeStatus::NOT_AVAILABLE == mTorchStatus) {
423 auto timeout = std::chrono::system_clock::now() +
424 std::chrono::seconds(kTorchTimeoutSec);
425 ASSERT_NE(std::cv_status::timeout, mTorchCond.wait_until(l, timeout));
426 }
427 ASSERT_EQ(TorchModeStatus::AVAILABLE_OFF, mTorchStatus);
428 }
429
430 ret = device->getTorchStrengthLevel(&strengthLevel);
431 ASSERT_TRUE(ret.isOk());
432 ALOGI("Torch strength level after turning OFF torch is : %d", strengthLevel);
433 ASSERT_EQ(strengthLevel, defaultLevel);
434 }
435 }
436}
437
438// In case it is supported verify that torch can be enabled.
439// Check for corresponding torch callbacks as well.
440TEST_P(CameraAidlTest, setTorchMode) {
441 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
442
443 std::shared_ptr<TorchProviderCb> cb = ndk::SharedRefBase::make<TorchProviderCb>(this);
444 ndk::ScopedAStatus ret = mProvider->setCallback(cb);
445 ALOGI("setCallback returns status: %d", ret.getServiceSpecificError());
446 ASSERT_TRUE(ret.isOk());
447 ASSERT_NE(cb, nullptr);
448
449 for (const auto& name : cameraDeviceNames) {
450 std::shared_ptr<ICameraDevice> device;
451 ALOGI("setTorchMode: Testing camera device %s", name.c_str());
452 ret = mProvider->getCameraDeviceInterface(name, &device);
453 ALOGI("getCameraDeviceInterface returns status:%d:%d", ret.getExceptionCode(),
454 ret.getServiceSpecificError());
455 ASSERT_TRUE(ret.isOk());
456 ASSERT_NE(device, nullptr);
457
458 CameraMetadata metadata;
459 ret = device->getCameraCharacteristics(&metadata);
460 ALOGI("getCameraCharacteristics returns status:%d", ret.getServiceSpecificError());
461 ASSERT_TRUE(ret.isOk());
462 camera_metadata_t* staticMeta =
463 reinterpret_cast<camera_metadata_t*>(metadata.metadata.data());
464 bool torchSupported = isTorchSupported(staticMeta);
465
466 mTorchStatus = TorchModeStatus::NOT_AVAILABLE;
467 ret = device->setTorchMode(true);
468 ALOGI("setTorchMode returns status: %d", ret.getServiceSpecificError());
469 if (!torchSupported) {
470 ASSERT_EQ(static_cast<int32_t>(Status::OPERATION_NOT_SUPPORTED),
471 ret.getServiceSpecificError());
472 } else {
473 ASSERT_TRUE(ret.isOk());
474 {
475 std::unique_lock<std::mutex> l(mTorchLock);
476 while (TorchModeStatus::NOT_AVAILABLE == mTorchStatus) {
477 auto timeout = std::chrono::system_clock::now() +
478 std::chrono::seconds(kTorchTimeoutSec);
479 ASSERT_NE(std::cv_status::timeout, mTorchCond.wait_until(l, timeout));
480 }
481 ASSERT_EQ(TorchModeStatus::AVAILABLE_ON, mTorchStatus);
482 mTorchStatus = TorchModeStatus::NOT_AVAILABLE;
483 }
484
485 ret = device->setTorchMode(false);
486 ASSERT_TRUE(ret.isOk());
487 {
488 std::unique_lock<std::mutex> l(mTorchLock);
489 while (TorchModeStatus::NOT_AVAILABLE == mTorchStatus) {
490 auto timeout = std::chrono::system_clock::now() +
491 std::chrono::seconds(kTorchTimeoutSec);
492 ASSERT_NE(std::cv_status::timeout, mTorchCond.wait_until(l, timeout));
493 }
494 ASSERT_EQ(TorchModeStatus::AVAILABLE_OFF, mTorchStatus);
495 }
496 }
497 }
Avichal Rakesh362242f2022-02-08 12:40:53 -0800498}
499
500// Check dump functionality.
501TEST_P(CameraAidlTest, dump) {
502 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
503
504 for (const auto& name : cameraDeviceNames) {
505 std::shared_ptr<ICameraDevice> device;
506 ALOGI("dump: Testing camera device %s", name.c_str());
507
508 ndk::ScopedAStatus ret = mProvider->getCameraDeviceInterface(name, &device);
509 ALOGI("getCameraDeviceInterface returns status:%d:%d", ret.getExceptionCode(),
510 ret.getServiceSpecificError());
511 ASSERT_TRUE(ret.isOk());
512 ASSERT_NE(device, nullptr);
513
514 int raw_handle = open(kDumpOutput, O_RDWR);
515 ASSERT_GE(raw_handle, 0);
516
517 auto retStatus = device->dump(raw_handle, nullptr, 0);
518 ASSERT_EQ(retStatus, ::android::OK);
519 close(raw_handle);
520 }
521}
522
523// Open, dump, then close
524TEST_P(CameraAidlTest, openClose) {
525 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
526
527 for (const auto& name : cameraDeviceNames) {
528 std::shared_ptr<ICameraDevice> device;
529 ALOGI("openClose: Testing camera device %s", name.c_str());
530 ndk::ScopedAStatus ret = mProvider->getCameraDeviceInterface(name, &device);
531 ALOGI("getCameraDeviceInterface returns status:%d:%d", ret.getExceptionCode(),
532 ret.getServiceSpecificError());
533 ASSERT_TRUE(ret.isOk());
534 ASSERT_NE(device, nullptr);
535
536 std::shared_ptr<EmptyDeviceCb> cb = ndk::SharedRefBase::make<EmptyDeviceCb>();
537
538 ret = device->open(cb, &mSession);
539 ASSERT_TRUE(ret.isOk());
540 ALOGI("device::open returns status:%d:%d", ret.getExceptionCode(),
541 ret.getServiceSpecificError());
542 ASSERT_NE(mSession, nullptr);
543 int raw_handle = open(kDumpOutput, O_RDWR);
544 ASSERT_GE(raw_handle, 0);
545
546 auto retStatus = device->dump(raw_handle, nullptr, 0);
547 ASSERT_EQ(retStatus, ::android::OK);
548 close(raw_handle);
549
550 ret = mSession->close();
551 mSession = nullptr;
552 ASSERT_TRUE(ret.isOk());
553 // TODO: test all session API calls return INTERNAL_ERROR after close
554 // TODO: keep a wp copy here and verify session cannot be promoted out of this scope
555 }
556}
557
558// Check whether all common default request settings can be successfully
559// constructed.
560TEST_P(CameraAidlTest, constructDefaultRequestSettings) {
561 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
562
563 for (const auto& name : cameraDeviceNames) {
564 std::shared_ptr<ICameraDevice> device;
565 ALOGI("constructDefaultRequestSettings: Testing camera device %s", name.c_str());
566 ndk::ScopedAStatus ret = mProvider->getCameraDeviceInterface(name, &device);
567 ALOGI("getCameraDeviceInterface returns status:%d:%d", ret.getExceptionCode(),
568 ret.getServiceSpecificError());
569 ASSERT_TRUE(ret.isOk());
570 ASSERT_NE(device, nullptr);
571
Shuzhen Wangdf89cb92023-11-09 18:24:42 -0800572 int32_t interfaceVersion;
573 ret = device->getInterfaceVersion(&interfaceVersion);
574 ASSERT_TRUE(ret.isOk());
575 bool supportFeatureCombinationQuery =
576 (interfaceVersion >= CAMERA_DEVICE_API_MINOR_VERSION_3);
577
Avichal Rakesh362242f2022-02-08 12:40:53 -0800578 std::shared_ptr<EmptyDeviceCb> cb = ndk::SharedRefBase::make<EmptyDeviceCb>();
579 ret = device->open(cb, &mSession);
580 ALOGI("device::open returns status:%d:%d", ret.getExceptionCode(),
581 ret.getServiceSpecificError());
582 ASSERT_TRUE(ret.isOk());
583 ASSERT_NE(mSession, nullptr);
584
585 for (int32_t t = (int32_t)RequestTemplate::PREVIEW; t <= (int32_t)RequestTemplate::MANUAL;
586 t++) {
587 RequestTemplate reqTemplate = (RequestTemplate)t;
588 CameraMetadata rawMetadata;
589 ret = mSession->constructDefaultRequestSettings(reqTemplate, &rawMetadata);
590 ALOGI("constructDefaultRequestSettings returns status:%d:%d", ret.getExceptionCode(),
591 ret.getServiceSpecificError());
Avichal Rakeshd3503a32022-02-25 06:23:14 +0000592
Avichal Rakesh362242f2022-02-08 12:40:53 -0800593 if (reqTemplate == RequestTemplate::ZERO_SHUTTER_LAG ||
594 reqTemplate == RequestTemplate::MANUAL) {
595 // optional templates
596 ASSERT_TRUE(ret.isOk() || static_cast<int32_t>(Status::ILLEGAL_ARGUMENT) ==
597 ret.getServiceSpecificError());
598 } else {
599 ASSERT_TRUE(ret.isOk());
600 }
601
602 if (ret.isOk()) {
Shuzhen Wangdba6eaa2023-12-20 23:54:38 +0000603 validateDefaultRequestMetadata(reqTemplate, rawMetadata);
Avichal Rakesh362242f2022-02-08 12:40:53 -0800604 } else {
605 ASSERT_EQ(0u, rawMetadata.metadata.size());
606 }
Shuzhen Wangdf89cb92023-11-09 18:24:42 -0800607
608 if (flags::feature_combination_query()) {
609 if (supportFeatureCombinationQuery) {
610 CameraMetadata rawMetadata2;
611 ndk::ScopedAStatus ret2 =
612 device->constructDefaultRequestSettings(reqTemplate, &rawMetadata2);
613
Shuzhen Wangdba6eaa2023-12-20 23:54:38 +0000614 ASSERT_EQ(ret.isOk(), ret2.isOk());
615 ASSERT_EQ(ret.getStatus(), ret2.getStatus());
Shuzhen Wangdf89cb92023-11-09 18:24:42 -0800616
Shuzhen Wangdba6eaa2023-12-20 23:54:38 +0000617 ASSERT_EQ(rawMetadata.metadata.size(), rawMetadata2.metadata.size());
618 if (ret2.isOk()) {
619 validateDefaultRequestMetadata(reqTemplate, rawMetadata2);
Shuzhen Wangdf89cb92023-11-09 18:24:42 -0800620 }
621 }
622 }
Avichal Rakesh362242f2022-02-08 12:40:53 -0800623 }
624 ret = mSession->close();
625 mSession = nullptr;
626 ASSERT_TRUE(ret.isOk());
627 }
628}
629
630// Verify that all supported stream formats and sizes can be configured
631// successfully.
632TEST_P(CameraAidlTest, configureStreamsAvailableOutputs) {
633 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
634 std::vector<AvailableStream> outputStreams;
635
636 for (const auto& name : cameraDeviceNames) {
637 CameraMetadata meta;
638 std::shared_ptr<ICameraDevice> device;
639
640 openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/, &device /*out*/);
641
642 camera_metadata_t* staticMeta = reinterpret_cast<camera_metadata_t*>(meta.metadata.data());
643 outputStreams.clear();
644 ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta, outputStreams));
645 ASSERT_NE(0u, outputStreams.size());
646
647 int32_t jpegBufferSize = 0;
648 ASSERT_EQ(Status::OK, getJpegBufferSize(staticMeta, &jpegBufferSize));
649 ASSERT_NE(0u, jpegBufferSize);
650
651 int32_t streamId = 0;
652 int32_t streamConfigCounter = 0;
653 for (auto& it : outputStreams) {
654 Stream stream;
655 Dataspace dataspace = getDataspace(static_cast<PixelFormat>(it.format));
656 stream.id = streamId;
657 stream.streamType = StreamType::OUTPUT;
658 stream.width = it.width;
659 stream.height = it.height;
660 stream.format = static_cast<PixelFormat>(it.format);
661 stream.dataSpace = dataspace;
662 stream.usage = static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
663 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER);
664 stream.rotation = StreamRotation::ROTATION_0;
Avichal Rakeshd3503a32022-02-25 06:23:14 +0000665 stream.dynamicRangeProfile = RequestAvailableDynamicRangeProfilesMap::
666 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD;
Austin Borger263e3622023-06-15 11:32:04 -0700667 stream.useCase = ScalerAvailableStreamUseCases::
668 ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT;
669 stream.colorSpace = static_cast<int>(
670 RequestAvailableColorSpaceProfilesMap::
671 ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED);
Avichal Rakesh362242f2022-02-08 12:40:53 -0800672
673 std::vector<Stream> streams = {stream};
674 StreamConfiguration config;
675 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
676 jpegBufferSize);
677
Shuzhen Wangdf89cb92023-11-09 18:24:42 -0800678 verifyStreamCombination(device, config, /*expectedStatus*/ true);
Avichal Rakesh362242f2022-02-08 12:40:53 -0800679
680 config.streamConfigCounter = streamConfigCounter++;
681 std::vector<HalStream> halConfigs;
682 ndk::ScopedAStatus ret = mSession->configureStreams(config, &halConfigs);
683 ASSERT_TRUE(ret.isOk());
684 ASSERT_EQ(halConfigs.size(), 1);
685 ASSERT_EQ(halConfigs[0].id, streamId);
686
687 streamId++;
688 }
689
690 ndk::ScopedAStatus ret = mSession->close();
691 mSession = nullptr;
692 ASSERT_TRUE(ret.isOk());
693 }
694}
695
696// Verify that mandatory concurrent streams and outputs are supported.
697TEST_P(CameraAidlTest, configureConcurrentStreamsAvailableOutputs) {
698 struct CameraTestInfo {
699 CameraMetadata staticMeta;
700 std::shared_ptr<ICameraDeviceSession> session;
701 std::shared_ptr<ICameraDevice> cameraDevice;
702 StreamConfiguration config;
703 };
704
705 std::map<std::string, std::string> idToNameMap = getCameraDeviceIdToNameMap(mProvider);
706 std::vector<ConcurrentCameraIdCombination> concurrentDeviceCombinations =
707 getConcurrentDeviceCombinations(mProvider);
708 std::vector<AvailableStream> outputStreams;
709 for (const auto& cameraDeviceIds : concurrentDeviceCombinations) {
710 std::vector<CameraIdAndStreamCombination> cameraIdsAndStreamCombinations;
711 std::vector<CameraTestInfo> cameraTestInfos;
Avichal Rakesh362242f2022-02-08 12:40:53 -0800712 for (const auto& id : cameraDeviceIds.combination) {
713 CameraTestInfo cti;
714 auto it = idToNameMap.find(id);
715 ASSERT_TRUE(idToNameMap.end() != it);
716 std::string name = it->second;
717
718 openEmptyDeviceSession(name, mProvider, &cti.session /*out*/, &cti.staticMeta /*out*/,
719 &cti.cameraDevice /*out*/);
720
721 outputStreams.clear();
722 camera_metadata_t* staticMeta =
723 reinterpret_cast<camera_metadata_t*>(cti.staticMeta.metadata.data());
724 ASSERT_EQ(Status::OK, getMandatoryConcurrentStreams(staticMeta, &outputStreams));
725 ASSERT_NE(0u, outputStreams.size());
726
727 int32_t jpegBufferSize = 0;
728 ASSERT_EQ(Status::OK, getJpegBufferSize(staticMeta, &jpegBufferSize));
729 ASSERT_NE(0u, jpegBufferSize);
730
731 int32_t streamId = 0;
732 std::vector<Stream> streams(outputStreams.size());
733 size_t j = 0;
734 for (const auto& s : outputStreams) {
735 Stream stream;
736 Dataspace dataspace = getDataspace(static_cast<PixelFormat>(s.format));
737 stream.id = streamId++;
738 stream.streamType = StreamType::OUTPUT;
739 stream.width = s.width;
740 stream.height = s.height;
741 stream.format = static_cast<PixelFormat>(s.format);
742 stream.usage = static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
743 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER);
744 stream.dataSpace = dataspace;
745 stream.rotation = StreamRotation::ROTATION_0;
746 stream.sensorPixelModesUsed = {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT};
Avichal Rakeshd3503a32022-02-25 06:23:14 +0000747 stream.dynamicRangeProfile = RequestAvailableDynamicRangeProfilesMap::
748 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD;
Avichal Rakesh362242f2022-02-08 12:40:53 -0800749 streams[j] = stream;
750 j++;
751 }
752
753 // Add the created stream configs to cameraIdsAndStreamCombinations
754 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &cti.config,
755 jpegBufferSize);
756
757 cti.config.streamConfigCounter = outputStreams.size();
758 CameraIdAndStreamCombination cameraIdAndStreamCombination;
759 cameraIdAndStreamCombination.cameraId = id;
760 cameraIdAndStreamCombination.streamConfiguration = cti.config;
761 cameraIdsAndStreamCombinations.push_back(cameraIdAndStreamCombination);
Avichal Rakesh362242f2022-02-08 12:40:53 -0800762 cameraTestInfos.push_back(cti);
763 }
764 // Now verify that concurrent streams are supported
765 bool combinationSupported;
766 ndk::ScopedAStatus ret = mProvider->isConcurrentStreamCombinationSupported(
767 cameraIdsAndStreamCombinations, &combinationSupported);
768 ASSERT_TRUE(ret.isOk());
769 ASSERT_EQ(combinationSupported, true);
770
771 // Test the stream can actually be configured
772 for (auto& cti : cameraTestInfos) {
773 if (cti.session != nullptr) {
Shuzhen Wangdf89cb92023-11-09 18:24:42 -0800774 verifyStreamCombination(cti.cameraDevice, cti.config, /*expectedStatus*/ true);
Avichal Rakesh362242f2022-02-08 12:40:53 -0800775 }
776
777 if (cti.session != nullptr) {
778 std::vector<HalStream> streamConfigs;
779 ret = cti.session->configureStreams(cti.config, &streamConfigs);
780 ASSERT_TRUE(ret.isOk());
781 ASSERT_EQ(cti.config.streams.size(), streamConfigs.size());
782 }
783 }
784
785 for (auto& cti : cameraTestInfos) {
786 ret = cti.session->close();
787 ASSERT_TRUE(ret.isOk());
788 }
789 }
790}
791
792// Check for correct handling of invalid/incorrect configuration parameters.
793TEST_P(CameraAidlTest, configureStreamsInvalidOutputs) {
794 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
795 std::vector<AvailableStream> outputStreams;
796
797 for (const auto& name : cameraDeviceNames) {
798 CameraMetadata meta;
799 std::shared_ptr<ICameraDevice> cameraDevice;
800
801 openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/,
802 &cameraDevice /*out*/);
803 camera_metadata_t* staticMeta = reinterpret_cast<camera_metadata_t*>(meta.metadata.data());
804 outputStreams.clear();
805
806 ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta, outputStreams));
807 ASSERT_NE(0u, outputStreams.size());
808
809 int32_t jpegBufferSize = 0;
810 ASSERT_EQ(Status::OK, getJpegBufferSize(staticMeta, &jpegBufferSize));
811 ASSERT_NE(0u, jpegBufferSize);
812
813 int32_t streamId = 0;
814 Stream stream = {streamId++,
815 StreamType::OUTPUT,
816 static_cast<uint32_t>(0),
817 static_cast<uint32_t>(0),
818 static_cast<PixelFormat>(outputStreams[0].format),
819 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
820 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
821 Dataspace::UNKNOWN,
822 StreamRotation::ROTATION_0,
823 std::string(),
824 jpegBufferSize,
825 -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +0000826 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
827 RequestAvailableDynamicRangeProfilesMap::
828 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -0800829 int32_t streamConfigCounter = 0;
830 std::vector<Stream> streams = {stream};
831 StreamConfiguration config;
832 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
833 jpegBufferSize);
834
Shuzhen Wangdf89cb92023-11-09 18:24:42 -0800835 verifyStreamCombination(cameraDevice, config, /*expectedStatus*/ false);
Avichal Rakesh362242f2022-02-08 12:40:53 -0800836
837 config.streamConfigCounter = streamConfigCounter++;
838 std::vector<HalStream> halConfigs;
839 ndk::ScopedAStatus ret = mSession->configureStreams(config, &halConfigs);
840 ASSERT_TRUE(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT) ==
841 ret.getServiceSpecificError() ||
842 static_cast<int32_t>(Status::INTERNAL_ERROR) == ret.getServiceSpecificError());
843
844 stream = {streamId++,
845 StreamType::OUTPUT,
846 /*width*/ INT32_MAX,
847 /*height*/ INT32_MAX,
848 static_cast<PixelFormat>(outputStreams[0].format),
849 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
850 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
851 Dataspace::UNKNOWN,
852 StreamRotation::ROTATION_0,
853 std::string(),
854 jpegBufferSize,
855 -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +0000856 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
857 RequestAvailableDynamicRangeProfilesMap::
858 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -0800859
860 streams[0] = stream;
861 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
862 jpegBufferSize);
863
864 config.streamConfigCounter = streamConfigCounter++;
865 halConfigs.clear();
866 ret = mSession->configureStreams(config, &halConfigs);
867 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT), ret.getServiceSpecificError());
868
869 for (auto& it : outputStreams) {
870 stream = {streamId++,
871 StreamType::OUTPUT,
872 it.width,
873 it.height,
874 static_cast<PixelFormat>(UINT32_MAX),
875 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
876 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
877 Dataspace::UNKNOWN,
878 StreamRotation::ROTATION_0,
879 std::string(),
880 jpegBufferSize,
881 -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +0000882 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
883 RequestAvailableDynamicRangeProfilesMap::
884 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -0800885
886 streams[0] = stream;
887 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
888 jpegBufferSize);
889 config.streamConfigCounter = streamConfigCounter++;
890 halConfigs.clear();
891 ret = mSession->configureStreams(config, &halConfigs);
892 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT),
893 ret.getServiceSpecificError());
894
895 stream = {streamId++,
896 StreamType::OUTPUT,
897 it.width,
898 it.height,
899 static_cast<PixelFormat>(it.format),
900 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
901 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
902 Dataspace::UNKNOWN,
903 static_cast<StreamRotation>(UINT32_MAX),
904 std::string(),
905 jpegBufferSize,
906 -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +0000907 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
908 RequestAvailableDynamicRangeProfilesMap::
909 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -0800910
911 streams[0] = stream;
912 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
913 jpegBufferSize);
914
915 config.streamConfigCounter = streamConfigCounter++;
916 halConfigs.clear();
917 ret = mSession->configureStreams(config, &halConfigs);
918 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT),
919 ret.getServiceSpecificError());
920 }
921
922 ret = mSession->close();
923 mSession = nullptr;
924 ASSERT_TRUE(ret.isOk());
925 }
926}
927
928// Check whether all supported ZSL output stream combinations can be
929// configured successfully.
930TEST_P(CameraAidlTest, configureStreamsZSLInputOutputs) {
931 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
932 std::vector<AvailableStream> inputStreams;
933 std::vector<AvailableZSLInputOutput> inputOutputMap;
934
935 for (const auto& name : cameraDeviceNames) {
936 CameraMetadata meta;
937 std::shared_ptr<ICameraDevice> cameraDevice;
938
939 openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/,
940 &cameraDevice /*out*/);
941 camera_metadata_t* staticMeta = reinterpret_cast<camera_metadata_t*>(meta.metadata.data());
942
943 Status rc = isZSLModeAvailable(staticMeta);
944 if (Status::OPERATION_NOT_SUPPORTED == rc) {
945 ndk::ScopedAStatus ret = mSession->close();
946 mSession = nullptr;
947 ASSERT_TRUE(ret.isOk());
948 continue;
949 }
950 ASSERT_EQ(Status::OK, rc);
951
952 inputStreams.clear();
953 ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta, inputStreams));
954 ASSERT_NE(0u, inputStreams.size());
955
956 inputOutputMap.clear();
957 ASSERT_EQ(Status::OK, getZSLInputOutputMap(staticMeta, inputOutputMap));
958 ASSERT_NE(0u, inputOutputMap.size());
959
960 bool supportMonoY8 = false;
961 if (Status::OK == isMonochromeCamera(staticMeta)) {
962 for (auto& it : inputStreams) {
963 if (it.format == static_cast<uint32_t>(PixelFormat::Y8)) {
964 supportMonoY8 = true;
965 break;
966 }
967 }
968 }
969
970 int32_t jpegBufferSize = 0;
971 ASSERT_EQ(Status::OK, getJpegBufferSize(staticMeta, &jpegBufferSize));
972 ASSERT_NE(0u, jpegBufferSize);
973
974 int32_t streamId = 0;
975 bool hasPrivToY8 = false, hasY8ToY8 = false, hasY8ToBlob = false;
976 uint32_t streamConfigCounter = 0;
977 for (auto& inputIter : inputOutputMap) {
978 AvailableStream input;
979 ASSERT_EQ(Status::OK, findLargestSize(inputStreams, inputIter.inputFormat, input));
980 ASSERT_NE(0u, inputStreams.size());
981
982 if (inputIter.inputFormat ==
983 static_cast<uint32_t>(PixelFormat::IMPLEMENTATION_DEFINED) &&
984 inputIter.outputFormat == static_cast<uint32_t>(PixelFormat::Y8)) {
985 hasPrivToY8 = true;
986 } else if (inputIter.inputFormat == static_cast<uint32_t>(PixelFormat::Y8)) {
987 if (inputIter.outputFormat == static_cast<uint32_t>(PixelFormat::BLOB)) {
988 hasY8ToBlob = true;
989 } else if (inputIter.outputFormat == static_cast<uint32_t>(PixelFormat::Y8)) {
990 hasY8ToY8 = true;
991 }
992 }
993 AvailableStream outputThreshold = {INT32_MAX, INT32_MAX, inputIter.outputFormat};
994 std::vector<AvailableStream> outputStreams;
995 ASSERT_EQ(Status::OK,
996 getAvailableOutputStreams(staticMeta, outputStreams, &outputThreshold));
997 for (auto& outputIter : outputStreams) {
998 Dataspace outputDataSpace =
999 getDataspace(static_cast<PixelFormat>(outputIter.format));
1000 Stream zslStream = {
1001 streamId++,
1002 StreamType::OUTPUT,
1003 input.width,
1004 input.height,
1005 static_cast<PixelFormat>(input.format),
1006 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
1007 GRALLOC_USAGE_HW_CAMERA_ZSL),
1008 Dataspace::UNKNOWN,
1009 StreamRotation::ROTATION_0,
1010 std::string(),
1011 jpegBufferSize,
1012 -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00001013 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
1014 RequestAvailableDynamicRangeProfilesMap::
1015 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08001016 Stream inputStream = {
1017 streamId++,
1018 StreamType::INPUT,
1019 input.width,
1020 input.height,
1021 static_cast<PixelFormat>(input.format),
1022 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(0),
1023 Dataspace::UNKNOWN,
1024 StreamRotation::ROTATION_0,
1025 std::string(),
1026 jpegBufferSize,
1027 -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00001028 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
1029 RequestAvailableDynamicRangeProfilesMap::
1030 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08001031 Stream outputStream = {
1032 streamId++,
1033 StreamType::OUTPUT,
1034 outputIter.width,
1035 outputIter.height,
1036 static_cast<PixelFormat>(outputIter.format),
1037 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
1038 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
1039 outputDataSpace,
1040 StreamRotation::ROTATION_0,
1041 std::string(),
1042 jpegBufferSize,
1043 -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00001044 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
1045 RequestAvailableDynamicRangeProfilesMap::
1046 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08001047
1048 std::vector<Stream> streams = {inputStream, zslStream, outputStream};
1049
1050 StreamConfiguration config;
1051 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
1052 jpegBufferSize);
1053
Shuzhen Wangdf89cb92023-11-09 18:24:42 -08001054 verifyStreamCombination(cameraDevice, config, /*expectedStatus*/ true);
Avichal Rakesh362242f2022-02-08 12:40:53 -08001055
1056 config.streamConfigCounter = streamConfigCounter++;
1057 std::vector<HalStream> halConfigs;
1058 ndk::ScopedAStatus ret = mSession->configureStreams(config, &halConfigs);
1059 ASSERT_TRUE(ret.isOk());
1060 ASSERT_EQ(3u, halConfigs.size());
1061 }
1062 }
1063
1064 if (supportMonoY8) {
1065 if (Status::OK == isZSLModeAvailable(staticMeta, PRIV_REPROCESS)) {
1066 ASSERT_TRUE(hasPrivToY8);
1067 }
1068 if (Status::OK == isZSLModeAvailable(staticMeta, YUV_REPROCESS)) {
1069 ASSERT_TRUE(hasY8ToY8);
1070 ASSERT_TRUE(hasY8ToBlob);
1071 }
1072 }
1073
1074 ndk::ScopedAStatus ret = mSession->close();
1075 mSession = nullptr;
1076 ASSERT_TRUE(ret.isOk());
1077 }
1078}
1079
1080// Check whether session parameters are supported. If Hal support for them
1081// exist, then try to configure a preview stream using them.
1082TEST_P(CameraAidlTest, configureStreamsWithSessionParameters) {
1083 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
1084 std::vector<AvailableStream> outputPreviewStreams;
1085 AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
1086 static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
1087
1088 for (const auto& name : cameraDeviceNames) {
1089 CameraMetadata meta;
1090
1091 std::shared_ptr<ICameraDevice> unusedCameraDevice;
1092 openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/,
1093 &unusedCameraDevice /*out*/);
1094 camera_metadata_t* staticMetaBuffer =
1095 reinterpret_cast<camera_metadata_t*>(meta.metadata.data());
1096
1097 std::unordered_set<int32_t> availableSessionKeys;
1098 auto rc = getSupportedKeys(staticMetaBuffer, ANDROID_REQUEST_AVAILABLE_SESSION_KEYS,
1099 &availableSessionKeys);
1100 ASSERT_TRUE(Status::OK == rc);
1101 if (availableSessionKeys.empty()) {
1102 ndk::ScopedAStatus ret = mSession->close();
1103 mSession = nullptr;
1104 ASSERT_TRUE(ret.isOk());
1105 continue;
1106 }
1107
1108 android::hardware::camera::common::V1_0::helper::CameraMetadata previewRequestSettings;
1109 android::hardware::camera::common::V1_0::helper::CameraMetadata sessionParams,
1110 modifiedSessionParams;
1111 constructFilteredSettings(mSession, availableSessionKeys, RequestTemplate::PREVIEW,
1112 &previewRequestSettings, &sessionParams);
1113 if (sessionParams.isEmpty()) {
1114 ndk::ScopedAStatus ret = mSession->close();
1115 mSession = nullptr;
1116 ASSERT_TRUE(ret.isOk());
1117 continue;
1118 }
1119
1120 outputPreviewStreams.clear();
1121
1122 ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMetaBuffer, outputPreviewStreams,
1123 &previewThreshold));
1124 ASSERT_NE(0u, outputPreviewStreams.size());
1125
Avichal Rakeshd3503a32022-02-25 06:23:14 +00001126 Stream previewStream = {
1127 0,
1128 StreamType::OUTPUT,
1129 outputPreviewStreams[0].width,
1130 outputPreviewStreams[0].height,
1131 static_cast<PixelFormat>(outputPreviewStreams[0].format),
1132 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
1133 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
1134 Dataspace::UNKNOWN,
1135 StreamRotation::ROTATION_0,
1136 std::string(),
1137 /*bufferSize*/ 0,
1138 /*groupId*/ -1,
1139 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
1140 RequestAvailableDynamicRangeProfilesMap::
1141 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08001142
1143 std::vector<Stream> streams = {previewStream};
1144 StreamConfiguration config;
1145
1146 config.streams = streams;
1147 config.operationMode = StreamConfigurationMode::NORMAL_MODE;
1148 modifiedSessionParams = sessionParams;
1149 auto sessionParamsBuffer = sessionParams.release();
1150 std::vector<uint8_t> rawSessionParam =
1151 std::vector(reinterpret_cast<uint8_t*>(sessionParamsBuffer),
1152 reinterpret_cast<uint8_t*>(sessionParamsBuffer) +
1153 get_camera_metadata_size(sessionParamsBuffer));
1154
1155 config.sessionParams.metadata = rawSessionParam;
1156 config.streamConfigCounter = 0;
1157 config.streams = {previewStream};
1158 config.streamConfigCounter = 0;
1159 config.multiResolutionInputImage = false;
1160
1161 bool newSessionParamsAvailable = false;
1162 for (const auto& it : availableSessionKeys) {
1163 if (modifiedSessionParams.exists(it)) {
1164 modifiedSessionParams.erase(it);
1165 newSessionParamsAvailable = true;
1166 break;
1167 }
1168 }
1169 if (newSessionParamsAvailable) {
1170 auto modifiedSessionParamsBuffer = modifiedSessionParams.release();
1171 verifySessionReconfigurationQuery(mSession, sessionParamsBuffer,
1172 modifiedSessionParamsBuffer);
1173 modifiedSessionParams.acquire(modifiedSessionParamsBuffer);
1174 }
1175
1176 std::vector<HalStream> halConfigs;
1177 ndk::ScopedAStatus ret = mSession->configureStreams(config, &halConfigs);
1178 ASSERT_TRUE(ret.isOk());
1179 ASSERT_EQ(1u, halConfigs.size());
1180
1181 sessionParams.acquire(sessionParamsBuffer);
1182 ret = mSession->close();
1183 mSession = nullptr;
1184 ASSERT_TRUE(ret.isOk());
1185 }
1186}
1187
1188// Verify that all supported preview + still capture stream combinations
1189// can be configured successfully.
1190TEST_P(CameraAidlTest, configureStreamsPreviewStillOutputs) {
1191 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
1192 std::vector<AvailableStream> outputBlobStreams;
1193 std::vector<AvailableStream> outputPreviewStreams;
1194 AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
1195 static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
1196 AvailableStream blobThreshold = {INT32_MAX, INT32_MAX, static_cast<int32_t>(PixelFormat::BLOB)};
1197
1198 for (const auto& name : cameraDeviceNames) {
1199 CameraMetadata meta;
1200
1201 std::shared_ptr<ICameraDevice> cameraDevice;
1202 openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/,
1203 &cameraDevice /*out*/);
1204
1205 camera_metadata_t* staticMeta = reinterpret_cast<camera_metadata_t*>(meta.metadata.data());
1206
1207 // Check if camera support depth only
1208 if (isDepthOnly(staticMeta)) {
1209 ndk::ScopedAStatus ret = mSession->close();
1210 mSession = nullptr;
1211 ASSERT_TRUE(ret.isOk());
1212 continue;
1213 }
1214
1215 outputBlobStreams.clear();
1216 ASSERT_EQ(Status::OK,
1217 getAvailableOutputStreams(staticMeta, outputBlobStreams, &blobThreshold));
1218 ASSERT_NE(0u, outputBlobStreams.size());
1219
1220 outputPreviewStreams.clear();
1221 ASSERT_EQ(Status::OK,
1222 getAvailableOutputStreams(staticMeta, outputPreviewStreams, &previewThreshold));
1223 ASSERT_NE(0u, outputPreviewStreams.size());
1224
1225 int32_t jpegBufferSize = 0;
1226 ASSERT_EQ(Status::OK, getJpegBufferSize(staticMeta, &jpegBufferSize));
1227 ASSERT_NE(0u, jpegBufferSize);
1228
1229 int32_t streamId = 0;
1230 uint32_t streamConfigCounter = 0;
1231
1232 for (auto& blobIter : outputBlobStreams) {
1233 for (auto& previewIter : outputPreviewStreams) {
1234 Stream previewStream = {
1235 streamId++,
1236 StreamType::OUTPUT,
1237 previewIter.width,
1238 previewIter.height,
1239 static_cast<PixelFormat>(previewIter.format),
1240 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
1241 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
1242 Dataspace::UNKNOWN,
1243 StreamRotation::ROTATION_0,
1244 std::string(),
1245 /*bufferSize*/ 0,
1246 /*groupId*/ -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00001247 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
1248 RequestAvailableDynamicRangeProfilesMap::
1249 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08001250 Stream blobStream = {
1251 streamId++,
1252 StreamType::OUTPUT,
1253 blobIter.width,
1254 blobIter.height,
1255 static_cast<PixelFormat>(blobIter.format),
1256 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
1257 GRALLOC1_CONSUMER_USAGE_CPU_READ),
1258 Dataspace::JFIF,
1259 StreamRotation::ROTATION_0,
1260 std::string(),
1261 /*bufferSize*/ 0,
1262 /*groupId*/ -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00001263 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
1264 RequestAvailableDynamicRangeProfilesMap::
1265 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08001266 std::vector<Stream> streams = {previewStream, blobStream};
1267 StreamConfiguration config;
1268
1269 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
1270 jpegBufferSize);
1271 config.streamConfigCounter = streamConfigCounter++;
Shuzhen Wangdf89cb92023-11-09 18:24:42 -08001272 verifyStreamCombination(cameraDevice, config, /*expectedStatus*/ true);
Avichal Rakesh362242f2022-02-08 12:40:53 -08001273
1274 std::vector<HalStream> halConfigs;
1275 ndk::ScopedAStatus ret = mSession->configureStreams(config, &halConfigs);
1276 ASSERT_TRUE(ret.isOk());
1277 ASSERT_EQ(2u, halConfigs.size());
1278 }
1279 }
1280
1281 ndk::ScopedAStatus ret = mSession->close();
1282 mSession = nullptr;
1283 ASSERT_TRUE(ret.isOk());
1284 }
1285}
1286
1287// In case constrained mode is supported, test whether it can be
1288// configured. Additionally check for common invalid inputs when
1289// using this mode.
1290TEST_P(CameraAidlTest, configureStreamsConstrainedOutputs) {
1291 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
1292
1293 for (const auto& name : cameraDeviceNames) {
1294 CameraMetadata meta;
1295 std::shared_ptr<ICameraDevice> cameraDevice;
1296
1297 openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/,
1298 &cameraDevice /*out*/);
1299 camera_metadata_t* staticMeta = reinterpret_cast<camera_metadata_t*>(meta.metadata.data());
1300
1301 Status rc = isConstrainedModeAvailable(staticMeta);
1302 if (Status::OPERATION_NOT_SUPPORTED == rc) {
1303 ndk::ScopedAStatus ret = mSession->close();
1304 mSession = nullptr;
1305 ASSERT_TRUE(ret.isOk());
1306 continue;
1307 }
1308 ASSERT_EQ(Status::OK, rc);
1309
1310 AvailableStream hfrStream;
1311 rc = pickConstrainedModeSize(staticMeta, hfrStream);
1312 ASSERT_EQ(Status::OK, rc);
1313
1314 int32_t streamId = 0;
1315 uint32_t streamConfigCounter = 0;
1316 Stream stream = {streamId,
1317 StreamType::OUTPUT,
1318 hfrStream.width,
1319 hfrStream.height,
1320 static_cast<PixelFormat>(hfrStream.format),
1321 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
1322 GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER),
1323 Dataspace::UNKNOWN,
1324 StreamRotation::ROTATION_0,
1325 std::string(),
1326 /*bufferSize*/ 0,
1327 /*groupId*/ -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00001328 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
1329 RequestAvailableDynamicRangeProfilesMap::
1330 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08001331 std::vector<Stream> streams = {stream};
1332 StreamConfiguration config;
1333 createStreamConfiguration(streams, StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE,
1334 &config);
1335
Shuzhen Wangdf89cb92023-11-09 18:24:42 -08001336 verifyStreamCombination(cameraDevice, config, /*expectedStatus*/ true);
Avichal Rakesh362242f2022-02-08 12:40:53 -08001337
1338 config.streamConfigCounter = streamConfigCounter++;
1339 std::vector<HalStream> halConfigs;
1340 ndk::ScopedAStatus ret = mSession->configureStreams(config, &halConfigs);
1341 ASSERT_TRUE(ret.isOk());
1342 ASSERT_EQ(1u, halConfigs.size());
1343 ASSERT_EQ(halConfigs[0].id, streamId);
1344
1345 stream = {streamId++,
1346 StreamType::OUTPUT,
1347 static_cast<uint32_t>(0),
1348 static_cast<uint32_t>(0),
1349 static_cast<PixelFormat>(hfrStream.format),
1350 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
1351 GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER),
1352 Dataspace::UNKNOWN,
1353 StreamRotation::ROTATION_0,
1354 std::string(),
1355 /*bufferSize*/ 0,
1356 /*groupId*/ -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00001357 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
1358 RequestAvailableDynamicRangeProfilesMap::
1359 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08001360 streams[0] = stream;
1361 createStreamConfiguration(streams, StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE,
1362 &config);
1363
1364 config.streamConfigCounter = streamConfigCounter++;
1365 std::vector<HalStream> halConfig;
1366 ret = mSession->configureStreams(config, &halConfig);
1367 ASSERT_TRUE(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT) ==
1368 ret.getServiceSpecificError() ||
1369 static_cast<int32_t>(Status::INTERNAL_ERROR) == ret.getServiceSpecificError());
1370
1371 stream = {streamId++,
1372 StreamType::OUTPUT,
1373 INT32_MAX,
1374 INT32_MAX,
1375 static_cast<PixelFormat>(hfrStream.format),
1376 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
1377 GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER),
1378 Dataspace::UNKNOWN,
1379 StreamRotation::ROTATION_0,
1380 std::string(),
1381 /*bufferSize*/ 0,
1382 /*groupId*/ -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00001383 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
1384 RequestAvailableDynamicRangeProfilesMap::
1385 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08001386 streams[0] = stream;
1387 createStreamConfiguration(streams, StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE,
1388 &config);
1389
1390 config.streamConfigCounter = streamConfigCounter++;
1391 halConfigs.clear();
1392 ret = mSession->configureStreams(config, &halConfigs);
1393 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT), ret.getServiceSpecificError());
1394
1395 stream = {streamId++,
1396 StreamType::OUTPUT,
1397 hfrStream.width,
1398 hfrStream.height,
1399 static_cast<PixelFormat>(UINT32_MAX),
1400 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
1401 GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER),
1402 Dataspace::UNKNOWN,
1403 StreamRotation::ROTATION_0,
1404 std::string(),
1405 /*bufferSize*/ 0,
1406 /*groupId*/ -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00001407 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
1408 RequestAvailableDynamicRangeProfilesMap::
1409 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08001410 streams[0] = stream;
1411 createStreamConfiguration(streams, StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE,
1412 &config);
1413
1414 config.streamConfigCounter = streamConfigCounter++;
1415 halConfigs.clear();
1416 ret = mSession->configureStreams(config, &halConfigs);
1417 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT), ret.getServiceSpecificError());
1418
1419 ret = mSession->close();
1420 mSession = nullptr;
1421 ASSERT_TRUE(ret.isOk());
1422 }
1423}
1424
1425// Verify that all supported video + snapshot stream combinations can
1426// be configured successfully.
1427TEST_P(CameraAidlTest, configureStreamsVideoStillOutputs) {
1428 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
1429 std::vector<AvailableStream> outputBlobStreams;
1430 std::vector<AvailableStream> outputVideoStreams;
1431 AvailableStream videoThreshold = {kMaxVideoWidth, kMaxVideoHeight,
1432 static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
1433 AvailableStream blobThreshold = {kMaxVideoWidth, kMaxVideoHeight,
1434 static_cast<int32_t>(PixelFormat::BLOB)};
1435
1436 for (const auto& name : cameraDeviceNames) {
1437 CameraMetadata meta;
1438 std::shared_ptr<ICameraDevice> cameraDevice;
1439
1440 openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/,
1441 &cameraDevice /*out*/);
1442
1443 camera_metadata_t* staticMeta = reinterpret_cast<camera_metadata_t*>(meta.metadata.data());
1444
1445 // Check if camera support depth only
1446 if (isDepthOnly(staticMeta)) {
1447 ndk::ScopedAStatus ret = mSession->close();
1448 mSession = nullptr;
1449 ASSERT_TRUE(ret.isOk());
1450 continue;
1451 }
1452
1453 outputBlobStreams.clear();
1454 ASSERT_EQ(Status::OK,
1455 getAvailableOutputStreams(staticMeta, outputBlobStreams, &blobThreshold));
1456 ASSERT_NE(0u, outputBlobStreams.size());
1457
1458 outputVideoStreams.clear();
1459 ASSERT_EQ(Status::OK,
1460 getAvailableOutputStreams(staticMeta, outputVideoStreams, &videoThreshold));
1461 ASSERT_NE(0u, outputVideoStreams.size());
1462
1463 int32_t jpegBufferSize = 0;
1464 ASSERT_EQ(Status::OK, getJpegBufferSize(staticMeta, &jpegBufferSize));
1465 ASSERT_NE(0u, jpegBufferSize);
1466
1467 int32_t streamId = 0;
1468 uint32_t streamConfigCounter = 0;
1469 for (auto& blobIter : outputBlobStreams) {
1470 for (auto& videoIter : outputVideoStreams) {
1471 Stream videoStream = {
1472 streamId++,
1473 StreamType::OUTPUT,
1474 videoIter.width,
1475 videoIter.height,
1476 static_cast<PixelFormat>(videoIter.format),
1477 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
1478 GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER),
1479 Dataspace::UNKNOWN,
1480 StreamRotation::ROTATION_0,
1481 std::string(),
1482 jpegBufferSize,
1483 /*groupId*/ -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00001484 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
1485 RequestAvailableDynamicRangeProfilesMap::
1486 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08001487 Stream blobStream = {
1488 streamId++,
1489 StreamType::OUTPUT,
1490 blobIter.width,
1491 blobIter.height,
1492 static_cast<PixelFormat>(blobIter.format),
1493 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
1494 GRALLOC1_CONSUMER_USAGE_CPU_READ),
1495 Dataspace::JFIF,
1496 StreamRotation::ROTATION_0,
1497 std::string(),
1498 jpegBufferSize,
1499 /*groupId*/ -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00001500 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
1501 RequestAvailableDynamicRangeProfilesMap::
1502 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08001503 std::vector<Stream> streams = {videoStream, blobStream};
1504 StreamConfiguration config;
1505
1506 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
1507 jpegBufferSize);
Shuzhen Wangdf89cb92023-11-09 18:24:42 -08001508 verifyStreamCombination(cameraDevice, config, /*expectedStatus*/ true);
Avichal Rakesh362242f2022-02-08 12:40:53 -08001509
1510 config.streamConfigCounter = streamConfigCounter++;
1511 std::vector<HalStream> halConfigs;
1512 ndk::ScopedAStatus ret = mSession->configureStreams(config, &halConfigs);
1513 ASSERT_TRUE(ret.isOk());
1514 ASSERT_EQ(2u, halConfigs.size());
1515 }
1516 }
1517
1518 ndk::ScopedAStatus ret = mSession->close();
1519 mSession = nullptr;
1520 ASSERT_TRUE(ret.isOk());
1521 }
1522}
1523
1524// Generate and verify a camera capture request
1525TEST_P(CameraAidlTest, processCaptureRequestPreview) {
1526 // TODO(b/220897574): Failing with BUFFER_ERROR
1527 processCaptureRequestInternal(GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, RequestTemplate::PREVIEW,
1528 false /*secureOnlyCameras*/);
1529}
1530
1531// Generate and verify a secure camera capture request
1532TEST_P(CameraAidlTest, processSecureCaptureRequest) {
1533 processCaptureRequestInternal(GRALLOC1_PRODUCER_USAGE_PROTECTED, RequestTemplate::STILL_CAPTURE,
1534 true /*secureOnlyCameras*/);
1535}
1536
1537TEST_P(CameraAidlTest, processCaptureRequestPreviewStabilization) {
1538 std::unordered_map<std::string, nsecs_t> cameraDeviceToTimeLag;
1539 processPreviewStabilizationCaptureRequestInternal(/*previewStabilizationOn*/ false,
1540 cameraDeviceToTimeLag);
1541 processPreviewStabilizationCaptureRequestInternal(/*previewStabilizationOn*/ true,
1542 cameraDeviceToTimeLag);
1543}
1544
1545// Generate and verify a multi-camera capture request
1546TEST_P(CameraAidlTest, processMultiCaptureRequestPreview) {
1547 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
1548 AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
1549 static_cast<int32_t>(PixelFormat::YCBCR_420_888)};
1550 int64_t bufferId = 1;
1551 uint32_t frameNumber = 1;
1552 std::vector<uint8_t> settings;
1553 std::vector<uint8_t> emptySettings;
1554 std::string invalidPhysicalId = "-1";
1555
1556 for (const auto& name : cameraDeviceNames) {
1557 std::string version, deviceId;
Avichal Rakeshfbcf7ea2022-03-09 01:00:34 +00001558 ALOGI("processMultiCaptureRequestPreview: Test device %s", name.c_str());
Avichal Rakesh362242f2022-02-08 12:40:53 -08001559 ASSERT_TRUE(matchDeviceName(name, mProviderType, &version, &deviceId));
1560 CameraMetadata metadata;
1561
1562 std::shared_ptr<ICameraDevice> unusedDevice;
1563 openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &metadata /*out*/,
1564 &unusedDevice /*out*/);
1565
1566 camera_metadata_t* staticMeta =
1567 reinterpret_cast<camera_metadata_t*>(metadata.metadata.data());
1568 Status rc = isLogicalMultiCamera(staticMeta);
1569 if (Status::OPERATION_NOT_SUPPORTED == rc) {
1570 ndk::ScopedAStatus ret = mSession->close();
1571 mSession = nullptr;
1572 ASSERT_TRUE(ret.isOk());
1573 continue;
1574 }
Avichal Rakeshfbcf7ea2022-03-09 01:00:34 +00001575 ASSERT_EQ(Status::OK, rc);
Avichal Rakesh362242f2022-02-08 12:40:53 -08001576
1577 std::unordered_set<std::string> physicalIds;
1578 rc = getPhysicalCameraIds(staticMeta, &physicalIds);
1579 ASSERT_TRUE(Status::OK == rc);
1580 ASSERT_TRUE(physicalIds.size() > 1);
1581
1582 std::unordered_set<int32_t> physicalRequestKeyIDs;
1583 rc = getSupportedKeys(staticMeta, ANDROID_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS,
1584 &physicalRequestKeyIDs);
1585 ASSERT_TRUE(Status::OK == rc);
1586 if (physicalRequestKeyIDs.empty()) {
1587 ndk::ScopedAStatus ret = mSession->close();
1588 mSession = nullptr;
1589 ASSERT_TRUE(ret.isOk());
1590 // The logical camera doesn't support any individual physical requests.
1591 continue;
1592 }
1593
1594 android::hardware::camera::common::V1_0::helper::CameraMetadata defaultPreviewSettings;
1595 android::hardware::camera::common::V1_0::helper::CameraMetadata filteredSettings;
1596 constructFilteredSettings(mSession, physicalRequestKeyIDs, RequestTemplate::PREVIEW,
1597 &defaultPreviewSettings, &filteredSettings);
1598 if (filteredSettings.isEmpty()) {
1599 // No physical device settings in default request.
1600 ndk::ScopedAStatus ret = mSession->close();
1601 mSession = nullptr;
1602 ASSERT_TRUE(ret.isOk());
1603 continue;
1604 }
1605
1606 const camera_metadata_t* settingsBuffer = defaultPreviewSettings.getAndLock();
1607 uint8_t* rawSettingsBuffer = (uint8_t*)settingsBuffer;
1608 settings.assign(rawSettingsBuffer,
1609 rawSettingsBuffer + get_camera_metadata_size(settingsBuffer));
1610 CameraMetadata settingsMetadata = {settings};
1611 overrideRotateAndCrop(&settingsMetadata);
1612
1613 ndk::ScopedAStatus ret = mSession->close();
1614 mSession = nullptr;
1615 ASSERT_TRUE(ret.isOk());
1616
1617 // Leave only 2 physical devices in the id set.
1618 auto it = physicalIds.begin();
1619 std::string physicalDeviceId = *it;
1620 it++;
1621 physicalIds.erase(++it, physicalIds.end());
1622 ASSERT_EQ(physicalIds.size(), 2u);
1623
1624 std::vector<HalStream> halStreams;
1625 bool supportsPartialResults = false;
Jayant Chowdhary4869ae72023-12-18 05:36:14 +00001626 std::set<int32_t> halBufManagedStreamIds;
Avichal Rakesh362242f2022-02-08 12:40:53 -08001627 int32_t partialResultCount = 0;
1628 Stream previewStream;
1629 std::shared_ptr<DeviceCb> cb;
1630
Avichal Rakeshfbcf7ea2022-03-09 01:00:34 +00001631 configurePreviewStreams(
1632 name, mProvider, &previewThreshold, physicalIds, &mSession, &previewStream,
1633 &halStreams /*out*/, &supportsPartialResults /*out*/, &partialResultCount /*out*/,
Jayant Chowdhary4869ae72023-12-18 05:36:14 +00001634 &halBufManagedStreamIds /*out*/, &cb /*out*/, 0 /*streamConfigCounter*/, true);
Avichal Rakeshfbcf7ea2022-03-09 01:00:34 +00001635 if (mSession == nullptr) {
1636 // stream combination not supported by HAL, skip test for device
1637 continue;
1638 }
Avichal Rakesh362242f2022-02-08 12:40:53 -08001639
1640 ::aidl::android::hardware::common::fmq::MQDescriptor<
1641 int8_t, aidl::android::hardware::common::fmq::SynchronizedReadWrite>
1642 descriptor;
1643 auto resultQueueRet = mSession->getCaptureResultMetadataQueue(&descriptor);
1644 ASSERT_TRUE(resultQueueRet.isOk());
1645 std::shared_ptr<ResultMetadataQueue> resultQueue =
1646 std::make_shared<ResultMetadataQueue>(descriptor);
1647 if (!resultQueue->isValid() || resultQueue->availableToWrite() <= 0) {
1648 ALOGE("%s: HAL returns empty result metadata fmq, not use it", __func__);
1649 resultQueue = nullptr;
1650 // Don't use the queue onwards.
1651 }
1652
1653 std::shared_ptr<InFlightRequest> inflightReq = std::make_shared<InFlightRequest>(
1654 static_cast<ssize_t>(halStreams.size()), false, supportsPartialResults,
1655 partialResultCount, physicalIds, resultQueue);
1656
1657 std::vector<CaptureRequest> requests(1);
1658 CaptureRequest& request = requests[0];
1659 request.frameNumber = frameNumber;
1660 request.fmqSettingsSize = 0;
Emilian Peev3d919f92022-04-20 13:50:59 -07001661 request.settings = settingsMetadata;
Avichal Rakesh362242f2022-02-08 12:40:53 -08001662
1663 std::vector<StreamBuffer>& outputBuffers = request.outputBuffers;
1664
1665 std::vector<buffer_handle_t> graphicBuffers;
1666 graphicBuffers.reserve(halStreams.size());
1667 outputBuffers.resize(halStreams.size());
1668 size_t k = 0;
1669 for (const auto& halStream : halStreams) {
1670 buffer_handle_t buffer_handle;
Jayant Chowdhary4869ae72023-12-18 05:36:14 +00001671 bool useHalBufManagerForStream =
1672 halBufManagedStreamIds.find(halStream.id) != halBufManagedStreamIds.end();
1673 if (useHalBufManagerForStream) {
Avichal Rakesh362242f2022-02-08 12:40:53 -08001674 outputBuffers[k] = {halStream.id, /*bufferId*/ 0, NativeHandle(),
1675 BufferStatus::OK, NativeHandle(), NativeHandle()};
1676 } else {
1677 allocateGraphicBuffer(previewStream.width, previewStream.height,
1678 android_convertGralloc1To0Usage(
1679 static_cast<uint64_t>(halStream.producerUsage),
1680 static_cast<uint64_t>(halStream.consumerUsage)),
1681 halStream.overrideFormat, &buffer_handle);
1682 graphicBuffers.push_back(buffer_handle);
1683 outputBuffers[k] = {
1684 halStream.id, bufferId, ::android::makeToAidl(buffer_handle),
1685 BufferStatus::OK, NativeHandle(), NativeHandle()};
1686 bufferId++;
1687 }
1688 k++;
1689 }
1690
1691 std::vector<PhysicalCameraSetting> camSettings(1);
1692 const camera_metadata_t* filteredSettingsBuffer = filteredSettings.getAndLock();
1693 uint8_t* rawFilteredSettingsBuffer = (uint8_t*)filteredSettingsBuffer;
1694 camSettings[0].settings = {std::vector(
1695 rawFilteredSettingsBuffer,
1696 rawFilteredSettingsBuffer + get_camera_metadata_size(filteredSettingsBuffer))};
1697 overrideRotateAndCrop(&camSettings[0].settings);
1698 camSettings[0].fmqSettingsSize = 0;
1699 camSettings[0].physicalCameraId = physicalDeviceId;
1700
1701 request.inputBuffer = {
1702 -1, 0, NativeHandle(), BufferStatus::ERROR, NativeHandle(), NativeHandle()};
1703 request.physicalCameraSettings = camSettings;
1704
1705 {
1706 std::unique_lock<std::mutex> l(mLock);
1707 mInflightMap.clear();
1708 mInflightMap[frameNumber] = inflightReq;
1709 }
1710
1711 int32_t numRequestProcessed = 0;
1712 std::vector<BufferCache> cachesToRemove;
1713 ndk::ScopedAStatus returnStatus =
1714 mSession->processCaptureRequest(requests, cachesToRemove, &numRequestProcessed);
1715 ASSERT_TRUE(returnStatus.isOk());
1716 ASSERT_EQ(numRequestProcessed, 1u);
1717
1718 {
1719 std::unique_lock<std::mutex> l(mLock);
1720 while (!inflightReq->errorCodeValid &&
1721 ((0 < inflightReq->numBuffersLeft) || (!inflightReq->haveResultMetadata))) {
1722 auto timeout = std::chrono::system_clock::now() +
1723 std::chrono::seconds(kStreamBufferTimeoutSec);
1724 ASSERT_NE(std::cv_status::timeout, mResultCondition.wait_until(l, timeout));
1725 }
1726
1727 ASSERT_FALSE(inflightReq->errorCodeValid);
1728 ASSERT_NE(inflightReq->resultOutputBuffers.size(), 0u);
1729
1730 request.frameNumber++;
1731 // Empty settings should be supported after the first call
1732 // for repeating requests.
1733 request.settings.metadata.clear();
1734 request.physicalCameraSettings[0].settings.metadata.clear();
1735 // The buffer has been registered to HAL by bufferId, so per
1736 // API contract we should send a null handle for this buffer
1737 request.outputBuffers[0].buffer = NativeHandle();
1738 mInflightMap.clear();
1739 inflightReq = std::make_shared<InFlightRequest>(
1740 static_cast<ssize_t>(physicalIds.size()), false, supportsPartialResults,
1741 partialResultCount, physicalIds, resultQueue);
1742 mInflightMap[request.frameNumber] = inflightReq;
1743 }
1744
1745 returnStatus =
1746 mSession->processCaptureRequest(requests, cachesToRemove, &numRequestProcessed);
1747 ASSERT_TRUE(returnStatus.isOk());
1748 ASSERT_EQ(numRequestProcessed, 1u);
1749
1750 {
1751 std::unique_lock<std::mutex> l(mLock);
1752 while (!inflightReq->errorCodeValid &&
1753 ((0 < inflightReq->numBuffersLeft) || (!inflightReq->haveResultMetadata))) {
1754 auto timeout = std::chrono::system_clock::now() +
1755 std::chrono::seconds(kStreamBufferTimeoutSec);
1756 ASSERT_NE(std::cv_status::timeout, mResultCondition.wait_until(l, timeout));
1757 }
1758
1759 ASSERT_FALSE(inflightReq->errorCodeValid);
1760 ASSERT_NE(inflightReq->resultOutputBuffers.size(), 0u);
1761 }
1762
1763 // Invalid physical camera id should fail process requests
1764 frameNumber++;
1765 camSettings[0].physicalCameraId = invalidPhysicalId;
1766 camSettings[0].settings.metadata = settings;
1767
1768 request.physicalCameraSettings = camSettings; // Invalid camera settings
1769 returnStatus =
1770 mSession->processCaptureRequest(requests, cachesToRemove, &numRequestProcessed);
1771 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT),
1772 returnStatus.getServiceSpecificError());
1773
1774 defaultPreviewSettings.unlock(settingsBuffer);
1775 filteredSettings.unlock(filteredSettingsBuffer);
1776
Jayant Chowdhary4869ae72023-12-18 05:36:14 +00001777 if (halBufManagedStreamIds.size() != 0) {
1778 std::vector<int32_t> streamIds;
1779 for (size_t i = 0; i < halStreams.size(); i++) {
1780 int32_t streamId = halStreams[i].id;
1781 if (halBufManagedStreamIds.find(streamId) != halBufManagedStreamIds.end()) {
1782 streamIds.emplace_back(streamId);
1783 }
Avichal Rakesh362242f2022-02-08 12:40:53 -08001784 }
1785 verifyBuffersReturned(mSession, streamIds, cb);
1786 }
1787
1788 ret = mSession->close();
1789 mSession = nullptr;
1790 ASSERT_TRUE(ret.isOk());
1791 }
1792}
1793
1794// Generate and verify an ultra high resolution capture request
1795TEST_P(CameraAidlTest, processUltraHighResolutionRequest) {
1796 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
1797 int64_t bufferId = 1;
1798 int32_t frameNumber = 1;
1799 CameraMetadata settings;
1800
1801 for (const auto& name : cameraDeviceNames) {
1802 std::string version, deviceId;
1803 ASSERT_TRUE(matchDeviceName(name, mProviderType, &version, &deviceId));
1804 CameraMetadata meta;
1805
1806 std::shared_ptr<ICameraDevice> unusedDevice;
1807 openEmptyDeviceSession(name, mProvider, &mSession, &meta, &unusedDevice);
1808 camera_metadata_t* staticMeta = reinterpret_cast<camera_metadata_t*>(meta.metadata.data());
1809 if (!isUltraHighResolution(staticMeta)) {
1810 ndk::ScopedAStatus ret = mSession->close();
1811 mSession = nullptr;
1812 ASSERT_TRUE(ret.isOk());
1813 continue;
1814 }
1815 CameraMetadata req;
1816 android::hardware::camera::common::V1_0::helper::CameraMetadata defaultSettings;
1817 ndk::ScopedAStatus ret =
1818 mSession->constructDefaultRequestSettings(RequestTemplate::STILL_CAPTURE, &req);
1819 ASSERT_TRUE(ret.isOk());
1820
1821 const camera_metadata_t* metadata =
1822 reinterpret_cast<const camera_metadata_t*>(req.metadata.data());
1823 size_t expectedSize = req.metadata.size();
1824 int result = validate_camera_metadata_structure(metadata, &expectedSize);
1825 ASSERT_TRUE((result == 0) || (result == CAMERA_METADATA_VALIDATION_SHIFTED));
1826
1827 size_t entryCount = get_camera_metadata_entry_count(metadata);
1828 ASSERT_GT(entryCount, 0u);
1829 defaultSettings = metadata;
1830 uint8_t sensorPixelMode =
1831 static_cast<uint8_t>(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION);
1832 ASSERT_EQ(::android::OK,
1833 defaultSettings.update(ANDROID_SENSOR_PIXEL_MODE, &sensorPixelMode, 1));
1834
1835 const camera_metadata_t* settingsBuffer = defaultSettings.getAndLock();
1836 uint8_t* rawSettingsBuffer = (uint8_t*)settingsBuffer;
1837 settings.metadata = std::vector(
1838 rawSettingsBuffer, rawSettingsBuffer + get_camera_metadata_size(settingsBuffer));
1839 overrideRotateAndCrop(&settings);
1840
1841 ret = mSession->close();
1842 mSession = nullptr;
1843 ASSERT_TRUE(ret.isOk());
1844
1845 std::vector<HalStream> halStreams;
1846 bool supportsPartialResults = false;
Jayant Chowdhary4869ae72023-12-18 05:36:14 +00001847 std::set<int32_t> halBufManagedStreamIds;
Avichal Rakesh362242f2022-02-08 12:40:53 -08001848 int32_t partialResultCount = 0;
1849 Stream previewStream;
1850 std::shared_ptr<DeviceCb> cb;
1851
1852 std::list<PixelFormat> pixelFormats = {PixelFormat::YCBCR_420_888, PixelFormat::RAW16};
1853 for (PixelFormat format : pixelFormats) {
Emilian Peevdda1eb72022-07-28 16:37:40 -07001854 previewStream.usage =
1855 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
1856 GRALLOC1_CONSUMER_USAGE_CPU_READ);
1857 previewStream.dataSpace = Dataspace::UNKNOWN;
Avichal Rakesh362242f2022-02-08 12:40:53 -08001858 configureStreams(name, mProvider, format, &mSession, &previewStream, &halStreams,
Jayant Chowdhary4869ae72023-12-18 05:36:14 +00001859 &supportsPartialResults, &partialResultCount, &halBufManagedStreamIds,
1860 &cb, 0, /*maxResolution*/ true);
Avichal Rakesh362242f2022-02-08 12:40:53 -08001861 ASSERT_NE(mSession, nullptr);
1862
1863 ::aidl::android::hardware::common::fmq::MQDescriptor<
1864 int8_t, aidl::android::hardware::common::fmq::SynchronizedReadWrite>
1865 descriptor;
1866 auto resultQueueRet = mSession->getCaptureResultMetadataQueue(&descriptor);
1867 ASSERT_TRUE(resultQueueRet.isOk());
1868
1869 std::shared_ptr<ResultMetadataQueue> resultQueue =
1870 std::make_shared<ResultMetadataQueue>(descriptor);
1871 if (!resultQueue->isValid() || resultQueue->availableToWrite() <= 0) {
1872 ALOGE("%s: HAL returns empty result metadata fmq, not use it", __func__);
1873 resultQueue = nullptr;
1874 // Don't use the queue onwards.
1875 }
1876
1877 std::vector<buffer_handle_t> graphicBuffers;
1878 graphicBuffers.reserve(halStreams.size());
1879 std::shared_ptr<InFlightRequest> inflightReq = std::make_shared<InFlightRequest>(
1880 static_cast<ssize_t>(halStreams.size()), false, supportsPartialResults,
1881 partialResultCount, std::unordered_set<std::string>(), resultQueue);
1882
1883 std::vector<CaptureRequest> requests(1);
1884 CaptureRequest& request = requests[0];
1885 std::vector<StreamBuffer>& outputBuffers = request.outputBuffers;
1886 outputBuffers.resize(halStreams.size());
1887
1888 size_t k = 0;
1889 for (const auto& halStream : halStreams) {
1890 buffer_handle_t buffer_handle;
Jayant Chowdhary4869ae72023-12-18 05:36:14 +00001891 bool halBufManagerUsed =
1892 halBufManagedStreamIds.find(halStream.id) != halBufManagedStreamIds.end();
1893 if (halBufManagerUsed) {
Avichal Rakesh362242f2022-02-08 12:40:53 -08001894 outputBuffers[k] = {halStream.id, 0,
1895 NativeHandle(), BufferStatus::OK,
1896 NativeHandle(), NativeHandle()};
1897 } else {
1898 allocateGraphicBuffer(previewStream.width, previewStream.height,
1899 android_convertGralloc1To0Usage(
1900 static_cast<uint64_t>(halStream.producerUsage),
1901 static_cast<uint64_t>(halStream.consumerUsage)),
1902 halStream.overrideFormat, &buffer_handle);
1903 graphicBuffers.push_back(buffer_handle);
1904 outputBuffers[k] = {
1905 halStream.id, bufferId, ::android::makeToAidl(buffer_handle),
1906 BufferStatus::OK, NativeHandle(), NativeHandle()};
1907 bufferId++;
1908 }
1909 k++;
1910 }
1911
1912 request.inputBuffer = {
1913 -1, 0, NativeHandle(), BufferStatus::ERROR, NativeHandle(), NativeHandle()};
1914 request.frameNumber = frameNumber;
1915 request.fmqSettingsSize = 0;
1916 request.settings = settings;
1917 request.inputWidth = 0;
1918 request.inputHeight = 0;
1919
1920 {
1921 std::unique_lock<std::mutex> l(mLock);
1922 mInflightMap.clear();
1923 mInflightMap[frameNumber] = inflightReq;
1924 }
1925
1926 int32_t numRequestProcessed = 0;
1927 std::vector<BufferCache> cachesToRemove;
1928 ndk::ScopedAStatus returnStatus =
1929 mSession->processCaptureRequest(requests, cachesToRemove, &numRequestProcessed);
1930 ASSERT_TRUE(returnStatus.isOk());
1931 ASSERT_EQ(numRequestProcessed, 1u);
1932
1933 {
1934 std::unique_lock<std::mutex> l(mLock);
1935 while (!inflightReq->errorCodeValid &&
1936 ((0 < inflightReq->numBuffersLeft) || (!inflightReq->haveResultMetadata))) {
1937 auto timeout = std::chrono::system_clock::now() +
1938 std::chrono::seconds(kStreamBufferTimeoutSec);
1939 ASSERT_NE(std::cv_status::timeout, mResultCondition.wait_until(l, timeout));
1940 }
1941
1942 ASSERT_FALSE(inflightReq->errorCodeValid);
1943 ASSERT_NE(inflightReq->resultOutputBuffers.size(), 0u);
1944 }
Jayant Chowdhary4869ae72023-12-18 05:36:14 +00001945 if (halBufManagedStreamIds.size()) {
1946 std::vector<int32_t> streamIds;
1947 for (size_t i = 0; i < halStreams.size(); i++) {
1948 if (contains(halBufManagedStreamIds, halStreams[i].id)) {
1949 streamIds.emplace_back(halStreams[i].id);
1950 }
Avichal Rakesh362242f2022-02-08 12:40:53 -08001951 }
1952 verifyBuffersReturned(mSession, streamIds, cb);
1953 }
1954
1955 ret = mSession->close();
1956 mSession = nullptr;
1957 ASSERT_TRUE(ret.isOk());
1958 }
1959 }
1960}
1961
1962// Generate and verify 10-bit dynamic range request
1963TEST_P(CameraAidlTest, process10BitDynamicRangeRequest) {
1964 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
Avichal Rakesh362242f2022-02-08 12:40:53 -08001965 CameraMetadata settings;
1966
1967 for (const auto& name : cameraDeviceNames) {
1968 std::string version, deviceId;
1969 ASSERT_TRUE(matchDeviceName(name, mProviderType, &version, &deviceId));
1970 CameraMetadata meta;
1971 std::shared_ptr<ICameraDevice> device;
1972 openEmptyDeviceSession(name, mProvider, &mSession, &meta, &device);
1973 camera_metadata_t* staticMeta = reinterpret_cast<camera_metadata_t*>(meta.metadata.data());
1974 if (!is10BitDynamicRangeCapable(staticMeta)) {
1975 ndk::ScopedAStatus ret = mSession->close();
1976 mSession = nullptr;
1977 ASSERT_TRUE(ret.isOk());
1978 continue;
1979 }
Avichal Rakeshd3503a32022-02-25 06:23:14 +00001980 std::vector<RequestAvailableDynamicRangeProfilesMap> profileList;
Avichal Rakesh362242f2022-02-08 12:40:53 -08001981 get10BitDynamicRangeProfiles(staticMeta, &profileList);
1982 ASSERT_FALSE(profileList.empty());
1983
1984 CameraMetadata req;
1985 android::hardware::camera::common::V1_0::helper::CameraMetadata defaultSettings;
1986 ndk::ScopedAStatus ret =
Emilian Peevdda1eb72022-07-28 16:37:40 -07001987 mSession->constructDefaultRequestSettings(RequestTemplate::PREVIEW, &req);
Avichal Rakesh362242f2022-02-08 12:40:53 -08001988 ASSERT_TRUE(ret.isOk());
1989
1990 const camera_metadata_t* metadata =
1991 reinterpret_cast<const camera_metadata_t*>(req.metadata.data());
1992 size_t expectedSize = req.metadata.size();
1993 int result = validate_camera_metadata_structure(metadata, &expectedSize);
1994 ASSERT_TRUE((result == 0) || (result == CAMERA_METADATA_VALIDATION_SHIFTED));
1995
1996 size_t entryCount = get_camera_metadata_entry_count(metadata);
1997 ASSERT_GT(entryCount, 0u);
1998 defaultSettings = metadata;
1999
2000 const camera_metadata_t* settingsBuffer = defaultSettings.getAndLock();
2001 uint8_t* rawSettingsBuffer = (uint8_t*)settingsBuffer;
2002 settings.metadata = std::vector(
2003 rawSettingsBuffer, rawSettingsBuffer + get_camera_metadata_size(settingsBuffer));
2004 overrideRotateAndCrop(&settings);
2005
2006 ret = mSession->close();
2007 mSession = nullptr;
2008 ASSERT_TRUE(ret.isOk());
2009
2010 std::vector<HalStream> halStreams;
2011 bool supportsPartialResults = false;
Jayant Chowdhary4869ae72023-12-18 05:36:14 +00002012 std::set<int32_t> halBufManagedStreamIds;
Avichal Rakesh362242f2022-02-08 12:40:53 -08002013 int32_t partialResultCount = 0;
2014 Stream previewStream;
2015 std::shared_ptr<DeviceCb> cb;
2016 for (const auto& profile : profileList) {
Emilian Peevdda1eb72022-07-28 16:37:40 -07002017 previewStream.usage =
2018 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
2019 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER);
2020 previewStream.dataSpace = getDataspace(PixelFormat::IMPLEMENTATION_DEFINED);
Avichal Rakesh362242f2022-02-08 12:40:53 -08002021 configureStreams(name, mProvider, PixelFormat::IMPLEMENTATION_DEFINED, &mSession,
2022 &previewStream, &halStreams, &supportsPartialResults,
Jayant Chowdhary4869ae72023-12-18 05:36:14 +00002023 &partialResultCount, &halBufManagedStreamIds, &cb, 0,
Avichal Rakesh362242f2022-02-08 12:40:53 -08002024 /*maxResolution*/ false, profile);
2025 ASSERT_NE(mSession, nullptr);
2026
2027 ::aidl::android::hardware::common::fmq::MQDescriptor<
2028 int8_t, aidl::android::hardware::common::fmq::SynchronizedReadWrite>
2029 descriptor;
2030 auto resultQueueRet = mSession->getCaptureResultMetadataQueue(&descriptor);
2031 ASSERT_TRUE(resultQueueRet.isOk());
2032
2033 std::shared_ptr<ResultMetadataQueue> resultQueue =
2034 std::make_shared<ResultMetadataQueue>(descriptor);
2035 if (!resultQueue->isValid() || resultQueue->availableToWrite() <= 0) {
2036 ALOGE("%s: HAL returns empty result metadata fmq, not use it", __func__);
2037 resultQueue = nullptr;
2038 // Don't use the queue onwards.
2039 }
2040
Emilian Peevdda1eb72022-07-28 16:37:40 -07002041 mInflightMap.clear();
2042 // Stream as long as needed to fill the Hal inflight queue
2043 std::vector<CaptureRequest> requests(halStreams[0].maxBuffers);
Avichal Rakesh362242f2022-02-08 12:40:53 -08002044
Emilian Peev470d1382023-01-18 11:09:09 -08002045 for (int32_t requestId = 0; requestId < requests.size(); requestId++) {
Emilian Peevdda1eb72022-07-28 16:37:40 -07002046 std::shared_ptr<InFlightRequest> inflightReq = std::make_shared<InFlightRequest>(
2047 static_cast<ssize_t>(halStreams.size()), false, supportsPartialResults,
2048 partialResultCount, std::unordered_set<std::string>(), resultQueue);
Avichal Rakesh362242f2022-02-08 12:40:53 -08002049
Emilian Peev470d1382023-01-18 11:09:09 -08002050 CaptureRequest& request = requests[requestId];
Emilian Peevdda1eb72022-07-28 16:37:40 -07002051 std::vector<StreamBuffer>& outputBuffers = request.outputBuffers;
2052 outputBuffers.resize(halStreams.size());
Avichal Rakesh362242f2022-02-08 12:40:53 -08002053
Emilian Peevdda1eb72022-07-28 16:37:40 -07002054 size_t k = 0;
2055 inflightReq->mOutstandingBufferIds.resize(halStreams.size());
2056 std::vector<buffer_handle_t> graphicBuffers;
2057 graphicBuffers.reserve(halStreams.size());
Avichal Rakesh362242f2022-02-08 12:40:53 -08002058
Emilian Peev470d1382023-01-18 11:09:09 -08002059 auto bufferId = requestId + 1; // Buffer id value 0 is not valid
Emilian Peevdda1eb72022-07-28 16:37:40 -07002060 for (const auto& halStream : halStreams) {
2061 buffer_handle_t buffer_handle;
Jayant Chowdhary4869ae72023-12-18 05:36:14 +00002062 if (contains(halBufManagedStreamIds, halStream.id)) {
Emilian Peevdda1eb72022-07-28 16:37:40 -07002063 outputBuffers[k] = {halStream.id, 0,
2064 NativeHandle(), BufferStatus::OK,
2065 NativeHandle(), NativeHandle()};
2066 } else {
2067 auto usage = android_convertGralloc1To0Usage(
2068 static_cast<uint64_t>(halStream.producerUsage),
2069 static_cast<uint64_t>(halStream.consumerUsage));
2070 allocateGraphicBuffer(previewStream.width, previewStream.height, usage,
2071 halStream.overrideFormat, &buffer_handle);
2072
2073 inflightReq->mOutstandingBufferIds[halStream.id][bufferId] = buffer_handle;
2074 graphicBuffers.push_back(buffer_handle);
2075 outputBuffers[k] = {halStream.id, bufferId,
2076 android::makeToAidl(buffer_handle), BufferStatus::OK, NativeHandle(),
2077 NativeHandle()};
Emilian Peevdda1eb72022-07-28 16:37:40 -07002078 }
2079 k++;
Avichal Rakesh362242f2022-02-08 12:40:53 -08002080 }
Avichal Rakesh362242f2022-02-08 12:40:53 -08002081
Emilian Peevdda1eb72022-07-28 16:37:40 -07002082 request.inputBuffer = {
2083 -1, 0, NativeHandle(), BufferStatus::ERROR, NativeHandle(), NativeHandle()};
Emilian Peev470d1382023-01-18 11:09:09 -08002084 request.frameNumber = bufferId;
Emilian Peevdda1eb72022-07-28 16:37:40 -07002085 request.fmqSettingsSize = 0;
2086 request.settings = settings;
2087 request.inputWidth = 0;
2088 request.inputHeight = 0;
Avichal Rakesh362242f2022-02-08 12:40:53 -08002089
Emilian Peevdda1eb72022-07-28 16:37:40 -07002090 {
2091 std::unique_lock<std::mutex> l(mLock);
Emilian Peev470d1382023-01-18 11:09:09 -08002092 mInflightMap[bufferId] = inflightReq;
Emilian Peevdda1eb72022-07-28 16:37:40 -07002093 }
2094
Avichal Rakesh362242f2022-02-08 12:40:53 -08002095 }
2096
2097 int32_t numRequestProcessed = 0;
2098 std::vector<BufferCache> cachesToRemove;
2099 ndk::ScopedAStatus returnStatus =
Emilian Peevdda1eb72022-07-28 16:37:40 -07002100 mSession->processCaptureRequest(requests, cachesToRemove, &numRequestProcessed);
Avichal Rakesh362242f2022-02-08 12:40:53 -08002101 ASSERT_TRUE(returnStatus.isOk());
Emilian Peevdda1eb72022-07-28 16:37:40 -07002102 ASSERT_EQ(numRequestProcessed, requests.size());
Avichal Rakesh362242f2022-02-08 12:40:53 -08002103
Emilian Peevdda1eb72022-07-28 16:37:40 -07002104 returnStatus = mSession->repeatingRequestEnd(requests.size() - 1,
2105 std::vector<int32_t> {halStreams[0].id});
2106 ASSERT_TRUE(returnStatus.isOk());
2107
Emilian Peev470d1382023-01-18 11:09:09 -08002108 // We are keeping frame numbers and buffer ids consistent. Buffer id value of 0
2109 // is used to indicate a buffer that is not present/available so buffer ids as well
2110 // as frame numbers begin with 1.
2111 for (int32_t frameNumber = 1; frameNumber <= requests.size(); frameNumber++) {
Emilian Peevdda1eb72022-07-28 16:37:40 -07002112 const auto& inflightReq = mInflightMap[frameNumber];
Avichal Rakesh362242f2022-02-08 12:40:53 -08002113 std::unique_lock<std::mutex> l(mLock);
2114 while (!inflightReq->errorCodeValid &&
2115 ((0 < inflightReq->numBuffersLeft) || (!inflightReq->haveResultMetadata))) {
2116 auto timeout = std::chrono::system_clock::now() +
2117 std::chrono::seconds(kStreamBufferTimeoutSec);
2118 ASSERT_NE(std::cv_status::timeout, mResultCondition.wait_until(l, timeout));
2119 }
2120
Shuzhen Wang0f56c562023-04-03 16:58:59 -07002121 waitForReleaseFence(inflightReq->resultOutputBuffers);
2122
Avichal Rakesh362242f2022-02-08 12:40:53 -08002123 ASSERT_FALSE(inflightReq->errorCodeValid);
2124 ASSERT_NE(inflightReq->resultOutputBuffers.size(), 0u);
2125 verify10BitMetadata(mHandleImporter, *inflightReq, profile);
2126 }
Emilian Peevdda1eb72022-07-28 16:37:40 -07002127
Jayant Chowdhary4869ae72023-12-18 05:36:14 +00002128 if (halBufManagedStreamIds.size() != 0) {
2129 std::vector<int32_t> streamIds;
2130 for (size_t i = 0; i < halStreams.size(); i++) {
2131 if (contains(halBufManagedStreamIds, halStreams[i].id)) {
2132 streamIds.emplace_back(halStreams[i].id);
2133 }
Avichal Rakesh362242f2022-02-08 12:40:53 -08002134 }
2135 mSession->signalStreamFlush(streamIds, /*streamConfigCounter*/ 0);
2136 cb->waitForBuffersReturned();
2137 }
2138
2139 ret = mSession->close();
2140 mSession = nullptr;
2141 ASSERT_TRUE(ret.isOk());
2142 }
2143 }
2144}
2145
Austin Borger4728fc42022-07-15 11:27:53 -07002146TEST_P(CameraAidlTest, process8BitColorSpaceRequests) {
Austin Borger54b22362023-03-22 11:25:06 -07002147 static int profiles[] = {ColorSpaceNamed::DISPLAY_P3, ColorSpaceNamed::SRGB};
Austin Borger4728fc42022-07-15 11:27:53 -07002148
2149 for (int32_t i = 0; i < sizeof(profiles) / sizeof(profiles[0]); i++) {
2150 processColorSpaceRequest(static_cast<RequestAvailableColorSpaceProfilesMap>(profiles[i]),
2151 static_cast<RequestAvailableDynamicRangeProfilesMap>(
2152 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD));
2153 }
2154}
2155
2156TEST_P(CameraAidlTest, process10BitColorSpaceRequests) {
2157 static const camera_metadata_enum_android_request_available_dynamic_range_profiles_map
2158 dynamicRangeProfiles[] = {
2159 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HLG10,
2160 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10,
2161 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10_PLUS,
2162 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF,
2163 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF_PO,
2164 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM,
2165 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM_PO,
2166 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_REF,
2167 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_REF_PO,
2168 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_OEM,
2169 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_OEM_PO
2170 };
2171
Austin Borger54b22362023-03-22 11:25:06 -07002172 // Process all dynamic range profiles with BT2020_HLG
Austin Borger4728fc42022-07-15 11:27:53 -07002173 for (int32_t i = 0; i < sizeof(dynamicRangeProfiles) / sizeof(dynamicRangeProfiles[0]); i++) {
2174 processColorSpaceRequest(
Austin Borger54b22362023-03-22 11:25:06 -07002175 static_cast<RequestAvailableColorSpaceProfilesMap>(ColorSpaceNamed::BT2020_HLG),
Austin Borger4728fc42022-07-15 11:27:53 -07002176 static_cast<RequestAvailableDynamicRangeProfilesMap>(dynamicRangeProfiles[i]));
2177 }
2178}
2179
Shuzhen Wang4dd6a512022-11-08 20:47:20 +00002180TEST_P(CameraAidlTest, processZoomSettingsOverrideRequests) {
2181 const int32_t kFrameCount = 5;
2182 const int32_t kTestCases = 2;
Shuzhen Wang38ddb272023-05-22 09:40:28 -07002183 const bool kOverrideSequence[kTestCases][kFrameCount] = {// ZOOM, ZOOM, ZOOM, ZOOM, ZOOM;
2184 {true, true, true, true, true},
2185 // OFF, ZOOM, ZOOM, ZOOM, OFF;
2186 {false, true, true, true, false}};
Shuzhen Wang4dd6a512022-11-08 20:47:20 +00002187 const bool kExpectedOverrideResults[kTestCases][kFrameCount] = {
Shuzhen Wang38ddb272023-05-22 09:40:28 -07002188 // All resuls should be overridden except the last one. The last result's
2189 // zoom doesn't have speed-up.
2190 {true, true, true, true, false},
2191 // Because we require at least 1 frame speed-up, request #1, #2 and #3
2192 // will be overridden.
2193 {true, true, true, false, false}};
Shuzhen Wang4dd6a512022-11-08 20:47:20 +00002194
2195 for (int i = 0; i < kTestCases; i++) {
2196 processZoomSettingsOverrideRequests(kFrameCount, kOverrideSequence[i],
2197 kExpectedOverrideResults[i]);
2198 }
2199}
2200
Avichal Rakesh362242f2022-02-08 12:40:53 -08002201// Generate and verify a burst containing alternating sensor sensitivity values
2202TEST_P(CameraAidlTest, processCaptureRequestBurstISO) {
2203 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
2204 AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
2205 static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
2206 int64_t bufferId = 1;
2207 int32_t frameNumber = 1;
2208 float isoTol = .03f;
2209 CameraMetadata settings;
2210
2211 for (const auto& name : cameraDeviceNames) {
2212 CameraMetadata meta;
2213 settings.metadata.clear();
2214 std::shared_ptr<ICameraDevice> unusedDevice;
2215 openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/,
2216 &unusedDevice /*out*/);
2217 camera_metadata_t* staticMetaBuffer =
2218 clone_camera_metadata(reinterpret_cast<camera_metadata_t*>(meta.metadata.data()));
2219 ::android::hardware::camera::common::V1_0::helper::CameraMetadata staticMeta(
2220 staticMetaBuffer);
2221
2222 camera_metadata_entry_t hwLevel = staticMeta.find(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL);
2223 ASSERT_TRUE(0 < hwLevel.count);
2224 if (ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED == hwLevel.data.u8[0] ||
2225 ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL == hwLevel.data.u8[0]) {
2226 // Limited/External devices can skip this test
2227 ndk::ScopedAStatus ret = mSession->close();
2228 mSession = nullptr;
2229 ASSERT_TRUE(ret.isOk());
2230 continue;
2231 }
2232
2233 camera_metadata_entry_t isoRange = staticMeta.find(ANDROID_SENSOR_INFO_SENSITIVITY_RANGE);
2234 ASSERT_EQ(isoRange.count, 2u);
2235
2236 ndk::ScopedAStatus ret = mSession->close();
2237 mSession = nullptr;
2238 ASSERT_TRUE(ret.isOk());
2239
2240 bool supportsPartialResults = false;
2241 bool useHalBufManager = false;
2242 int32_t partialResultCount = 0;
2243 Stream previewStream;
2244 std::vector<HalStream> halStreams;
2245 std::shared_ptr<DeviceCb> cb;
2246 configurePreviewStream(name, mProvider, &previewThreshold, &mSession /*out*/,
2247 &previewStream /*out*/, &halStreams /*out*/,
2248 &supportsPartialResults /*out*/, &partialResultCount /*out*/,
2249 &useHalBufManager /*out*/, &cb /*out*/);
2250
2251 ::aidl::android::hardware::common::fmq::MQDescriptor<
2252 int8_t, aidl::android::hardware::common::fmq::SynchronizedReadWrite>
2253 descriptor;
2254 auto resultQueueRet = mSession->getCaptureResultMetadataQueue(&descriptor);
2255 std::shared_ptr<ResultMetadataQueue> resultQueue =
2256 std::make_shared<ResultMetadataQueue>(descriptor);
2257 ASSERT_TRUE(resultQueueRet.isOk());
2258 if (!resultQueue->isValid() || resultQueue->availableToWrite() <= 0) {
2259 ALOGE("%s: HAL returns empty result metadata fmq, not use it", __func__);
2260 resultQueue = nullptr;
2261 // Don't use the queue onwards.
2262 }
2263
2264 ret = mSession->constructDefaultRequestSettings(RequestTemplate::PREVIEW, &settings);
2265 ASSERT_TRUE(ret.isOk());
2266
2267 ::android::hardware::camera::common::V1_0::helper::CameraMetadata requestMeta;
2268 std::vector<CaptureRequest> requests(kBurstFrameCount);
2269 std::vector<buffer_handle_t> buffers(kBurstFrameCount);
2270 std::vector<std::shared_ptr<InFlightRequest>> inflightReqs(kBurstFrameCount);
2271 std::vector<int32_t> isoValues(kBurstFrameCount);
2272 std::vector<CameraMetadata> requestSettings(kBurstFrameCount);
2273
2274 for (int32_t i = 0; i < kBurstFrameCount; i++) {
2275 std::unique_lock<std::mutex> l(mLock);
2276 CaptureRequest& request = requests[i];
2277 std::vector<StreamBuffer>& outputBuffers = request.outputBuffers;
2278 outputBuffers.resize(1);
2279 StreamBuffer& outputBuffer = outputBuffers[0];
2280
2281 isoValues[i] = ((i % 2) == 0) ? isoRange.data.i32[0] : isoRange.data.i32[1];
2282 if (useHalBufManager) {
2283 outputBuffer = {halStreams[0].id, 0,
2284 NativeHandle(), BufferStatus::OK,
2285 NativeHandle(), NativeHandle()};
2286 } else {
2287 allocateGraphicBuffer(previewStream.width, previewStream.height,
2288 android_convertGralloc1To0Usage(
2289 static_cast<uint64_t>(halStreams[0].producerUsage),
2290 static_cast<uint64_t>(halStreams[0].consumerUsage)),
2291 halStreams[0].overrideFormat, &buffers[i]);
2292 outputBuffer = {halStreams[0].id, bufferId + i, ::android::makeToAidl(buffers[i]),
2293 BufferStatus::OK, NativeHandle(), NativeHandle()};
2294 }
2295
2296 requestMeta.append(reinterpret_cast<camera_metadata_t*>(settings.metadata.data()));
2297
2298 // Disable all 3A routines
2299 uint8_t mode = static_cast<uint8_t>(ANDROID_CONTROL_MODE_OFF);
2300 ASSERT_EQ(::android::OK, requestMeta.update(ANDROID_CONTROL_MODE, &mode, 1));
2301 ASSERT_EQ(::android::OK,
2302 requestMeta.update(ANDROID_SENSOR_SENSITIVITY, &isoValues[i], 1));
2303 camera_metadata_t* metaBuffer = requestMeta.release();
2304 uint8_t* rawMetaBuffer = reinterpret_cast<uint8_t*>(metaBuffer);
2305 requestSettings[i].metadata = std::vector(
2306 rawMetaBuffer, rawMetaBuffer + get_camera_metadata_size(metaBuffer));
2307 overrideRotateAndCrop(&(requestSettings[i]));
2308
2309 request.frameNumber = frameNumber + i;
2310 request.fmqSettingsSize = 0;
2311 request.settings = requestSettings[i];
2312 request.inputBuffer = {
2313 -1, 0, NativeHandle(), BufferStatus::ERROR, NativeHandle(), NativeHandle()};
2314
2315 inflightReqs[i] = std::make_shared<InFlightRequest>(1, false, supportsPartialResults,
2316 partialResultCount, resultQueue);
2317 mInflightMap[frameNumber + i] = inflightReqs[i];
2318 }
2319
2320 int32_t numRequestProcessed = 0;
2321 std::vector<BufferCache> cachesToRemove;
2322
2323 ndk::ScopedAStatus returnStatus =
2324 mSession->processCaptureRequest(requests, cachesToRemove, &numRequestProcessed);
2325 ASSERT_TRUE(returnStatus.isOk());
2326 ASSERT_EQ(numRequestProcessed, kBurstFrameCount);
2327
2328 for (size_t i = 0; i < kBurstFrameCount; i++) {
2329 std::unique_lock<std::mutex> l(mLock);
2330 while (!inflightReqs[i]->errorCodeValid && ((0 < inflightReqs[i]->numBuffersLeft) ||
2331 (!inflightReqs[i]->haveResultMetadata))) {
2332 auto timeout = std::chrono::system_clock::now() +
2333 std::chrono::seconds(kStreamBufferTimeoutSec);
2334 ASSERT_NE(std::cv_status::timeout, mResultCondition.wait_until(l, timeout));
2335 }
2336
2337 ASSERT_FALSE(inflightReqs[i]->errorCodeValid);
2338 ASSERT_NE(inflightReqs[i]->resultOutputBuffers.size(), 0u);
2339 ASSERT_EQ(previewStream.id, inflightReqs[i]->resultOutputBuffers[0].buffer.streamId);
2340 ASSERT_FALSE(inflightReqs[i]->collectedResult.isEmpty());
2341 ASSERT_TRUE(inflightReqs[i]->collectedResult.exists(ANDROID_SENSOR_SENSITIVITY));
2342 camera_metadata_entry_t isoResult =
2343 inflightReqs[i]->collectedResult.find(ANDROID_SENSOR_SENSITIVITY);
2344 ASSERT_TRUE(std::abs(isoResult.data.i32[0] - isoValues[i]) <=
2345 std::round(isoValues[i] * isoTol));
2346 }
2347
2348 if (useHalBufManager) {
2349 verifyBuffersReturned(mSession, previewStream.id, cb);
2350 }
2351 ret = mSession->close();
2352 mSession = nullptr;
2353 ASSERT_TRUE(ret.isOk());
2354 }
2355}
2356
2357// Test whether an incorrect capture request with missing settings will
2358// be reported correctly.
2359TEST_P(CameraAidlTest, processCaptureRequestInvalidSinglePreview) {
2360 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
2361 std::vector<AvailableStream> outputPreviewStreams;
2362 AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
2363 static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
2364 int64_t bufferId = 1;
2365 int32_t frameNumber = 1;
2366 CameraMetadata settings;
2367
2368 for (const auto& name : cameraDeviceNames) {
2369 Stream previewStream;
2370 std::vector<HalStream> halStreams;
2371 std::shared_ptr<DeviceCb> cb;
2372 bool supportsPartialResults = false;
2373 bool useHalBufManager = false;
2374 int32_t partialResultCount = 0;
2375 configurePreviewStream(name, mProvider, &previewThreshold, &mSession /*out*/,
2376 &previewStream /*out*/, &halStreams /*out*/,
2377 &supportsPartialResults /*out*/, &partialResultCount /*out*/,
2378 &useHalBufManager /*out*/, &cb /*out*/);
2379 ASSERT_NE(mSession, nullptr);
2380 ASSERT_FALSE(halStreams.empty());
2381
2382 buffer_handle_t buffer_handle = nullptr;
2383
2384 if (useHalBufManager) {
2385 bufferId = 0;
2386 } else {
2387 allocateGraphicBuffer(previewStream.width, previewStream.height,
2388 android_convertGralloc1To0Usage(
2389 static_cast<uint64_t>(halStreams[0].producerUsage),
2390 static_cast<uint64_t>(halStreams[0].consumerUsage)),
2391 halStreams[0].overrideFormat, &buffer_handle);
2392 }
2393
2394 std::vector<CaptureRequest> requests(1);
2395 CaptureRequest& request = requests[0];
2396 std::vector<StreamBuffer>& outputBuffers = request.outputBuffers;
2397 outputBuffers.resize(1);
2398 StreamBuffer& outputBuffer = outputBuffers[0];
2399
2400 outputBuffer = {
2401 halStreams[0].id,
2402 bufferId,
2403 buffer_handle == nullptr ? NativeHandle() : ::android::makeToAidl(buffer_handle),
2404 BufferStatus::OK,
2405 NativeHandle(),
2406 NativeHandle()};
2407
2408 request.inputBuffer = {
2409 -1, 0, NativeHandle(), BufferStatus::ERROR, NativeHandle(), NativeHandle()};
2410 request.frameNumber = frameNumber;
2411 request.fmqSettingsSize = 0;
2412 request.settings = settings;
2413
2414 // Settings were not correctly initialized, we should fail here
2415 int32_t numRequestProcessed = 0;
2416 std::vector<BufferCache> cachesToRemove;
2417 ndk::ScopedAStatus ret =
2418 mSession->processCaptureRequest(requests, cachesToRemove, &numRequestProcessed);
2419 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT), ret.getServiceSpecificError());
2420 ASSERT_EQ(numRequestProcessed, 0u);
2421
2422 ret = mSession->close();
2423 mSession = nullptr;
2424 ASSERT_TRUE(ret.isOk());
2425 }
2426}
2427
2428// Verify camera offline session behavior
2429TEST_P(CameraAidlTest, switchToOffline) {
2430 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
2431 AvailableStream threshold = {kMaxStillWidth, kMaxStillHeight,
2432 static_cast<int32_t>(PixelFormat::BLOB)};
2433 int64_t bufferId = 1;
2434 int32_t frameNumber = 1;
2435 CameraMetadata settings;
2436
2437 for (const auto& name : cameraDeviceNames) {
2438 CameraMetadata meta;
2439 {
2440 std::shared_ptr<ICameraDevice> unusedDevice;
2441 openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/,
2442 &unusedDevice);
2443 camera_metadata_t* staticMetaBuffer = clone_camera_metadata(
2444 reinterpret_cast<camera_metadata_t*>(meta.metadata.data()));
2445 ::android::hardware::camera::common::V1_0::helper::CameraMetadata staticMeta(
2446 staticMetaBuffer);
2447
2448 if (isOfflineSessionSupported(staticMetaBuffer) != Status::OK) {
2449 ndk::ScopedAStatus ret = mSession->close();
2450 mSession = nullptr;
2451 ASSERT_TRUE(ret.isOk());
2452 continue;
2453 }
2454 ndk::ScopedAStatus ret = mSession->close();
2455 mSession = nullptr;
2456 ASSERT_TRUE(ret.isOk());
2457 }
2458
2459 bool supportsPartialResults = false;
2460 int32_t partialResultCount = 0;
2461 Stream stream;
2462 std::vector<HalStream> halStreams;
2463 std::shared_ptr<DeviceCb> cb;
2464 int32_t jpegBufferSize;
Jayant Chowdhary4869ae72023-12-18 05:36:14 +00002465 std::set<int32_t> halBufManagedStreamIds;
Avichal Rakesh362242f2022-02-08 12:40:53 -08002466 configureOfflineStillStream(name, mProvider, &threshold, &mSession /*out*/, &stream /*out*/,
2467 &halStreams /*out*/, &supportsPartialResults /*out*/,
2468 &partialResultCount /*out*/, &cb /*out*/,
Jayant Chowdhary4869ae72023-12-18 05:36:14 +00002469 &jpegBufferSize /*out*/, &halBufManagedStreamIds /*out*/);
Avichal Rakesh362242f2022-02-08 12:40:53 -08002470
2471 auto ret = mSession->constructDefaultRequestSettings(RequestTemplate::STILL_CAPTURE,
2472 &settings);
2473 ASSERT_TRUE(ret.isOk());
2474
2475 ::aidl::android::hardware::common::fmq::MQDescriptor<
2476 int8_t, aidl::android::hardware::common::fmq::SynchronizedReadWrite>
2477 descriptor;
2478
2479 ndk::ScopedAStatus resultQueueRet = mSession->getCaptureResultMetadataQueue(&descriptor);
2480 ASSERT_TRUE(resultQueueRet.isOk());
2481 std::shared_ptr<ResultMetadataQueue> resultQueue =
2482 std::make_shared<ResultMetadataQueue>(descriptor);
2483 if (!resultQueue->isValid() || resultQueue->availableToWrite() <= 0) {
2484 ALOGE("%s: HAL returns empty result metadata fmq, not use it", __func__);
2485 resultQueue = nullptr;
2486 // Don't use the queue onwards.
2487 }
2488
2489 ::android::hardware::camera::common::V1_0::helper::CameraMetadata requestMeta;
2490
2491 std::vector<buffer_handle_t> buffers(kBurstFrameCount);
2492 std::vector<std::shared_ptr<InFlightRequest>> inflightReqs(kBurstFrameCount);
2493 std::vector<CameraMetadata> requestSettings(kBurstFrameCount);
2494
2495 std::vector<CaptureRequest> requests(kBurstFrameCount);
2496
2497 HalStream halStream = halStreams[0];
2498 for (uint32_t i = 0; i < kBurstFrameCount; i++) {
2499 CaptureRequest& request = requests[i];
2500 std::vector<StreamBuffer>& outputBuffers = request.outputBuffers;
2501 outputBuffers.resize(1);
2502 StreamBuffer& outputBuffer = outputBuffers[0];
2503
2504 std::unique_lock<std::mutex> l(mLock);
Jayant Chowdhary4869ae72023-12-18 05:36:14 +00002505 if (contains(halBufManagedStreamIds, halStream.id)) {
Avichal Rakesh362242f2022-02-08 12:40:53 -08002506 outputBuffer = {halStream.id, 0, NativeHandle(), BufferStatus::OK, NativeHandle(),
2507 NativeHandle()};
2508 } else {
2509 // jpeg buffer (w,h) = (blobLen, 1)
2510 allocateGraphicBuffer(jpegBufferSize, /*height*/ 1,
2511 android_convertGralloc1To0Usage(
2512 static_cast<uint64_t>(halStream.producerUsage),
2513 static_cast<uint64_t>(halStream.consumerUsage)),
2514 halStream.overrideFormat, &buffers[i]);
2515 outputBuffer = {halStream.id, bufferId + i, ::android::makeToAidl(buffers[i]),
2516 BufferStatus::OK, NativeHandle(), NativeHandle()};
2517 }
2518
2519 requestMeta.clear();
2520 requestMeta.append(reinterpret_cast<camera_metadata_t*>(settings.metadata.data()));
2521
2522 camera_metadata_t* metaBuffer = requestMeta.release();
2523 uint8_t* rawMetaBuffer = reinterpret_cast<uint8_t*>(metaBuffer);
2524 requestSettings[i].metadata = std::vector(
2525 rawMetaBuffer, rawMetaBuffer + get_camera_metadata_size(metaBuffer));
2526 overrideRotateAndCrop(&requestSettings[i]);
2527
2528 request.frameNumber = frameNumber + i;
2529 request.fmqSettingsSize = 0;
2530 request.settings = requestSettings[i];
2531 request.inputBuffer = {/*streamId*/ -1,
2532 /*bufferId*/ 0, NativeHandle(),
2533 BufferStatus::ERROR, NativeHandle(),
2534 NativeHandle()};
2535
2536 inflightReqs[i] = std::make_shared<InFlightRequest>(1, false, supportsPartialResults,
2537 partialResultCount, resultQueue);
2538 mInflightMap[frameNumber + i] = inflightReqs[i];
2539 }
2540
2541 int32_t numRequestProcessed = 0;
2542 std::vector<BufferCache> cachesToRemove;
2543
2544 ndk::ScopedAStatus returnStatus =
2545 mSession->processCaptureRequest(requests, cachesToRemove, &numRequestProcessed);
2546 ASSERT_TRUE(returnStatus.isOk());
2547 ASSERT_EQ(numRequestProcessed, kBurstFrameCount);
2548
2549 std::vector<int32_t> offlineStreamIds = {halStream.id};
2550 CameraOfflineSessionInfo offlineSessionInfo;
2551 std::shared_ptr<ICameraOfflineSession> offlineSession;
2552 returnStatus =
2553 mSession->switchToOffline(offlineStreamIds, &offlineSessionInfo, &offlineSession);
2554
2555 if (!halStreams[0].supportOffline) {
2556 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT),
2557 returnStatus.getServiceSpecificError());
2558 ret = mSession->close();
2559 mSession = nullptr;
2560 ASSERT_TRUE(ret.isOk());
2561 continue;
2562 }
2563
2564 ASSERT_TRUE(returnStatus.isOk());
2565 // Hal might be unable to find any requests qualified for offline mode.
2566 if (offlineSession == nullptr) {
2567 ret = mSession->close();
2568 mSession = nullptr;
2569 ASSERT_TRUE(ret.isOk());
2570 continue;
2571 }
2572
2573 ASSERT_EQ(offlineSessionInfo.offlineStreams.size(), 1u);
2574 ASSERT_EQ(offlineSessionInfo.offlineStreams[0].id, halStream.id);
2575 ASSERT_NE(offlineSessionInfo.offlineRequests.size(), 0u);
2576
2577 // close device session to make sure offline session does not rely on it
2578 ret = mSession->close();
2579 mSession = nullptr;
2580 ASSERT_TRUE(ret.isOk());
2581
2582 ::aidl::android::hardware::common::fmq::MQDescriptor<
2583 int8_t, aidl::android::hardware::common::fmq::SynchronizedReadWrite>
2584 offlineResultDescriptor;
2585
2586 auto offlineResultQueueRet =
2587 offlineSession->getCaptureResultMetadataQueue(&offlineResultDescriptor);
2588 std::shared_ptr<ResultMetadataQueue> offlineResultQueue =
2589 std::make_shared<ResultMetadataQueue>(descriptor);
2590 if (!offlineResultQueue->isValid() || offlineResultQueue->availableToWrite() <= 0) {
2591 ALOGE("%s: offline session returns empty result metadata fmq, not use it", __func__);
2592 offlineResultQueue = nullptr;
2593 // Don't use the queue onwards.
2594 }
2595 ASSERT_TRUE(offlineResultQueueRet.isOk());
2596
2597 updateInflightResultQueue(offlineResultQueue);
2598
2599 ret = offlineSession->setCallback(cb);
2600 ASSERT_TRUE(ret.isOk());
2601
2602 for (size_t i = 0; i < kBurstFrameCount; i++) {
2603 std::unique_lock<std::mutex> l(mLock);
2604 while (!inflightReqs[i]->errorCodeValid && ((0 < inflightReqs[i]->numBuffersLeft) ||
2605 (!inflightReqs[i]->haveResultMetadata))) {
2606 auto timeout = std::chrono::system_clock::now() +
2607 std::chrono::seconds(kStreamBufferTimeoutSec);
2608 ASSERT_NE(std::cv_status::timeout, mResultCondition.wait_until(l, timeout));
2609 }
2610
2611 ASSERT_FALSE(inflightReqs[i]->errorCodeValid);
2612 ASSERT_NE(inflightReqs[i]->resultOutputBuffers.size(), 0u);
2613 ASSERT_EQ(stream.id, inflightReqs[i]->resultOutputBuffers[0].buffer.streamId);
2614 ASSERT_FALSE(inflightReqs[i]->collectedResult.isEmpty());
2615 }
2616
2617 ret = offlineSession->close();
2618 ASSERT_TRUE(ret.isOk());
2619 }
2620}
2621
2622// Check whether an invalid capture request with missing output buffers
2623// will be reported correctly.
2624TEST_P(CameraAidlTest, processCaptureRequestInvalidBuffer) {
2625 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
2626 std::vector<AvailableStream> outputBlobStreams;
2627 AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
2628 static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
2629 int32_t frameNumber = 1;
2630 CameraMetadata settings;
2631
2632 for (const auto& name : cameraDeviceNames) {
2633 Stream previewStream;
2634 std::vector<HalStream> halStreams;
2635 std::shared_ptr<DeviceCb> cb;
2636 bool supportsPartialResults = false;
2637 bool useHalBufManager = false;
2638 int32_t partialResultCount = 0;
2639 configurePreviewStream(name, mProvider, &previewThreshold, &mSession /*out*/,
2640 &previewStream /*out*/, &halStreams /*out*/,
2641 &supportsPartialResults /*out*/, &partialResultCount /*out*/,
2642 &useHalBufManager /*out*/, &cb /*out*/);
2643
2644 RequestTemplate reqTemplate = RequestTemplate::PREVIEW;
2645 ndk::ScopedAStatus ret = mSession->constructDefaultRequestSettings(reqTemplate, &settings);
2646 ASSERT_TRUE(ret.isOk());
2647 overrideRotateAndCrop(&settings);
2648
2649 std::vector<CaptureRequest> requests(1);
2650 CaptureRequest& request = requests[0];
2651 std::vector<StreamBuffer>& outputBuffers = request.outputBuffers;
2652 outputBuffers.resize(1);
2653 // Empty output buffer
2654 outputBuffers[0] = {
2655 -1, 0, NativeHandle(), BufferStatus::ERROR, NativeHandle(), NativeHandle()};
2656
2657 request.inputBuffer = {
2658 -1, 0, NativeHandle(), BufferStatus::ERROR, NativeHandle(), NativeHandle()};
2659 request.frameNumber = frameNumber;
2660 request.fmqSettingsSize = 0;
2661 request.settings = settings;
2662
2663 // Output buffers are missing, we should fail here
2664 int32_t numRequestProcessed = 0;
2665 std::vector<BufferCache> cachesToRemove;
2666 ret = mSession->processCaptureRequest(requests, cachesToRemove, &numRequestProcessed);
2667 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT), ret.getServiceSpecificError());
2668 ASSERT_EQ(numRequestProcessed, 0u);
2669
2670 ret = mSession->close();
2671 mSession = nullptr;
2672 ASSERT_TRUE(ret.isOk());
2673 }
2674}
2675
2676// Generate, trigger and flush a preview request
2677TEST_P(CameraAidlTest, flushPreviewRequest) {
2678 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
2679 std::vector<AvailableStream> outputPreviewStreams;
2680 AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
2681 static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
2682 int64_t bufferId = 1;
2683 int32_t frameNumber = 1;
2684 CameraMetadata settings;
2685
2686 for (const auto& name : cameraDeviceNames) {
2687 Stream previewStream;
2688 std::vector<HalStream> halStreams;
2689 std::shared_ptr<DeviceCb> cb;
2690 bool supportsPartialResults = false;
2691 bool useHalBufManager = false;
2692 int32_t partialResultCount = 0;
2693
2694 configurePreviewStream(name, mProvider, &previewThreshold, &mSession /*out*/,
2695 &previewStream /*out*/, &halStreams /*out*/,
2696 &supportsPartialResults /*out*/, &partialResultCount /*out*/,
2697 &useHalBufManager /*out*/, &cb /*out*/);
2698
2699 ASSERT_NE(mSession, nullptr);
2700 ASSERT_NE(cb, nullptr);
2701 ASSERT_FALSE(halStreams.empty());
2702
2703 ::aidl::android::hardware::common::fmq::MQDescriptor<
2704 int8_t, aidl::android::hardware::common::fmq::SynchronizedReadWrite>
2705 descriptor;
2706
2707 auto resultQueueRet = mSession->getCaptureResultMetadataQueue(&descriptor);
2708 std::shared_ptr<ResultMetadataQueue> resultQueue =
2709 std::make_shared<ResultMetadataQueue>(descriptor);
2710 ASSERT_TRUE(resultQueueRet.isOk());
2711 if (!resultQueue->isValid() || resultQueue->availableToWrite() <= 0) {
2712 ALOGE("%s: HAL returns empty result metadata fmq, not use it", __func__);
2713 resultQueue = nullptr;
2714 // Don't use the queue onwards.
2715 }
2716
2717 std::shared_ptr<InFlightRequest> inflightReq = std::make_shared<InFlightRequest>(
2718 1, false, supportsPartialResults, partialResultCount, resultQueue);
2719 RequestTemplate reqTemplate = RequestTemplate::PREVIEW;
2720
2721 ndk::ScopedAStatus ret = mSession->constructDefaultRequestSettings(reqTemplate, &settings);
2722 ASSERT_TRUE(ret.isOk());
2723 overrideRotateAndCrop(&settings);
2724
2725 buffer_handle_t buffer_handle;
2726 std::vector<CaptureRequest> requests(1);
2727 CaptureRequest& request = requests[0];
2728 std::vector<StreamBuffer>& outputBuffers = request.outputBuffers;
2729 outputBuffers.resize(1);
2730 StreamBuffer& outputBuffer = outputBuffers[0];
2731 if (useHalBufManager) {
2732 bufferId = 0;
2733 outputBuffer = {halStreams[0].id, bufferId, NativeHandle(),
2734 BufferStatus::OK, NativeHandle(), NativeHandle()};
2735 } else {
2736 allocateGraphicBuffer(previewStream.width, previewStream.height,
2737 android_convertGralloc1To0Usage(
2738 static_cast<uint64_t>(halStreams[0].producerUsage),
2739 static_cast<uint64_t>(halStreams[0].consumerUsage)),
2740 halStreams[0].overrideFormat, &buffer_handle);
2741 outputBuffer = {halStreams[0].id, bufferId, ::android::makeToAidl(buffer_handle),
2742 BufferStatus::OK, NativeHandle(), NativeHandle()};
2743 }
2744
2745 request.frameNumber = frameNumber;
2746 request.fmqSettingsSize = 0;
2747 request.settings = settings;
2748 request.inputBuffer = {
2749 -1, 0, NativeHandle(), BufferStatus::ERROR, NativeHandle(), NativeHandle()};
2750
2751 {
2752 std::unique_lock<std::mutex> l(mLock);
2753 mInflightMap.clear();
2754 mInflightMap[frameNumber] = inflightReq;
2755 }
2756
2757 int32_t numRequestProcessed = 0;
2758 std::vector<BufferCache> cachesToRemove;
2759 ret = mSession->processCaptureRequest(requests, cachesToRemove, &numRequestProcessed);
2760 ASSERT_TRUE(ret.isOk());
2761 ASSERT_EQ(numRequestProcessed, 1u);
2762
2763 // Flush before waiting for request to complete.
2764 ndk::ScopedAStatus returnStatus = mSession->flush();
2765 ASSERT_TRUE(returnStatus.isOk());
2766
2767 {
2768 std::unique_lock<std::mutex> l(mLock);
2769 while (!inflightReq->errorCodeValid &&
2770 ((0 < inflightReq->numBuffersLeft) || (!inflightReq->haveResultMetadata))) {
2771 auto timeout = std::chrono::system_clock::now() +
2772 std::chrono::seconds(kStreamBufferTimeoutSec);
2773 ASSERT_NE(std::cv_status::timeout, mResultCondition.wait_until(l, timeout));
2774 }
2775
2776 if (!inflightReq->errorCodeValid) {
2777 ASSERT_NE(inflightReq->resultOutputBuffers.size(), 0u);
2778 ASSERT_EQ(previewStream.id, inflightReq->resultOutputBuffers[0].buffer.streamId);
2779 } else {
2780 switch (inflightReq->errorCode) {
2781 case ErrorCode::ERROR_REQUEST:
2782 case ErrorCode::ERROR_RESULT:
2783 case ErrorCode::ERROR_BUFFER:
2784 // Expected
2785 break;
2786 case ErrorCode::ERROR_DEVICE:
2787 default:
2788 FAIL() << "Unexpected error:"
2789 << static_cast<uint32_t>(inflightReq->errorCode);
2790 }
2791 }
2792 }
2793
2794 if (useHalBufManager) {
2795 verifyBuffersReturned(mSession, previewStream.id, cb);
2796 }
2797
2798 ret = mSession->close();
2799 mSession = nullptr;
2800 ASSERT_TRUE(ret.isOk());
2801 }
2802}
2803
2804// Verify that camera flushes correctly without any pending requests.
2805TEST_P(CameraAidlTest, flushEmpty) {
2806 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
2807 std::vector<AvailableStream> outputPreviewStreams;
2808 AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
2809 static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
2810
2811 for (const auto& name : cameraDeviceNames) {
2812 Stream previewStream;
2813 std::vector<HalStream> halStreams;
2814 std::shared_ptr<DeviceCb> cb;
2815 bool supportsPartialResults = false;
2816 bool useHalBufManager = false;
2817
2818 int32_t partialResultCount = 0;
2819 configurePreviewStream(name, mProvider, &previewThreshold, &mSession /*out*/,
2820 &previewStream /*out*/, &halStreams /*out*/,
2821 &supportsPartialResults /*out*/, &partialResultCount /*out*/,
2822 &useHalBufManager /*out*/, &cb /*out*/);
2823
2824 ndk::ScopedAStatus returnStatus = mSession->flush();
2825 ASSERT_TRUE(returnStatus.isOk());
2826
2827 {
2828 std::unique_lock<std::mutex> l(mLock);
2829 auto timeout = std::chrono::system_clock::now() +
2830 std::chrono::milliseconds(kEmptyFlushTimeoutMSec);
2831 ASSERT_EQ(std::cv_status::timeout, mResultCondition.wait_until(l, timeout));
2832 }
2833
2834 ndk::ScopedAStatus ret = mSession->close();
2835 mSession = nullptr;
2836 ASSERT_TRUE(ret.isOk());
2837 }
2838}
2839
2840// Test camera provider notify method
2841TEST_P(CameraAidlTest, providerDeviceStateNotification) {
2842 notifyDeviceState(ICameraProvider::DEVICE_STATE_BACK_COVERED);
2843 notifyDeviceState(ICameraProvider::DEVICE_STATE_NORMAL);
2844}
2845
2846// Verify that all supported stream formats and sizes can be configured
2847// successfully for injection camera.
2848TEST_P(CameraAidlTest, configureInjectionStreamsAvailableOutputs) {
2849 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
2850 std::vector<AvailableStream> outputStreams;
2851
2852 for (const auto& name : cameraDeviceNames) {
2853 CameraMetadata metadata;
2854
2855 std::shared_ptr<ICameraInjectionSession> injectionSession;
2856 std::shared_ptr<ICameraDevice> unusedDevice;
2857 openEmptyInjectionSession(name, mProvider, &injectionSession /*out*/, &metadata /*out*/,
2858 &unusedDevice /*out*/);
2859 if (injectionSession == nullptr) {
2860 continue;
2861 }
2862
2863 camera_metadata_t* staticMetaBuffer =
2864 reinterpret_cast<camera_metadata_t*>(metadata.metadata.data());
2865 CameraMetadata chars;
2866 chars.metadata = metadata.metadata;
2867
2868 outputStreams.clear();
2869 ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMetaBuffer, outputStreams));
2870 ASSERT_NE(0u, outputStreams.size());
2871
2872 int32_t jpegBufferSize = 0;
2873 ASSERT_EQ(Status::OK, getJpegBufferSize(staticMetaBuffer, &jpegBufferSize));
2874 ASSERT_NE(0u, jpegBufferSize);
2875
2876 int32_t streamId = 0;
2877 int32_t streamConfigCounter = 0;
2878 for (auto& it : outputStreams) {
2879 Dataspace dataspace = getDataspace(static_cast<PixelFormat>(it.format));
2880 Stream stream = {streamId,
2881 StreamType::OUTPUT,
2882 it.width,
2883 it.height,
2884 static_cast<PixelFormat>(it.format),
2885 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
2886 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
2887 dataspace,
2888 StreamRotation::ROTATION_0,
2889 std::string(),
2890 jpegBufferSize,
2891 0,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00002892 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
2893 RequestAvailableDynamicRangeProfilesMap::
2894 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08002895
2896 std::vector<Stream> streams = {stream};
2897 StreamConfiguration config;
2898 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
2899 jpegBufferSize);
2900
2901 config.streamConfigCounter = streamConfigCounter++;
2902 ndk::ScopedAStatus s = injectionSession->configureInjectionStreams(config, chars);
2903 ASSERT_TRUE(s.isOk());
2904 streamId++;
2905 }
2906
2907 std::shared_ptr<ICameraDeviceSession> session;
2908 ndk::ScopedAStatus ret = injectionSession->getCameraDeviceSession(&session);
2909 ASSERT_TRUE(ret.isOk());
2910 ASSERT_NE(session, nullptr);
2911 ret = session->close();
2912 ASSERT_TRUE(ret.isOk());
2913 }
2914}
2915
2916// Check for correct handling of invalid/incorrect configuration parameters for injection camera.
2917TEST_P(CameraAidlTest, configureInjectionStreamsInvalidOutputs) {
2918 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
2919 std::vector<AvailableStream> outputStreams;
2920
2921 for (const auto& name : cameraDeviceNames) {
2922 CameraMetadata metadata;
2923 std::shared_ptr<ICameraInjectionSession> injectionSession;
2924 std::shared_ptr<ICameraDevice> unusedDevice;
2925 openEmptyInjectionSession(name, mProvider, &injectionSession /*out*/, &metadata /*out*/,
2926 &unusedDevice);
2927 if (injectionSession == nullptr) {
2928 continue;
2929 }
2930
2931 camera_metadata_t* staticMetaBuffer =
2932 reinterpret_cast<camera_metadata_t*>(metadata.metadata.data());
2933 std::shared_ptr<ICameraDeviceSession> session;
2934 ndk::ScopedAStatus ret = injectionSession->getCameraDeviceSession(&session);
2935 ASSERT_TRUE(ret.isOk());
2936 ASSERT_NE(session, nullptr);
2937
2938 CameraMetadata chars;
2939 chars.metadata = metadata.metadata;
2940
2941 outputStreams.clear();
2942 ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMetaBuffer, outputStreams));
2943 ASSERT_NE(0u, outputStreams.size());
2944
2945 int32_t jpegBufferSize = 0;
2946 ASSERT_EQ(Status::OK, getJpegBufferSize(staticMetaBuffer, &jpegBufferSize));
2947 ASSERT_NE(0u, jpegBufferSize);
2948
2949 int32_t streamId = 0;
2950 Stream stream = {streamId++,
2951 StreamType::OUTPUT,
2952 0,
2953 0,
2954 static_cast<PixelFormat>(outputStreams[0].format),
2955 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
2956 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
2957 Dataspace::UNKNOWN,
2958 StreamRotation::ROTATION_0,
2959 std::string(),
2960 jpegBufferSize,
2961 0,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00002962 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
2963 RequestAvailableDynamicRangeProfilesMap::
2964 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08002965
2966 int32_t streamConfigCounter = 0;
2967 std::vector<Stream> streams = {stream};
2968 StreamConfiguration config;
2969 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
2970 jpegBufferSize);
2971
2972 config.streamConfigCounter = streamConfigCounter++;
2973 ndk::ScopedAStatus s = injectionSession->configureInjectionStreams(config, chars);
2974 ASSERT_TRUE(
2975 (static_cast<int32_t>(Status::ILLEGAL_ARGUMENT) == s.getServiceSpecificError()) ||
2976 (static_cast<int32_t>(Status::INTERNAL_ERROR) == s.getServiceSpecificError()));
2977
2978 stream = {streamId++,
2979 StreamType::OUTPUT,
2980 INT32_MAX,
2981 INT32_MAX,
2982 static_cast<PixelFormat>(outputStreams[0].format),
2983 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
2984 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
2985 Dataspace::UNKNOWN,
2986 StreamRotation::ROTATION_0,
2987 std::string(),
2988 jpegBufferSize,
2989 0,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00002990 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
2991 RequestAvailableDynamicRangeProfilesMap::
2992 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
2993
Avichal Rakesh362242f2022-02-08 12:40:53 -08002994 streams[0] = stream;
2995 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
2996 jpegBufferSize);
2997 config.streamConfigCounter = streamConfigCounter++;
2998 s = injectionSession->configureInjectionStreams(config, chars);
2999 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT), s.getServiceSpecificError());
3000
3001 for (auto& it : outputStreams) {
3002 stream = {streamId++,
3003 StreamType::OUTPUT,
3004 it.width,
3005 it.height,
3006 static_cast<PixelFormat>(INT32_MAX),
3007 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
3008 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
3009 Dataspace::UNKNOWN,
3010 StreamRotation::ROTATION_0,
3011 std::string(),
3012 jpegBufferSize,
3013 0,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00003014 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
3015 RequestAvailableDynamicRangeProfilesMap::
3016 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08003017 streams[0] = stream;
3018 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
3019 jpegBufferSize);
3020 config.streamConfigCounter = streamConfigCounter++;
3021 s = injectionSession->configureInjectionStreams(config, chars);
3022 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT), s.getServiceSpecificError());
3023
3024 stream = {streamId++,
3025 StreamType::OUTPUT,
3026 it.width,
3027 it.height,
3028 static_cast<PixelFormat>(it.format),
3029 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
3030 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
3031 Dataspace::UNKNOWN,
3032 static_cast<StreamRotation>(INT32_MAX),
3033 std::string(),
3034 jpegBufferSize,
3035 0,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00003036 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
3037 RequestAvailableDynamicRangeProfilesMap::
3038 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08003039 streams[0] = stream;
3040 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
3041 jpegBufferSize);
3042 config.streamConfigCounter = streamConfigCounter++;
3043 s = injectionSession->configureInjectionStreams(config, chars);
3044 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT), s.getServiceSpecificError());
3045 }
3046
3047 ret = session->close();
3048 ASSERT_TRUE(ret.isOk());
3049 }
3050}
3051
3052// Check whether session parameters are supported for injection camera. If Hal support for them
3053// exist, then try to configure a preview stream using them.
3054TEST_P(CameraAidlTest, configureInjectionStreamsWithSessionParameters) {
3055 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
3056 std::vector<AvailableStream> outputPreviewStreams;
3057 AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
3058 static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
3059
3060 for (const auto& name : cameraDeviceNames) {
3061 CameraMetadata metadata;
3062 std::shared_ptr<ICameraInjectionSession> injectionSession;
3063 std::shared_ptr<ICameraDevice> unusedDevice;
3064 openEmptyInjectionSession(name, mProvider, &injectionSession /*out*/, &metadata /*out*/,
3065 &unusedDevice /*out*/);
3066 if (injectionSession == nullptr) {
3067 continue;
3068 }
3069
3070 std::shared_ptr<ICameraDeviceSession> session;
3071 ndk::ScopedAStatus ret = injectionSession->getCameraDeviceSession(&session);
3072 ASSERT_TRUE(ret.isOk());
3073 ASSERT_NE(session, nullptr);
3074
3075 camera_metadata_t* staticMetaBuffer =
3076 reinterpret_cast<camera_metadata_t*>(metadata.metadata.data());
3077 CameraMetadata chars;
3078 chars.metadata = metadata.metadata;
3079
3080 std::unordered_set<int32_t> availableSessionKeys;
3081 Status rc = getSupportedKeys(staticMetaBuffer, ANDROID_REQUEST_AVAILABLE_SESSION_KEYS,
3082 &availableSessionKeys);
3083 ASSERT_EQ(Status::OK, rc);
3084 if (availableSessionKeys.empty()) {
3085 ret = session->close();
3086 ASSERT_TRUE(ret.isOk());
3087 continue;
3088 }
3089
3090 android::hardware::camera::common::V1_0::helper::CameraMetadata previewRequestSettings;
3091 android::hardware::camera::common::V1_0::helper::CameraMetadata sessionParams,
3092 modifiedSessionParams;
3093 constructFilteredSettings(session, availableSessionKeys, RequestTemplate::PREVIEW,
3094 &previewRequestSettings, &sessionParams);
3095 if (sessionParams.isEmpty()) {
3096 ret = session->close();
3097 ASSERT_TRUE(ret.isOk());
3098 continue;
3099 }
3100
3101 outputPreviewStreams.clear();
3102
3103 ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMetaBuffer, outputPreviewStreams,
3104 &previewThreshold));
3105 ASSERT_NE(0u, outputPreviewStreams.size());
3106
3107 Stream previewStream = {
3108 0,
3109 StreamType::OUTPUT,
3110 outputPreviewStreams[0].width,
3111 outputPreviewStreams[0].height,
3112 static_cast<PixelFormat>(outputPreviewStreams[0].format),
3113 static_cast<::aidl::android::hardware::graphics::common::BufferUsage>(
3114 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
3115 Dataspace::UNKNOWN,
3116 StreamRotation::ROTATION_0,
3117 std::string(),
3118 0,
3119 -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00003120 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
3121 RequestAvailableDynamicRangeProfilesMap::
3122 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08003123 std::vector<Stream> streams = {previewStream};
3124 StreamConfiguration config;
3125 config.streams = streams;
3126 config.operationMode = StreamConfigurationMode::NORMAL_MODE;
3127
3128 modifiedSessionParams = sessionParams;
3129 camera_metadata_t* sessionParamsBuffer = sessionParams.release();
3130 uint8_t* rawSessionParamsBuffer = reinterpret_cast<uint8_t*>(sessionParamsBuffer);
3131 config.sessionParams.metadata =
3132 std::vector(rawSessionParamsBuffer,
3133 rawSessionParamsBuffer + get_camera_metadata_size(sessionParamsBuffer));
3134
3135 config.streamConfigCounter = 0;
3136 config.streamConfigCounter = 0;
3137 config.multiResolutionInputImage = false;
3138
3139 ndk::ScopedAStatus s = injectionSession->configureInjectionStreams(config, chars);
3140 ASSERT_TRUE(s.isOk());
3141
3142 sessionParams.acquire(sessionParamsBuffer);
3143 free_camera_metadata(staticMetaBuffer);
3144 ret = session->close();
3145 ASSERT_TRUE(ret.isOk());
3146 }
3147}
3148
Jayant Chowdharyde1909e2022-11-23 17:18:38 +00003149TEST_P(CameraAidlTest, configureStreamsUseCasesCroppedRaw) {
3150 AvailableStream rawStreamThreshold =
3151 {INT_MAX, INT_MAX, static_cast<int32_t>(PixelFormat::RAW16)};
3152 configureStreamUseCaseInternal(rawStreamThreshold);
3153}
3154
Avichal Rakesh362242f2022-02-08 12:40:53 -08003155// Verify that valid stream use cases can be configured successfully, and invalid use cases
3156// fail stream configuration.
3157TEST_P(CameraAidlTest, configureStreamsUseCases) {
Jayant Chowdharyde1909e2022-11-23 17:18:38 +00003158 AvailableStream previewStreamThreshold =
3159 {kMaxPreviewWidth, kMaxPreviewHeight, static_cast<int32_t>(PixelFormat::YCBCR_420_888)};
3160 configureStreamUseCaseInternal(previewStreamThreshold);
Avichal Rakesh362242f2022-02-08 12:40:53 -08003161}
3162
Austin Borger0918fc82023-03-21 18:48:18 -07003163// Validate the integrity of stream configuration metadata
3164TEST_P(CameraAidlTest, validateStreamConfigurations) {
3165 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
3166 std::vector<AvailableStream> outputStreams;
3167
3168 const int32_t scalerSizesTag = ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS;
3169 const int32_t scalerMinFrameDurationsTag = ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS;
3170 const int32_t scalerStallDurationsTag = ANDROID_SCALER_AVAILABLE_STALL_DURATIONS;
3171
3172 for (const auto& name : cameraDeviceNames) {
3173 CameraMetadata meta;
3174 std::shared_ptr<ICameraDevice> cameraDevice;
3175
3176 openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/,
3177 &cameraDevice /*out*/);
3178 camera_metadata_t* staticMeta = reinterpret_cast<camera_metadata_t*>(meta.metadata.data());
3179
3180 if (is10BitDynamicRangeCapable(staticMeta)) {
3181 std::vector<std::tuple<size_t, size_t>> supportedP010Sizes, supportedBlobSizes;
3182
3183 getSupportedSizes(staticMeta, scalerSizesTag, HAL_PIXEL_FORMAT_BLOB,
3184 &supportedBlobSizes);
3185 getSupportedSizes(staticMeta, scalerSizesTag, HAL_PIXEL_FORMAT_YCBCR_P010,
3186 &supportedP010Sizes);
3187 ASSERT_FALSE(supportedP010Sizes.empty());
3188
3189 std::vector<int64_t> blobMinDurations, blobStallDurations;
3190 getSupportedDurations(staticMeta, scalerMinFrameDurationsTag, HAL_PIXEL_FORMAT_BLOB,
3191 supportedP010Sizes, &blobMinDurations);
3192 getSupportedDurations(staticMeta, scalerStallDurationsTag, HAL_PIXEL_FORMAT_BLOB,
3193 supportedP010Sizes, &blobStallDurations);
3194 ASSERT_FALSE(blobStallDurations.empty());
3195 ASSERT_FALSE(blobMinDurations.empty());
3196 ASSERT_EQ(supportedP010Sizes.size(), blobMinDurations.size());
3197 ASSERT_EQ(blobMinDurations.size(), blobStallDurations.size());
3198 }
3199
Austin Borger8e9ac022023-05-04 11:17:26 -07003200 // TODO (b/280887191): Validate other aspects of stream configuration metadata...
3201
3202 ndk::ScopedAStatus ret = mSession->close();
3203 mSession = nullptr;
3204 ASSERT_TRUE(ret.isOk());
Austin Borger0918fc82023-03-21 18:48:18 -07003205 }
3206}
3207
Avichal Rakesh362242f2022-02-08 12:40:53 -08003208GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(CameraAidlTest);
3209INSTANTIATE_TEST_SUITE_P(
3210 PerInstance, CameraAidlTest,
3211 testing::ValuesIn(android::getAidlHalInstanceNames(ICameraProvider::descriptor)),
Jayant Chowdharyde1909e2022-11-23 17:18:38 +00003212 android::hardware::PrintInstanceNameToString);