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