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