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