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