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