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