blob: e335853c2883740167de5415910e2d5a37ba30d9 [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()) {
534 const camera_metadata_t* metadata = (camera_metadata_t*)rawMetadata.metadata.data();
535 size_t expectedSize = rawMetadata.metadata.size();
536 int result = validate_camera_metadata_structure(metadata, &expectedSize);
537 ASSERT_TRUE((result == 0) || (result == CAMERA_METADATA_VALIDATION_SHIFTED));
538 verifyRequestTemplate(metadata, reqTemplate);
539 } else {
540 ASSERT_EQ(0u, rawMetadata.metadata.size());
541 }
Shuzhen Wangdf89cb92023-11-09 18:24:42 -0800542
543 if (flags::feature_combination_query()) {
544 if (supportFeatureCombinationQuery) {
545 CameraMetadata rawMetadata2;
546 ndk::ScopedAStatus ret2 =
547 device->constructDefaultRequestSettings(reqTemplate, &rawMetadata2);
548
549 // TODO: Do not allow OPERATION_NOT_SUPPORTED once HAL
550 // implementation is in place.
551 if (static_cast<Status>(ret2.getServiceSpecificError()) !=
552 Status::OPERATION_NOT_SUPPORTED) {
553 ASSERT_EQ(ret.isOk(), ret2.isOk());
554 ASSERT_EQ(ret.getStatus(), ret2.getStatus());
555
556 ASSERT_EQ(rawMetadata.metadata.size(), rawMetadata2.metadata.size());
557 if (ret2.isOk()) {
558 const camera_metadata_t* metadata =
559 (camera_metadata_t*)rawMetadata2.metadata.data();
560 size_t expectedSize = rawMetadata2.metadata.size();
561 int result =
562 validate_camera_metadata_structure(metadata, &expectedSize);
563 ASSERT_TRUE((result == 0) ||
564 (result == CAMERA_METADATA_VALIDATION_SHIFTED));
565 verifyRequestTemplate(metadata, reqTemplate);
566 }
567 }
568 }
569 }
Avichal Rakesh362242f2022-02-08 12:40:53 -0800570 }
571 ret = mSession->close();
572 mSession = nullptr;
573 ASSERT_TRUE(ret.isOk());
574 }
575}
576
577// Verify that all supported stream formats and sizes can be configured
578// successfully.
579TEST_P(CameraAidlTest, configureStreamsAvailableOutputs) {
580 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
581 std::vector<AvailableStream> outputStreams;
582
583 for (const auto& name : cameraDeviceNames) {
584 CameraMetadata meta;
585 std::shared_ptr<ICameraDevice> device;
586
587 openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/, &device /*out*/);
588
589 camera_metadata_t* staticMeta = reinterpret_cast<camera_metadata_t*>(meta.metadata.data());
590 outputStreams.clear();
591 ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta, outputStreams));
592 ASSERT_NE(0u, outputStreams.size());
593
594 int32_t jpegBufferSize = 0;
595 ASSERT_EQ(Status::OK, getJpegBufferSize(staticMeta, &jpegBufferSize));
596 ASSERT_NE(0u, jpegBufferSize);
597
598 int32_t streamId = 0;
599 int32_t streamConfigCounter = 0;
600 for (auto& it : outputStreams) {
601 Stream stream;
602 Dataspace dataspace = getDataspace(static_cast<PixelFormat>(it.format));
603 stream.id = streamId;
604 stream.streamType = StreamType::OUTPUT;
605 stream.width = it.width;
606 stream.height = it.height;
607 stream.format = static_cast<PixelFormat>(it.format);
608 stream.dataSpace = dataspace;
609 stream.usage = static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
610 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER);
611 stream.rotation = StreamRotation::ROTATION_0;
Avichal Rakeshd3503a32022-02-25 06:23:14 +0000612 stream.dynamicRangeProfile = RequestAvailableDynamicRangeProfilesMap::
613 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD;
Austin Borger263e3622023-06-15 11:32:04 -0700614 stream.useCase = ScalerAvailableStreamUseCases::
615 ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT;
616 stream.colorSpace = static_cast<int>(
617 RequestAvailableColorSpaceProfilesMap::
618 ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED);
Avichal Rakesh362242f2022-02-08 12:40:53 -0800619
620 std::vector<Stream> streams = {stream};
621 StreamConfiguration config;
622 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
623 jpegBufferSize);
624
Shuzhen Wangdf89cb92023-11-09 18:24:42 -0800625 verifyStreamCombination(device, config, /*expectedStatus*/ true);
Avichal Rakesh362242f2022-02-08 12:40:53 -0800626
627 config.streamConfigCounter = streamConfigCounter++;
628 std::vector<HalStream> halConfigs;
629 ndk::ScopedAStatus ret = mSession->configureStreams(config, &halConfigs);
630 ASSERT_TRUE(ret.isOk());
631 ASSERT_EQ(halConfigs.size(), 1);
632 ASSERT_EQ(halConfigs[0].id, streamId);
633
634 streamId++;
635 }
636
637 ndk::ScopedAStatus ret = mSession->close();
638 mSession = nullptr;
639 ASSERT_TRUE(ret.isOk());
640 }
641}
642
643// Verify that mandatory concurrent streams and outputs are supported.
644TEST_P(CameraAidlTest, configureConcurrentStreamsAvailableOutputs) {
645 struct CameraTestInfo {
646 CameraMetadata staticMeta;
647 std::shared_ptr<ICameraDeviceSession> session;
648 std::shared_ptr<ICameraDevice> cameraDevice;
649 StreamConfiguration config;
650 };
651
652 std::map<std::string, std::string> idToNameMap = getCameraDeviceIdToNameMap(mProvider);
653 std::vector<ConcurrentCameraIdCombination> concurrentDeviceCombinations =
654 getConcurrentDeviceCombinations(mProvider);
655 std::vector<AvailableStream> outputStreams;
656 for (const auto& cameraDeviceIds : concurrentDeviceCombinations) {
657 std::vector<CameraIdAndStreamCombination> cameraIdsAndStreamCombinations;
658 std::vector<CameraTestInfo> cameraTestInfos;
659 size_t i = 0;
660 for (const auto& id : cameraDeviceIds.combination) {
661 CameraTestInfo cti;
662 auto it = idToNameMap.find(id);
663 ASSERT_TRUE(idToNameMap.end() != it);
664 std::string name = it->second;
665
666 openEmptyDeviceSession(name, mProvider, &cti.session /*out*/, &cti.staticMeta /*out*/,
667 &cti.cameraDevice /*out*/);
668
669 outputStreams.clear();
670 camera_metadata_t* staticMeta =
671 reinterpret_cast<camera_metadata_t*>(cti.staticMeta.metadata.data());
672 ASSERT_EQ(Status::OK, getMandatoryConcurrentStreams(staticMeta, &outputStreams));
673 ASSERT_NE(0u, outputStreams.size());
674
675 int32_t jpegBufferSize = 0;
676 ASSERT_EQ(Status::OK, getJpegBufferSize(staticMeta, &jpegBufferSize));
677 ASSERT_NE(0u, jpegBufferSize);
678
679 int32_t streamId = 0;
680 std::vector<Stream> streams(outputStreams.size());
681 size_t j = 0;
682 for (const auto& s : outputStreams) {
683 Stream stream;
684 Dataspace dataspace = getDataspace(static_cast<PixelFormat>(s.format));
685 stream.id = streamId++;
686 stream.streamType = StreamType::OUTPUT;
687 stream.width = s.width;
688 stream.height = s.height;
689 stream.format = static_cast<PixelFormat>(s.format);
690 stream.usage = static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
691 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER);
692 stream.dataSpace = dataspace;
693 stream.rotation = StreamRotation::ROTATION_0;
694 stream.sensorPixelModesUsed = {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT};
Avichal Rakeshd3503a32022-02-25 06:23:14 +0000695 stream.dynamicRangeProfile = RequestAvailableDynamicRangeProfilesMap::
696 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD;
Avichal Rakesh362242f2022-02-08 12:40:53 -0800697 streams[j] = stream;
698 j++;
699 }
700
701 // Add the created stream configs to cameraIdsAndStreamCombinations
702 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &cti.config,
703 jpegBufferSize);
704
705 cti.config.streamConfigCounter = outputStreams.size();
706 CameraIdAndStreamCombination cameraIdAndStreamCombination;
707 cameraIdAndStreamCombination.cameraId = id;
708 cameraIdAndStreamCombination.streamConfiguration = cti.config;
709 cameraIdsAndStreamCombinations.push_back(cameraIdAndStreamCombination);
710 i++;
711 cameraTestInfos.push_back(cti);
712 }
713 // Now verify that concurrent streams are supported
714 bool combinationSupported;
715 ndk::ScopedAStatus ret = mProvider->isConcurrentStreamCombinationSupported(
716 cameraIdsAndStreamCombinations, &combinationSupported);
717 ASSERT_TRUE(ret.isOk());
718 ASSERT_EQ(combinationSupported, true);
719
720 // Test the stream can actually be configured
721 for (auto& cti : cameraTestInfos) {
722 if (cti.session != nullptr) {
Shuzhen Wangdf89cb92023-11-09 18:24:42 -0800723 verifyStreamCombination(cti.cameraDevice, cti.config, /*expectedStatus*/ true);
Avichal Rakesh362242f2022-02-08 12:40:53 -0800724 }
725
726 if (cti.session != nullptr) {
727 std::vector<HalStream> streamConfigs;
728 ret = cti.session->configureStreams(cti.config, &streamConfigs);
729 ASSERT_TRUE(ret.isOk());
730 ASSERT_EQ(cti.config.streams.size(), streamConfigs.size());
731 }
732 }
733
734 for (auto& cti : cameraTestInfos) {
735 ret = cti.session->close();
736 ASSERT_TRUE(ret.isOk());
737 }
738 }
739}
740
741// Check for correct handling of invalid/incorrect configuration parameters.
742TEST_P(CameraAidlTest, configureStreamsInvalidOutputs) {
743 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
744 std::vector<AvailableStream> outputStreams;
745
746 for (const auto& name : cameraDeviceNames) {
747 CameraMetadata meta;
748 std::shared_ptr<ICameraDevice> cameraDevice;
749
750 openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/,
751 &cameraDevice /*out*/);
752 camera_metadata_t* staticMeta = reinterpret_cast<camera_metadata_t*>(meta.metadata.data());
753 outputStreams.clear();
754
755 ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta, outputStreams));
756 ASSERT_NE(0u, outputStreams.size());
757
758 int32_t jpegBufferSize = 0;
759 ASSERT_EQ(Status::OK, getJpegBufferSize(staticMeta, &jpegBufferSize));
760 ASSERT_NE(0u, jpegBufferSize);
761
762 int32_t streamId = 0;
763 Stream stream = {streamId++,
764 StreamType::OUTPUT,
765 static_cast<uint32_t>(0),
766 static_cast<uint32_t>(0),
767 static_cast<PixelFormat>(outputStreams[0].format),
768 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
769 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
770 Dataspace::UNKNOWN,
771 StreamRotation::ROTATION_0,
772 std::string(),
773 jpegBufferSize,
774 -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +0000775 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
776 RequestAvailableDynamicRangeProfilesMap::
777 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -0800778 int32_t streamConfigCounter = 0;
779 std::vector<Stream> streams = {stream};
780 StreamConfiguration config;
781 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
782 jpegBufferSize);
783
Shuzhen Wangdf89cb92023-11-09 18:24:42 -0800784 verifyStreamCombination(cameraDevice, config, /*expectedStatus*/ false);
Avichal Rakesh362242f2022-02-08 12:40:53 -0800785
786 config.streamConfigCounter = streamConfigCounter++;
787 std::vector<HalStream> halConfigs;
788 ndk::ScopedAStatus ret = mSession->configureStreams(config, &halConfigs);
789 ASSERT_TRUE(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT) ==
790 ret.getServiceSpecificError() ||
791 static_cast<int32_t>(Status::INTERNAL_ERROR) == ret.getServiceSpecificError());
792
793 stream = {streamId++,
794 StreamType::OUTPUT,
795 /*width*/ INT32_MAX,
796 /*height*/ INT32_MAX,
797 static_cast<PixelFormat>(outputStreams[0].format),
798 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
799 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
800 Dataspace::UNKNOWN,
801 StreamRotation::ROTATION_0,
802 std::string(),
803 jpegBufferSize,
804 -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +0000805 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
806 RequestAvailableDynamicRangeProfilesMap::
807 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -0800808
809 streams[0] = stream;
810 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
811 jpegBufferSize);
812
813 config.streamConfigCounter = streamConfigCounter++;
814 halConfigs.clear();
815 ret = mSession->configureStreams(config, &halConfigs);
816 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT), ret.getServiceSpecificError());
817
818 for (auto& it : outputStreams) {
819 stream = {streamId++,
820 StreamType::OUTPUT,
821 it.width,
822 it.height,
823 static_cast<PixelFormat>(UINT32_MAX),
824 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
825 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
826 Dataspace::UNKNOWN,
827 StreamRotation::ROTATION_0,
828 std::string(),
829 jpegBufferSize,
830 -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +0000831 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
832 RequestAvailableDynamicRangeProfilesMap::
833 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -0800834
835 streams[0] = stream;
836 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
837 jpegBufferSize);
838 config.streamConfigCounter = streamConfigCounter++;
839 halConfigs.clear();
840 ret = mSession->configureStreams(config, &halConfigs);
841 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT),
842 ret.getServiceSpecificError());
843
844 stream = {streamId++,
845 StreamType::OUTPUT,
846 it.width,
847 it.height,
848 static_cast<PixelFormat>(it.format),
849 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
850 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
851 Dataspace::UNKNOWN,
852 static_cast<StreamRotation>(UINT32_MAX),
853 std::string(),
854 jpegBufferSize,
855 -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +0000856 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
857 RequestAvailableDynamicRangeProfilesMap::
858 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -0800859
860 streams[0] = stream;
861 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
862 jpegBufferSize);
863
864 config.streamConfigCounter = streamConfigCounter++;
865 halConfigs.clear();
866 ret = mSession->configureStreams(config, &halConfigs);
867 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT),
868 ret.getServiceSpecificError());
869 }
870
871 ret = mSession->close();
872 mSession = nullptr;
873 ASSERT_TRUE(ret.isOk());
874 }
875}
876
877// Check whether all supported ZSL output stream combinations can be
878// configured successfully.
879TEST_P(CameraAidlTest, configureStreamsZSLInputOutputs) {
880 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
881 std::vector<AvailableStream> inputStreams;
882 std::vector<AvailableZSLInputOutput> inputOutputMap;
883
884 for (const auto& name : cameraDeviceNames) {
885 CameraMetadata meta;
886 std::shared_ptr<ICameraDevice> cameraDevice;
887
888 openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/,
889 &cameraDevice /*out*/);
890 camera_metadata_t* staticMeta = reinterpret_cast<camera_metadata_t*>(meta.metadata.data());
891
892 Status rc = isZSLModeAvailable(staticMeta);
893 if (Status::OPERATION_NOT_SUPPORTED == rc) {
894 ndk::ScopedAStatus ret = mSession->close();
895 mSession = nullptr;
896 ASSERT_TRUE(ret.isOk());
897 continue;
898 }
899 ASSERT_EQ(Status::OK, rc);
900
901 inputStreams.clear();
902 ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta, inputStreams));
903 ASSERT_NE(0u, inputStreams.size());
904
905 inputOutputMap.clear();
906 ASSERT_EQ(Status::OK, getZSLInputOutputMap(staticMeta, inputOutputMap));
907 ASSERT_NE(0u, inputOutputMap.size());
908
909 bool supportMonoY8 = false;
910 if (Status::OK == isMonochromeCamera(staticMeta)) {
911 for (auto& it : inputStreams) {
912 if (it.format == static_cast<uint32_t>(PixelFormat::Y8)) {
913 supportMonoY8 = true;
914 break;
915 }
916 }
917 }
918
919 int32_t jpegBufferSize = 0;
920 ASSERT_EQ(Status::OK, getJpegBufferSize(staticMeta, &jpegBufferSize));
921 ASSERT_NE(0u, jpegBufferSize);
922
923 int32_t streamId = 0;
924 bool hasPrivToY8 = false, hasY8ToY8 = false, hasY8ToBlob = false;
925 uint32_t streamConfigCounter = 0;
926 for (auto& inputIter : inputOutputMap) {
927 AvailableStream input;
928 ASSERT_EQ(Status::OK, findLargestSize(inputStreams, inputIter.inputFormat, input));
929 ASSERT_NE(0u, inputStreams.size());
930
931 if (inputIter.inputFormat ==
932 static_cast<uint32_t>(PixelFormat::IMPLEMENTATION_DEFINED) &&
933 inputIter.outputFormat == static_cast<uint32_t>(PixelFormat::Y8)) {
934 hasPrivToY8 = true;
935 } else if (inputIter.inputFormat == static_cast<uint32_t>(PixelFormat::Y8)) {
936 if (inputIter.outputFormat == static_cast<uint32_t>(PixelFormat::BLOB)) {
937 hasY8ToBlob = true;
938 } else if (inputIter.outputFormat == static_cast<uint32_t>(PixelFormat::Y8)) {
939 hasY8ToY8 = true;
940 }
941 }
942 AvailableStream outputThreshold = {INT32_MAX, INT32_MAX, inputIter.outputFormat};
943 std::vector<AvailableStream> outputStreams;
944 ASSERT_EQ(Status::OK,
945 getAvailableOutputStreams(staticMeta, outputStreams, &outputThreshold));
946 for (auto& outputIter : outputStreams) {
947 Dataspace outputDataSpace =
948 getDataspace(static_cast<PixelFormat>(outputIter.format));
949 Stream zslStream = {
950 streamId++,
951 StreamType::OUTPUT,
952 input.width,
953 input.height,
954 static_cast<PixelFormat>(input.format),
955 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
956 GRALLOC_USAGE_HW_CAMERA_ZSL),
957 Dataspace::UNKNOWN,
958 StreamRotation::ROTATION_0,
959 std::string(),
960 jpegBufferSize,
961 -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +0000962 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
963 RequestAvailableDynamicRangeProfilesMap::
964 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -0800965 Stream inputStream = {
966 streamId++,
967 StreamType::INPUT,
968 input.width,
969 input.height,
970 static_cast<PixelFormat>(input.format),
971 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(0),
972 Dataspace::UNKNOWN,
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 Stream outputStream = {
981 streamId++,
982 StreamType::OUTPUT,
983 outputIter.width,
984 outputIter.height,
985 static_cast<PixelFormat>(outputIter.format),
986 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
987 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
988 outputDataSpace,
989 StreamRotation::ROTATION_0,
990 std::string(),
991 jpegBufferSize,
992 -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +0000993 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
994 RequestAvailableDynamicRangeProfilesMap::
995 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -0800996
997 std::vector<Stream> streams = {inputStream, zslStream, outputStream};
998
999 StreamConfiguration config;
1000 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
1001 jpegBufferSize);
1002
Shuzhen Wangdf89cb92023-11-09 18:24:42 -08001003 verifyStreamCombination(cameraDevice, config, /*expectedStatus*/ true);
Avichal Rakesh362242f2022-02-08 12:40:53 -08001004
1005 config.streamConfigCounter = streamConfigCounter++;
1006 std::vector<HalStream> halConfigs;
1007 ndk::ScopedAStatus ret = mSession->configureStreams(config, &halConfigs);
1008 ASSERT_TRUE(ret.isOk());
1009 ASSERT_EQ(3u, halConfigs.size());
1010 }
1011 }
1012
1013 if (supportMonoY8) {
1014 if (Status::OK == isZSLModeAvailable(staticMeta, PRIV_REPROCESS)) {
1015 ASSERT_TRUE(hasPrivToY8);
1016 }
1017 if (Status::OK == isZSLModeAvailable(staticMeta, YUV_REPROCESS)) {
1018 ASSERT_TRUE(hasY8ToY8);
1019 ASSERT_TRUE(hasY8ToBlob);
1020 }
1021 }
1022
1023 ndk::ScopedAStatus ret = mSession->close();
1024 mSession = nullptr;
1025 ASSERT_TRUE(ret.isOk());
1026 }
1027}
1028
1029// Check whether session parameters are supported. If Hal support for them
1030// exist, then try to configure a preview stream using them.
1031TEST_P(CameraAidlTest, configureStreamsWithSessionParameters) {
1032 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
1033 std::vector<AvailableStream> outputPreviewStreams;
1034 AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
1035 static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
1036
1037 for (const auto& name : cameraDeviceNames) {
1038 CameraMetadata meta;
1039
1040 std::shared_ptr<ICameraDevice> unusedCameraDevice;
1041 openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/,
1042 &unusedCameraDevice /*out*/);
1043 camera_metadata_t* staticMetaBuffer =
1044 reinterpret_cast<camera_metadata_t*>(meta.metadata.data());
1045
1046 std::unordered_set<int32_t> availableSessionKeys;
1047 auto rc = getSupportedKeys(staticMetaBuffer, ANDROID_REQUEST_AVAILABLE_SESSION_KEYS,
1048 &availableSessionKeys);
1049 ASSERT_TRUE(Status::OK == rc);
1050 if (availableSessionKeys.empty()) {
1051 ndk::ScopedAStatus ret = mSession->close();
1052 mSession = nullptr;
1053 ASSERT_TRUE(ret.isOk());
1054 continue;
1055 }
1056
1057 android::hardware::camera::common::V1_0::helper::CameraMetadata previewRequestSettings;
1058 android::hardware::camera::common::V1_0::helper::CameraMetadata sessionParams,
1059 modifiedSessionParams;
1060 constructFilteredSettings(mSession, availableSessionKeys, RequestTemplate::PREVIEW,
1061 &previewRequestSettings, &sessionParams);
1062 if (sessionParams.isEmpty()) {
1063 ndk::ScopedAStatus ret = mSession->close();
1064 mSession = nullptr;
1065 ASSERT_TRUE(ret.isOk());
1066 continue;
1067 }
1068
1069 outputPreviewStreams.clear();
1070
1071 ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMetaBuffer, outputPreviewStreams,
1072 &previewThreshold));
1073 ASSERT_NE(0u, outputPreviewStreams.size());
1074
Avichal Rakeshd3503a32022-02-25 06:23:14 +00001075 Stream previewStream = {
1076 0,
1077 StreamType::OUTPUT,
1078 outputPreviewStreams[0].width,
1079 outputPreviewStreams[0].height,
1080 static_cast<PixelFormat>(outputPreviewStreams[0].format),
1081 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
1082 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
1083 Dataspace::UNKNOWN,
1084 StreamRotation::ROTATION_0,
1085 std::string(),
1086 /*bufferSize*/ 0,
1087 /*groupId*/ -1,
1088 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
1089 RequestAvailableDynamicRangeProfilesMap::
1090 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08001091
1092 std::vector<Stream> streams = {previewStream};
1093 StreamConfiguration config;
1094
1095 config.streams = streams;
1096 config.operationMode = StreamConfigurationMode::NORMAL_MODE;
1097 modifiedSessionParams = sessionParams;
1098 auto sessionParamsBuffer = sessionParams.release();
1099 std::vector<uint8_t> rawSessionParam =
1100 std::vector(reinterpret_cast<uint8_t*>(sessionParamsBuffer),
1101 reinterpret_cast<uint8_t*>(sessionParamsBuffer) +
1102 get_camera_metadata_size(sessionParamsBuffer));
1103
1104 config.sessionParams.metadata = rawSessionParam;
1105 config.streamConfigCounter = 0;
1106 config.streams = {previewStream};
1107 config.streamConfigCounter = 0;
1108 config.multiResolutionInputImage = false;
1109
1110 bool newSessionParamsAvailable = false;
1111 for (const auto& it : availableSessionKeys) {
1112 if (modifiedSessionParams.exists(it)) {
1113 modifiedSessionParams.erase(it);
1114 newSessionParamsAvailable = true;
1115 break;
1116 }
1117 }
1118 if (newSessionParamsAvailable) {
1119 auto modifiedSessionParamsBuffer = modifiedSessionParams.release();
1120 verifySessionReconfigurationQuery(mSession, sessionParamsBuffer,
1121 modifiedSessionParamsBuffer);
1122 modifiedSessionParams.acquire(modifiedSessionParamsBuffer);
1123 }
1124
1125 std::vector<HalStream> halConfigs;
1126 ndk::ScopedAStatus ret = mSession->configureStreams(config, &halConfigs);
1127 ASSERT_TRUE(ret.isOk());
1128 ASSERT_EQ(1u, halConfigs.size());
1129
1130 sessionParams.acquire(sessionParamsBuffer);
1131 ret = mSession->close();
1132 mSession = nullptr;
1133 ASSERT_TRUE(ret.isOk());
1134 }
1135}
1136
1137// Verify that all supported preview + still capture stream combinations
1138// can be configured successfully.
1139TEST_P(CameraAidlTest, configureStreamsPreviewStillOutputs) {
1140 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
1141 std::vector<AvailableStream> outputBlobStreams;
1142 std::vector<AvailableStream> outputPreviewStreams;
1143 AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
1144 static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
1145 AvailableStream blobThreshold = {INT32_MAX, INT32_MAX, static_cast<int32_t>(PixelFormat::BLOB)};
1146
1147 for (const auto& name : cameraDeviceNames) {
1148 CameraMetadata meta;
1149
1150 std::shared_ptr<ICameraDevice> cameraDevice;
1151 openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/,
1152 &cameraDevice /*out*/);
1153
1154 camera_metadata_t* staticMeta = reinterpret_cast<camera_metadata_t*>(meta.metadata.data());
1155
1156 // Check if camera support depth only
1157 if (isDepthOnly(staticMeta)) {
1158 ndk::ScopedAStatus ret = mSession->close();
1159 mSession = nullptr;
1160 ASSERT_TRUE(ret.isOk());
1161 continue;
1162 }
1163
1164 outputBlobStreams.clear();
1165 ASSERT_EQ(Status::OK,
1166 getAvailableOutputStreams(staticMeta, outputBlobStreams, &blobThreshold));
1167 ASSERT_NE(0u, outputBlobStreams.size());
1168
1169 outputPreviewStreams.clear();
1170 ASSERT_EQ(Status::OK,
1171 getAvailableOutputStreams(staticMeta, outputPreviewStreams, &previewThreshold));
1172 ASSERT_NE(0u, outputPreviewStreams.size());
1173
1174 int32_t jpegBufferSize = 0;
1175 ASSERT_EQ(Status::OK, getJpegBufferSize(staticMeta, &jpegBufferSize));
1176 ASSERT_NE(0u, jpegBufferSize);
1177
1178 int32_t streamId = 0;
1179 uint32_t streamConfigCounter = 0;
1180
1181 for (auto& blobIter : outputBlobStreams) {
1182 for (auto& previewIter : outputPreviewStreams) {
1183 Stream previewStream = {
1184 streamId++,
1185 StreamType::OUTPUT,
1186 previewIter.width,
1187 previewIter.height,
1188 static_cast<PixelFormat>(previewIter.format),
1189 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
1190 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
1191 Dataspace::UNKNOWN,
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 Stream blobStream = {
1200 streamId++,
1201 StreamType::OUTPUT,
1202 blobIter.width,
1203 blobIter.height,
1204 static_cast<PixelFormat>(blobIter.format),
1205 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
1206 GRALLOC1_CONSUMER_USAGE_CPU_READ),
1207 Dataspace::JFIF,
1208 StreamRotation::ROTATION_0,
1209 std::string(),
1210 /*bufferSize*/ 0,
1211 /*groupId*/ -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00001212 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
1213 RequestAvailableDynamicRangeProfilesMap::
1214 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08001215 std::vector<Stream> streams = {previewStream, blobStream};
1216 StreamConfiguration config;
1217
1218 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
1219 jpegBufferSize);
1220 config.streamConfigCounter = streamConfigCounter++;
Shuzhen Wangdf89cb92023-11-09 18:24:42 -08001221 verifyStreamCombination(cameraDevice, config, /*expectedStatus*/ true);
Avichal Rakesh362242f2022-02-08 12:40:53 -08001222
1223 std::vector<HalStream> halConfigs;
1224 ndk::ScopedAStatus ret = mSession->configureStreams(config, &halConfigs);
1225 ASSERT_TRUE(ret.isOk());
1226 ASSERT_EQ(2u, halConfigs.size());
1227 }
1228 }
1229
1230 ndk::ScopedAStatus ret = mSession->close();
1231 mSession = nullptr;
1232 ASSERT_TRUE(ret.isOk());
1233 }
1234}
1235
1236// In case constrained mode is supported, test whether it can be
1237// configured. Additionally check for common invalid inputs when
1238// using this mode.
1239TEST_P(CameraAidlTest, configureStreamsConstrainedOutputs) {
1240 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
1241
1242 for (const auto& name : cameraDeviceNames) {
1243 CameraMetadata meta;
1244 std::shared_ptr<ICameraDevice> cameraDevice;
1245
1246 openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/,
1247 &cameraDevice /*out*/);
1248 camera_metadata_t* staticMeta = reinterpret_cast<camera_metadata_t*>(meta.metadata.data());
1249
1250 Status rc = isConstrainedModeAvailable(staticMeta);
1251 if (Status::OPERATION_NOT_SUPPORTED == rc) {
1252 ndk::ScopedAStatus ret = mSession->close();
1253 mSession = nullptr;
1254 ASSERT_TRUE(ret.isOk());
1255 continue;
1256 }
1257 ASSERT_EQ(Status::OK, rc);
1258
1259 AvailableStream hfrStream;
1260 rc = pickConstrainedModeSize(staticMeta, hfrStream);
1261 ASSERT_EQ(Status::OK, rc);
1262
1263 int32_t streamId = 0;
1264 uint32_t streamConfigCounter = 0;
1265 Stream stream = {streamId,
1266 StreamType::OUTPUT,
1267 hfrStream.width,
1268 hfrStream.height,
1269 static_cast<PixelFormat>(hfrStream.format),
1270 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
1271 GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER),
1272 Dataspace::UNKNOWN,
1273 StreamRotation::ROTATION_0,
1274 std::string(),
1275 /*bufferSize*/ 0,
1276 /*groupId*/ -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00001277 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
1278 RequestAvailableDynamicRangeProfilesMap::
1279 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08001280 std::vector<Stream> streams = {stream};
1281 StreamConfiguration config;
1282 createStreamConfiguration(streams, StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE,
1283 &config);
1284
Shuzhen Wangdf89cb92023-11-09 18:24:42 -08001285 verifyStreamCombination(cameraDevice, config, /*expectedStatus*/ true);
Avichal Rakesh362242f2022-02-08 12:40:53 -08001286
1287 config.streamConfigCounter = streamConfigCounter++;
1288 std::vector<HalStream> halConfigs;
1289 ndk::ScopedAStatus ret = mSession->configureStreams(config, &halConfigs);
1290 ASSERT_TRUE(ret.isOk());
1291 ASSERT_EQ(1u, halConfigs.size());
1292 ASSERT_EQ(halConfigs[0].id, streamId);
1293
1294 stream = {streamId++,
1295 StreamType::OUTPUT,
1296 static_cast<uint32_t>(0),
1297 static_cast<uint32_t>(0),
1298 static_cast<PixelFormat>(hfrStream.format),
1299 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
1300 GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER),
1301 Dataspace::UNKNOWN,
1302 StreamRotation::ROTATION_0,
1303 std::string(),
1304 /*bufferSize*/ 0,
1305 /*groupId*/ -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00001306 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
1307 RequestAvailableDynamicRangeProfilesMap::
1308 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08001309 streams[0] = stream;
1310 createStreamConfiguration(streams, StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE,
1311 &config);
1312
1313 config.streamConfigCounter = streamConfigCounter++;
1314 std::vector<HalStream> halConfig;
1315 ret = mSession->configureStreams(config, &halConfig);
1316 ASSERT_TRUE(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT) ==
1317 ret.getServiceSpecificError() ||
1318 static_cast<int32_t>(Status::INTERNAL_ERROR) == ret.getServiceSpecificError());
1319
1320 stream = {streamId++,
1321 StreamType::OUTPUT,
1322 INT32_MAX,
1323 INT32_MAX,
1324 static_cast<PixelFormat>(hfrStream.format),
1325 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
1326 GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER),
1327 Dataspace::UNKNOWN,
1328 StreamRotation::ROTATION_0,
1329 std::string(),
1330 /*bufferSize*/ 0,
1331 /*groupId*/ -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00001332 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
1333 RequestAvailableDynamicRangeProfilesMap::
1334 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08001335 streams[0] = stream;
1336 createStreamConfiguration(streams, StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE,
1337 &config);
1338
1339 config.streamConfigCounter = streamConfigCounter++;
1340 halConfigs.clear();
1341 ret = mSession->configureStreams(config, &halConfigs);
1342 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT), ret.getServiceSpecificError());
1343
1344 stream = {streamId++,
1345 StreamType::OUTPUT,
1346 hfrStream.width,
1347 hfrStream.height,
1348 static_cast<PixelFormat>(UINT32_MAX),
1349 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
1350 GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER),
1351 Dataspace::UNKNOWN,
1352 StreamRotation::ROTATION_0,
1353 std::string(),
1354 /*bufferSize*/ 0,
1355 /*groupId*/ -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00001356 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
1357 RequestAvailableDynamicRangeProfilesMap::
1358 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08001359 streams[0] = stream;
1360 createStreamConfiguration(streams, StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE,
1361 &config);
1362
1363 config.streamConfigCounter = streamConfigCounter++;
1364 halConfigs.clear();
1365 ret = mSession->configureStreams(config, &halConfigs);
1366 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT), ret.getServiceSpecificError());
1367
1368 ret = mSession->close();
1369 mSession = nullptr;
1370 ASSERT_TRUE(ret.isOk());
1371 }
1372}
1373
1374// Verify that all supported video + snapshot stream combinations can
1375// be configured successfully.
1376TEST_P(CameraAidlTest, configureStreamsVideoStillOutputs) {
1377 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
1378 std::vector<AvailableStream> outputBlobStreams;
1379 std::vector<AvailableStream> outputVideoStreams;
1380 AvailableStream videoThreshold = {kMaxVideoWidth, kMaxVideoHeight,
1381 static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
1382 AvailableStream blobThreshold = {kMaxVideoWidth, kMaxVideoHeight,
1383 static_cast<int32_t>(PixelFormat::BLOB)};
1384
1385 for (const auto& name : cameraDeviceNames) {
1386 CameraMetadata meta;
1387 std::shared_ptr<ICameraDevice> cameraDevice;
1388
1389 openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/,
1390 &cameraDevice /*out*/);
1391
1392 camera_metadata_t* staticMeta = reinterpret_cast<camera_metadata_t*>(meta.metadata.data());
1393
1394 // Check if camera support depth only
1395 if (isDepthOnly(staticMeta)) {
1396 ndk::ScopedAStatus ret = mSession->close();
1397 mSession = nullptr;
1398 ASSERT_TRUE(ret.isOk());
1399 continue;
1400 }
1401
1402 outputBlobStreams.clear();
1403 ASSERT_EQ(Status::OK,
1404 getAvailableOutputStreams(staticMeta, outputBlobStreams, &blobThreshold));
1405 ASSERT_NE(0u, outputBlobStreams.size());
1406
1407 outputVideoStreams.clear();
1408 ASSERT_EQ(Status::OK,
1409 getAvailableOutputStreams(staticMeta, outputVideoStreams, &videoThreshold));
1410 ASSERT_NE(0u, outputVideoStreams.size());
1411
1412 int32_t jpegBufferSize = 0;
1413 ASSERT_EQ(Status::OK, getJpegBufferSize(staticMeta, &jpegBufferSize));
1414 ASSERT_NE(0u, jpegBufferSize);
1415
1416 int32_t streamId = 0;
1417 uint32_t streamConfigCounter = 0;
1418 for (auto& blobIter : outputBlobStreams) {
1419 for (auto& videoIter : outputVideoStreams) {
1420 Stream videoStream = {
1421 streamId++,
1422 StreamType::OUTPUT,
1423 videoIter.width,
1424 videoIter.height,
1425 static_cast<PixelFormat>(videoIter.format),
1426 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
1427 GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER),
1428 Dataspace::UNKNOWN,
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 Stream blobStream = {
1437 streamId++,
1438 StreamType::OUTPUT,
1439 blobIter.width,
1440 blobIter.height,
1441 static_cast<PixelFormat>(blobIter.format),
1442 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
1443 GRALLOC1_CONSUMER_USAGE_CPU_READ),
1444 Dataspace::JFIF,
1445 StreamRotation::ROTATION_0,
1446 std::string(),
1447 jpegBufferSize,
1448 /*groupId*/ -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00001449 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
1450 RequestAvailableDynamicRangeProfilesMap::
1451 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08001452 std::vector<Stream> streams = {videoStream, blobStream};
1453 StreamConfiguration config;
1454
1455 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
1456 jpegBufferSize);
Shuzhen Wangdf89cb92023-11-09 18:24:42 -08001457 verifyStreamCombination(cameraDevice, config, /*expectedStatus*/ true);
Avichal Rakesh362242f2022-02-08 12:40:53 -08001458
1459 config.streamConfigCounter = streamConfigCounter++;
1460 std::vector<HalStream> halConfigs;
1461 ndk::ScopedAStatus ret = mSession->configureStreams(config, &halConfigs);
1462 ASSERT_TRUE(ret.isOk());
1463 ASSERT_EQ(2u, halConfigs.size());
1464 }
1465 }
1466
1467 ndk::ScopedAStatus ret = mSession->close();
1468 mSession = nullptr;
1469 ASSERT_TRUE(ret.isOk());
1470 }
1471}
1472
1473// Generate and verify a camera capture request
1474TEST_P(CameraAidlTest, processCaptureRequestPreview) {
1475 // TODO(b/220897574): Failing with BUFFER_ERROR
1476 processCaptureRequestInternal(GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, RequestTemplate::PREVIEW,
1477 false /*secureOnlyCameras*/);
1478}
1479
1480// Generate and verify a secure camera capture request
1481TEST_P(CameraAidlTest, processSecureCaptureRequest) {
1482 processCaptureRequestInternal(GRALLOC1_PRODUCER_USAGE_PROTECTED, RequestTemplate::STILL_CAPTURE,
1483 true /*secureOnlyCameras*/);
1484}
1485
1486TEST_P(CameraAidlTest, processCaptureRequestPreviewStabilization) {
1487 std::unordered_map<std::string, nsecs_t> cameraDeviceToTimeLag;
1488 processPreviewStabilizationCaptureRequestInternal(/*previewStabilizationOn*/ false,
1489 cameraDeviceToTimeLag);
1490 processPreviewStabilizationCaptureRequestInternal(/*previewStabilizationOn*/ true,
1491 cameraDeviceToTimeLag);
1492}
1493
1494// Generate and verify a multi-camera capture request
1495TEST_P(CameraAidlTest, processMultiCaptureRequestPreview) {
1496 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
1497 AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
1498 static_cast<int32_t>(PixelFormat::YCBCR_420_888)};
1499 int64_t bufferId = 1;
1500 uint32_t frameNumber = 1;
1501 std::vector<uint8_t> settings;
1502 std::vector<uint8_t> emptySettings;
1503 std::string invalidPhysicalId = "-1";
1504
1505 for (const auto& name : cameraDeviceNames) {
1506 std::string version, deviceId;
Avichal Rakeshfbcf7ea2022-03-09 01:00:34 +00001507 ALOGI("processMultiCaptureRequestPreview: Test device %s", name.c_str());
Avichal Rakesh362242f2022-02-08 12:40:53 -08001508 ASSERT_TRUE(matchDeviceName(name, mProviderType, &version, &deviceId));
1509 CameraMetadata metadata;
1510
1511 std::shared_ptr<ICameraDevice> unusedDevice;
1512 openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &metadata /*out*/,
1513 &unusedDevice /*out*/);
1514
1515 camera_metadata_t* staticMeta =
1516 reinterpret_cast<camera_metadata_t*>(metadata.metadata.data());
1517 Status rc = isLogicalMultiCamera(staticMeta);
1518 if (Status::OPERATION_NOT_SUPPORTED == rc) {
1519 ndk::ScopedAStatus ret = mSession->close();
1520 mSession = nullptr;
1521 ASSERT_TRUE(ret.isOk());
1522 continue;
1523 }
Avichal Rakeshfbcf7ea2022-03-09 01:00:34 +00001524 ASSERT_EQ(Status::OK, rc);
Avichal Rakesh362242f2022-02-08 12:40:53 -08001525
1526 std::unordered_set<std::string> physicalIds;
1527 rc = getPhysicalCameraIds(staticMeta, &physicalIds);
1528 ASSERT_TRUE(Status::OK == rc);
1529 ASSERT_TRUE(physicalIds.size() > 1);
1530
1531 std::unordered_set<int32_t> physicalRequestKeyIDs;
1532 rc = getSupportedKeys(staticMeta, ANDROID_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS,
1533 &physicalRequestKeyIDs);
1534 ASSERT_TRUE(Status::OK == rc);
1535 if (physicalRequestKeyIDs.empty()) {
1536 ndk::ScopedAStatus ret = mSession->close();
1537 mSession = nullptr;
1538 ASSERT_TRUE(ret.isOk());
1539 // The logical camera doesn't support any individual physical requests.
1540 continue;
1541 }
1542
1543 android::hardware::camera::common::V1_0::helper::CameraMetadata defaultPreviewSettings;
1544 android::hardware::camera::common::V1_0::helper::CameraMetadata filteredSettings;
1545 constructFilteredSettings(mSession, physicalRequestKeyIDs, RequestTemplate::PREVIEW,
1546 &defaultPreviewSettings, &filteredSettings);
1547 if (filteredSettings.isEmpty()) {
1548 // No physical device settings in default request.
1549 ndk::ScopedAStatus ret = mSession->close();
1550 mSession = nullptr;
1551 ASSERT_TRUE(ret.isOk());
1552 continue;
1553 }
1554
1555 const camera_metadata_t* settingsBuffer = defaultPreviewSettings.getAndLock();
1556 uint8_t* rawSettingsBuffer = (uint8_t*)settingsBuffer;
1557 settings.assign(rawSettingsBuffer,
1558 rawSettingsBuffer + get_camera_metadata_size(settingsBuffer));
1559 CameraMetadata settingsMetadata = {settings};
1560 overrideRotateAndCrop(&settingsMetadata);
1561
1562 ndk::ScopedAStatus ret = mSession->close();
1563 mSession = nullptr;
1564 ASSERT_TRUE(ret.isOk());
1565
1566 // Leave only 2 physical devices in the id set.
1567 auto it = physicalIds.begin();
1568 std::string physicalDeviceId = *it;
1569 it++;
1570 physicalIds.erase(++it, physicalIds.end());
1571 ASSERT_EQ(physicalIds.size(), 2u);
1572
1573 std::vector<HalStream> halStreams;
1574 bool supportsPartialResults = false;
1575 bool useHalBufManager = false;
1576 int32_t partialResultCount = 0;
1577 Stream previewStream;
1578 std::shared_ptr<DeviceCb> cb;
1579
Avichal Rakeshfbcf7ea2022-03-09 01:00:34 +00001580 configurePreviewStreams(
1581 name, mProvider, &previewThreshold, physicalIds, &mSession, &previewStream,
1582 &halStreams /*out*/, &supportsPartialResults /*out*/, &partialResultCount /*out*/,
1583 &useHalBufManager /*out*/, &cb /*out*/, 0 /*streamConfigCounter*/, true);
1584 if (mSession == nullptr) {
1585 // stream combination not supported by HAL, skip test for device
1586 continue;
1587 }
Avichal Rakesh362242f2022-02-08 12:40:53 -08001588
1589 ::aidl::android::hardware::common::fmq::MQDescriptor<
1590 int8_t, aidl::android::hardware::common::fmq::SynchronizedReadWrite>
1591 descriptor;
1592 auto resultQueueRet = mSession->getCaptureResultMetadataQueue(&descriptor);
1593 ASSERT_TRUE(resultQueueRet.isOk());
1594 std::shared_ptr<ResultMetadataQueue> resultQueue =
1595 std::make_shared<ResultMetadataQueue>(descriptor);
1596 if (!resultQueue->isValid() || resultQueue->availableToWrite() <= 0) {
1597 ALOGE("%s: HAL returns empty result metadata fmq, not use it", __func__);
1598 resultQueue = nullptr;
1599 // Don't use the queue onwards.
1600 }
1601
1602 std::shared_ptr<InFlightRequest> inflightReq = std::make_shared<InFlightRequest>(
1603 static_cast<ssize_t>(halStreams.size()), false, supportsPartialResults,
1604 partialResultCount, physicalIds, resultQueue);
1605
1606 std::vector<CaptureRequest> requests(1);
1607 CaptureRequest& request = requests[0];
1608 request.frameNumber = frameNumber;
1609 request.fmqSettingsSize = 0;
Emilian Peev3d919f92022-04-20 13:50:59 -07001610 request.settings = settingsMetadata;
Avichal Rakesh362242f2022-02-08 12:40:53 -08001611
1612 std::vector<StreamBuffer>& outputBuffers = request.outputBuffers;
1613
1614 std::vector<buffer_handle_t> graphicBuffers;
1615 graphicBuffers.reserve(halStreams.size());
1616 outputBuffers.resize(halStreams.size());
1617 size_t k = 0;
1618 for (const auto& halStream : halStreams) {
1619 buffer_handle_t buffer_handle;
1620 if (useHalBufManager) {
1621 outputBuffers[k] = {halStream.id, /*bufferId*/ 0, NativeHandle(),
1622 BufferStatus::OK, NativeHandle(), NativeHandle()};
1623 } else {
1624 allocateGraphicBuffer(previewStream.width, previewStream.height,
1625 android_convertGralloc1To0Usage(
1626 static_cast<uint64_t>(halStream.producerUsage),
1627 static_cast<uint64_t>(halStream.consumerUsage)),
1628 halStream.overrideFormat, &buffer_handle);
1629 graphicBuffers.push_back(buffer_handle);
1630 outputBuffers[k] = {
1631 halStream.id, bufferId, ::android::makeToAidl(buffer_handle),
1632 BufferStatus::OK, NativeHandle(), NativeHandle()};
1633 bufferId++;
1634 }
1635 k++;
1636 }
1637
1638 std::vector<PhysicalCameraSetting> camSettings(1);
1639 const camera_metadata_t* filteredSettingsBuffer = filteredSettings.getAndLock();
1640 uint8_t* rawFilteredSettingsBuffer = (uint8_t*)filteredSettingsBuffer;
1641 camSettings[0].settings = {std::vector(
1642 rawFilteredSettingsBuffer,
1643 rawFilteredSettingsBuffer + get_camera_metadata_size(filteredSettingsBuffer))};
1644 overrideRotateAndCrop(&camSettings[0].settings);
1645 camSettings[0].fmqSettingsSize = 0;
1646 camSettings[0].physicalCameraId = physicalDeviceId;
1647
1648 request.inputBuffer = {
1649 -1, 0, NativeHandle(), BufferStatus::ERROR, NativeHandle(), NativeHandle()};
1650 request.physicalCameraSettings = camSettings;
1651
1652 {
1653 std::unique_lock<std::mutex> l(mLock);
1654 mInflightMap.clear();
1655 mInflightMap[frameNumber] = inflightReq;
1656 }
1657
1658 int32_t numRequestProcessed = 0;
1659 std::vector<BufferCache> cachesToRemove;
1660 ndk::ScopedAStatus returnStatus =
1661 mSession->processCaptureRequest(requests, cachesToRemove, &numRequestProcessed);
1662 ASSERT_TRUE(returnStatus.isOk());
1663 ASSERT_EQ(numRequestProcessed, 1u);
1664
1665 {
1666 std::unique_lock<std::mutex> l(mLock);
1667 while (!inflightReq->errorCodeValid &&
1668 ((0 < inflightReq->numBuffersLeft) || (!inflightReq->haveResultMetadata))) {
1669 auto timeout = std::chrono::system_clock::now() +
1670 std::chrono::seconds(kStreamBufferTimeoutSec);
1671 ASSERT_NE(std::cv_status::timeout, mResultCondition.wait_until(l, timeout));
1672 }
1673
1674 ASSERT_FALSE(inflightReq->errorCodeValid);
1675 ASSERT_NE(inflightReq->resultOutputBuffers.size(), 0u);
1676
1677 request.frameNumber++;
1678 // Empty settings should be supported after the first call
1679 // for repeating requests.
1680 request.settings.metadata.clear();
1681 request.physicalCameraSettings[0].settings.metadata.clear();
1682 // The buffer has been registered to HAL by bufferId, so per
1683 // API contract we should send a null handle for this buffer
1684 request.outputBuffers[0].buffer = NativeHandle();
1685 mInflightMap.clear();
1686 inflightReq = std::make_shared<InFlightRequest>(
1687 static_cast<ssize_t>(physicalIds.size()), false, supportsPartialResults,
1688 partialResultCount, physicalIds, resultQueue);
1689 mInflightMap[request.frameNumber] = inflightReq;
1690 }
1691
1692 returnStatus =
1693 mSession->processCaptureRequest(requests, cachesToRemove, &numRequestProcessed);
1694 ASSERT_TRUE(returnStatus.isOk());
1695 ASSERT_EQ(numRequestProcessed, 1u);
1696
1697 {
1698 std::unique_lock<std::mutex> l(mLock);
1699 while (!inflightReq->errorCodeValid &&
1700 ((0 < inflightReq->numBuffersLeft) || (!inflightReq->haveResultMetadata))) {
1701 auto timeout = std::chrono::system_clock::now() +
1702 std::chrono::seconds(kStreamBufferTimeoutSec);
1703 ASSERT_NE(std::cv_status::timeout, mResultCondition.wait_until(l, timeout));
1704 }
1705
1706 ASSERT_FALSE(inflightReq->errorCodeValid);
1707 ASSERT_NE(inflightReq->resultOutputBuffers.size(), 0u);
1708 }
1709
1710 // Invalid physical camera id should fail process requests
1711 frameNumber++;
1712 camSettings[0].physicalCameraId = invalidPhysicalId;
1713 camSettings[0].settings.metadata = settings;
1714
1715 request.physicalCameraSettings = camSettings; // Invalid camera settings
1716 returnStatus =
1717 mSession->processCaptureRequest(requests, cachesToRemove, &numRequestProcessed);
1718 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT),
1719 returnStatus.getServiceSpecificError());
1720
1721 defaultPreviewSettings.unlock(settingsBuffer);
1722 filteredSettings.unlock(filteredSettingsBuffer);
1723
1724 if (useHalBufManager) {
1725 std::vector<int32_t> streamIds(halStreams.size());
1726 for (size_t i = 0; i < streamIds.size(); i++) {
1727 streamIds[i] = halStreams[i].id;
1728 }
1729 verifyBuffersReturned(mSession, streamIds, cb);
1730 }
1731
1732 ret = mSession->close();
1733 mSession = nullptr;
1734 ASSERT_TRUE(ret.isOk());
1735 }
1736}
1737
1738// Generate and verify an ultra high resolution capture request
1739TEST_P(CameraAidlTest, processUltraHighResolutionRequest) {
1740 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
1741 int64_t bufferId = 1;
1742 int32_t frameNumber = 1;
1743 CameraMetadata settings;
1744
1745 for (const auto& name : cameraDeviceNames) {
1746 std::string version, deviceId;
1747 ASSERT_TRUE(matchDeviceName(name, mProviderType, &version, &deviceId));
1748 CameraMetadata meta;
1749
1750 std::shared_ptr<ICameraDevice> unusedDevice;
1751 openEmptyDeviceSession(name, mProvider, &mSession, &meta, &unusedDevice);
1752 camera_metadata_t* staticMeta = reinterpret_cast<camera_metadata_t*>(meta.metadata.data());
1753 if (!isUltraHighResolution(staticMeta)) {
1754 ndk::ScopedAStatus ret = mSession->close();
1755 mSession = nullptr;
1756 ASSERT_TRUE(ret.isOk());
1757 continue;
1758 }
1759 CameraMetadata req;
1760 android::hardware::camera::common::V1_0::helper::CameraMetadata defaultSettings;
1761 ndk::ScopedAStatus ret =
1762 mSession->constructDefaultRequestSettings(RequestTemplate::STILL_CAPTURE, &req);
1763 ASSERT_TRUE(ret.isOk());
1764
1765 const camera_metadata_t* metadata =
1766 reinterpret_cast<const camera_metadata_t*>(req.metadata.data());
1767 size_t expectedSize = req.metadata.size();
1768 int result = validate_camera_metadata_structure(metadata, &expectedSize);
1769 ASSERT_TRUE((result == 0) || (result == CAMERA_METADATA_VALIDATION_SHIFTED));
1770
1771 size_t entryCount = get_camera_metadata_entry_count(metadata);
1772 ASSERT_GT(entryCount, 0u);
1773 defaultSettings = metadata;
1774 uint8_t sensorPixelMode =
1775 static_cast<uint8_t>(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION);
1776 ASSERT_EQ(::android::OK,
1777 defaultSettings.update(ANDROID_SENSOR_PIXEL_MODE, &sensorPixelMode, 1));
1778
1779 const camera_metadata_t* settingsBuffer = defaultSettings.getAndLock();
1780 uint8_t* rawSettingsBuffer = (uint8_t*)settingsBuffer;
1781 settings.metadata = std::vector(
1782 rawSettingsBuffer, rawSettingsBuffer + get_camera_metadata_size(settingsBuffer));
1783 overrideRotateAndCrop(&settings);
1784
1785 ret = mSession->close();
1786 mSession = nullptr;
1787 ASSERT_TRUE(ret.isOk());
1788
1789 std::vector<HalStream> halStreams;
1790 bool supportsPartialResults = false;
1791 bool useHalBufManager = false;
1792 int32_t partialResultCount = 0;
1793 Stream previewStream;
1794 std::shared_ptr<DeviceCb> cb;
1795
1796 std::list<PixelFormat> pixelFormats = {PixelFormat::YCBCR_420_888, PixelFormat::RAW16};
1797 for (PixelFormat format : pixelFormats) {
Emilian Peevdda1eb72022-07-28 16:37:40 -07001798 previewStream.usage =
1799 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
1800 GRALLOC1_CONSUMER_USAGE_CPU_READ);
1801 previewStream.dataSpace = Dataspace::UNKNOWN;
Avichal Rakesh362242f2022-02-08 12:40:53 -08001802 configureStreams(name, mProvider, format, &mSession, &previewStream, &halStreams,
1803 &supportsPartialResults, &partialResultCount, &useHalBufManager, &cb,
1804 0, /*maxResolution*/ true);
1805 ASSERT_NE(mSession, nullptr);
1806
1807 ::aidl::android::hardware::common::fmq::MQDescriptor<
1808 int8_t, aidl::android::hardware::common::fmq::SynchronizedReadWrite>
1809 descriptor;
1810 auto resultQueueRet = mSession->getCaptureResultMetadataQueue(&descriptor);
1811 ASSERT_TRUE(resultQueueRet.isOk());
1812
1813 std::shared_ptr<ResultMetadataQueue> resultQueue =
1814 std::make_shared<ResultMetadataQueue>(descriptor);
1815 if (!resultQueue->isValid() || resultQueue->availableToWrite() <= 0) {
1816 ALOGE("%s: HAL returns empty result metadata fmq, not use it", __func__);
1817 resultQueue = nullptr;
1818 // Don't use the queue onwards.
1819 }
1820
1821 std::vector<buffer_handle_t> graphicBuffers;
1822 graphicBuffers.reserve(halStreams.size());
1823 std::shared_ptr<InFlightRequest> inflightReq = std::make_shared<InFlightRequest>(
1824 static_cast<ssize_t>(halStreams.size()), false, supportsPartialResults,
1825 partialResultCount, std::unordered_set<std::string>(), resultQueue);
1826
1827 std::vector<CaptureRequest> requests(1);
1828 CaptureRequest& request = requests[0];
1829 std::vector<StreamBuffer>& outputBuffers = request.outputBuffers;
1830 outputBuffers.resize(halStreams.size());
1831
1832 size_t k = 0;
1833 for (const auto& halStream : halStreams) {
1834 buffer_handle_t buffer_handle;
1835 if (useHalBufManager) {
1836 outputBuffers[k] = {halStream.id, 0,
1837 NativeHandle(), BufferStatus::OK,
1838 NativeHandle(), NativeHandle()};
1839 } else {
1840 allocateGraphicBuffer(previewStream.width, previewStream.height,
1841 android_convertGralloc1To0Usage(
1842 static_cast<uint64_t>(halStream.producerUsage),
1843 static_cast<uint64_t>(halStream.consumerUsage)),
1844 halStream.overrideFormat, &buffer_handle);
1845 graphicBuffers.push_back(buffer_handle);
1846 outputBuffers[k] = {
1847 halStream.id, bufferId, ::android::makeToAidl(buffer_handle),
1848 BufferStatus::OK, NativeHandle(), NativeHandle()};
1849 bufferId++;
1850 }
1851 k++;
1852 }
1853
1854 request.inputBuffer = {
1855 -1, 0, NativeHandle(), BufferStatus::ERROR, NativeHandle(), NativeHandle()};
1856 request.frameNumber = frameNumber;
1857 request.fmqSettingsSize = 0;
1858 request.settings = settings;
1859 request.inputWidth = 0;
1860 request.inputHeight = 0;
1861
1862 {
1863 std::unique_lock<std::mutex> l(mLock);
1864 mInflightMap.clear();
1865 mInflightMap[frameNumber] = inflightReq;
1866 }
1867
1868 int32_t numRequestProcessed = 0;
1869 std::vector<BufferCache> cachesToRemove;
1870 ndk::ScopedAStatus returnStatus =
1871 mSession->processCaptureRequest(requests, cachesToRemove, &numRequestProcessed);
1872 ASSERT_TRUE(returnStatus.isOk());
1873 ASSERT_EQ(numRequestProcessed, 1u);
1874
1875 {
1876 std::unique_lock<std::mutex> l(mLock);
1877 while (!inflightReq->errorCodeValid &&
1878 ((0 < inflightReq->numBuffersLeft) || (!inflightReq->haveResultMetadata))) {
1879 auto timeout = std::chrono::system_clock::now() +
1880 std::chrono::seconds(kStreamBufferTimeoutSec);
1881 ASSERT_NE(std::cv_status::timeout, mResultCondition.wait_until(l, timeout));
1882 }
1883
1884 ASSERT_FALSE(inflightReq->errorCodeValid);
1885 ASSERT_NE(inflightReq->resultOutputBuffers.size(), 0u);
1886 }
1887 if (useHalBufManager) {
1888 std::vector<int32_t> streamIds(halStreams.size());
1889 for (size_t i = 0; i < streamIds.size(); i++) {
1890 streamIds[i] = halStreams[i].id;
1891 }
1892 verifyBuffersReturned(mSession, streamIds, cb);
1893 }
1894
1895 ret = mSession->close();
1896 mSession = nullptr;
1897 ASSERT_TRUE(ret.isOk());
1898 }
1899 }
1900}
1901
1902// Generate and verify 10-bit dynamic range request
1903TEST_P(CameraAidlTest, process10BitDynamicRangeRequest) {
1904 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
Avichal Rakesh362242f2022-02-08 12:40:53 -08001905 CameraMetadata settings;
1906
1907 for (const auto& name : cameraDeviceNames) {
1908 std::string version, deviceId;
1909 ASSERT_TRUE(matchDeviceName(name, mProviderType, &version, &deviceId));
1910 CameraMetadata meta;
1911 std::shared_ptr<ICameraDevice> device;
1912 openEmptyDeviceSession(name, mProvider, &mSession, &meta, &device);
1913 camera_metadata_t* staticMeta = reinterpret_cast<camera_metadata_t*>(meta.metadata.data());
1914 if (!is10BitDynamicRangeCapable(staticMeta)) {
1915 ndk::ScopedAStatus ret = mSession->close();
1916 mSession = nullptr;
1917 ASSERT_TRUE(ret.isOk());
1918 continue;
1919 }
Avichal Rakeshd3503a32022-02-25 06:23:14 +00001920 std::vector<RequestAvailableDynamicRangeProfilesMap> profileList;
Avichal Rakesh362242f2022-02-08 12:40:53 -08001921 get10BitDynamicRangeProfiles(staticMeta, &profileList);
1922 ASSERT_FALSE(profileList.empty());
1923
1924 CameraMetadata req;
1925 android::hardware::camera::common::V1_0::helper::CameraMetadata defaultSettings;
1926 ndk::ScopedAStatus ret =
Emilian Peevdda1eb72022-07-28 16:37:40 -07001927 mSession->constructDefaultRequestSettings(RequestTemplate::PREVIEW, &req);
Avichal Rakesh362242f2022-02-08 12:40:53 -08001928 ASSERT_TRUE(ret.isOk());
1929
1930 const camera_metadata_t* metadata =
1931 reinterpret_cast<const camera_metadata_t*>(req.metadata.data());
1932 size_t expectedSize = req.metadata.size();
1933 int result = validate_camera_metadata_structure(metadata, &expectedSize);
1934 ASSERT_TRUE((result == 0) || (result == CAMERA_METADATA_VALIDATION_SHIFTED));
1935
1936 size_t entryCount = get_camera_metadata_entry_count(metadata);
1937 ASSERT_GT(entryCount, 0u);
1938 defaultSettings = metadata;
1939
1940 const camera_metadata_t* settingsBuffer = defaultSettings.getAndLock();
1941 uint8_t* rawSettingsBuffer = (uint8_t*)settingsBuffer;
1942 settings.metadata = std::vector(
1943 rawSettingsBuffer, rawSettingsBuffer + get_camera_metadata_size(settingsBuffer));
1944 overrideRotateAndCrop(&settings);
1945
1946 ret = mSession->close();
1947 mSession = nullptr;
1948 ASSERT_TRUE(ret.isOk());
1949
1950 std::vector<HalStream> halStreams;
1951 bool supportsPartialResults = false;
1952 bool useHalBufManager = false;
1953 int32_t partialResultCount = 0;
1954 Stream previewStream;
1955 std::shared_ptr<DeviceCb> cb;
1956 for (const auto& profile : profileList) {
Emilian Peevdda1eb72022-07-28 16:37:40 -07001957 previewStream.usage =
1958 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
1959 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER);
1960 previewStream.dataSpace = getDataspace(PixelFormat::IMPLEMENTATION_DEFINED);
Avichal Rakesh362242f2022-02-08 12:40:53 -08001961 configureStreams(name, mProvider, PixelFormat::IMPLEMENTATION_DEFINED, &mSession,
1962 &previewStream, &halStreams, &supportsPartialResults,
1963 &partialResultCount, &useHalBufManager, &cb, 0,
1964 /*maxResolution*/ false, profile);
1965 ASSERT_NE(mSession, nullptr);
1966
1967 ::aidl::android::hardware::common::fmq::MQDescriptor<
1968 int8_t, aidl::android::hardware::common::fmq::SynchronizedReadWrite>
1969 descriptor;
1970 auto resultQueueRet = mSession->getCaptureResultMetadataQueue(&descriptor);
1971 ASSERT_TRUE(resultQueueRet.isOk());
1972
1973 std::shared_ptr<ResultMetadataQueue> resultQueue =
1974 std::make_shared<ResultMetadataQueue>(descriptor);
1975 if (!resultQueue->isValid() || resultQueue->availableToWrite() <= 0) {
1976 ALOGE("%s: HAL returns empty result metadata fmq, not use it", __func__);
1977 resultQueue = nullptr;
1978 // Don't use the queue onwards.
1979 }
1980
Emilian Peevdda1eb72022-07-28 16:37:40 -07001981 mInflightMap.clear();
1982 // Stream as long as needed to fill the Hal inflight queue
1983 std::vector<CaptureRequest> requests(halStreams[0].maxBuffers);
Avichal Rakesh362242f2022-02-08 12:40:53 -08001984
Emilian Peev470d1382023-01-18 11:09:09 -08001985 for (int32_t requestId = 0; requestId < requests.size(); requestId++) {
Emilian Peevdda1eb72022-07-28 16:37:40 -07001986 std::shared_ptr<InFlightRequest> inflightReq = std::make_shared<InFlightRequest>(
1987 static_cast<ssize_t>(halStreams.size()), false, supportsPartialResults,
1988 partialResultCount, std::unordered_set<std::string>(), resultQueue);
Avichal Rakesh362242f2022-02-08 12:40:53 -08001989
Emilian Peev470d1382023-01-18 11:09:09 -08001990 CaptureRequest& request = requests[requestId];
Emilian Peevdda1eb72022-07-28 16:37:40 -07001991 std::vector<StreamBuffer>& outputBuffers = request.outputBuffers;
1992 outputBuffers.resize(halStreams.size());
Avichal Rakesh362242f2022-02-08 12:40:53 -08001993
Emilian Peevdda1eb72022-07-28 16:37:40 -07001994 size_t k = 0;
1995 inflightReq->mOutstandingBufferIds.resize(halStreams.size());
1996 std::vector<buffer_handle_t> graphicBuffers;
1997 graphicBuffers.reserve(halStreams.size());
Avichal Rakesh362242f2022-02-08 12:40:53 -08001998
Emilian Peev470d1382023-01-18 11:09:09 -08001999 auto bufferId = requestId + 1; // Buffer id value 0 is not valid
Emilian Peevdda1eb72022-07-28 16:37:40 -07002000 for (const auto& halStream : halStreams) {
2001 buffer_handle_t buffer_handle;
2002 if (useHalBufManager) {
2003 outputBuffers[k] = {halStream.id, 0,
2004 NativeHandle(), BufferStatus::OK,
2005 NativeHandle(), NativeHandle()};
2006 } else {
2007 auto usage = android_convertGralloc1To0Usage(
2008 static_cast<uint64_t>(halStream.producerUsage),
2009 static_cast<uint64_t>(halStream.consumerUsage));
2010 allocateGraphicBuffer(previewStream.width, previewStream.height, usage,
2011 halStream.overrideFormat, &buffer_handle);
2012
2013 inflightReq->mOutstandingBufferIds[halStream.id][bufferId] = buffer_handle;
2014 graphicBuffers.push_back(buffer_handle);
2015 outputBuffers[k] = {halStream.id, bufferId,
2016 android::makeToAidl(buffer_handle), BufferStatus::OK, NativeHandle(),
2017 NativeHandle()};
Emilian Peevdda1eb72022-07-28 16:37:40 -07002018 }
2019 k++;
Avichal Rakesh362242f2022-02-08 12:40:53 -08002020 }
Avichal Rakesh362242f2022-02-08 12:40:53 -08002021
Emilian Peevdda1eb72022-07-28 16:37:40 -07002022 request.inputBuffer = {
2023 -1, 0, NativeHandle(), BufferStatus::ERROR, NativeHandle(), NativeHandle()};
Emilian Peev470d1382023-01-18 11:09:09 -08002024 request.frameNumber = bufferId;
Emilian Peevdda1eb72022-07-28 16:37:40 -07002025 request.fmqSettingsSize = 0;
2026 request.settings = settings;
2027 request.inputWidth = 0;
2028 request.inputHeight = 0;
Avichal Rakesh362242f2022-02-08 12:40:53 -08002029
Emilian Peevdda1eb72022-07-28 16:37:40 -07002030 {
2031 std::unique_lock<std::mutex> l(mLock);
Emilian Peev470d1382023-01-18 11:09:09 -08002032 mInflightMap[bufferId] = inflightReq;
Emilian Peevdda1eb72022-07-28 16:37:40 -07002033 }
2034
Avichal Rakesh362242f2022-02-08 12:40:53 -08002035 }
2036
2037 int32_t numRequestProcessed = 0;
2038 std::vector<BufferCache> cachesToRemove;
2039 ndk::ScopedAStatus returnStatus =
Emilian Peevdda1eb72022-07-28 16:37:40 -07002040 mSession->processCaptureRequest(requests, cachesToRemove, &numRequestProcessed);
Avichal Rakesh362242f2022-02-08 12:40:53 -08002041 ASSERT_TRUE(returnStatus.isOk());
Emilian Peevdda1eb72022-07-28 16:37:40 -07002042 ASSERT_EQ(numRequestProcessed, requests.size());
Avichal Rakesh362242f2022-02-08 12:40:53 -08002043
Emilian Peevdda1eb72022-07-28 16:37:40 -07002044 returnStatus = mSession->repeatingRequestEnd(requests.size() - 1,
2045 std::vector<int32_t> {halStreams[0].id});
2046 ASSERT_TRUE(returnStatus.isOk());
2047
Emilian Peev470d1382023-01-18 11:09:09 -08002048 // We are keeping frame numbers and buffer ids consistent. Buffer id value of 0
2049 // is used to indicate a buffer that is not present/available so buffer ids as well
2050 // as frame numbers begin with 1.
2051 for (int32_t frameNumber = 1; frameNumber <= requests.size(); frameNumber++) {
Emilian Peevdda1eb72022-07-28 16:37:40 -07002052 const auto& inflightReq = mInflightMap[frameNumber];
Avichal Rakesh362242f2022-02-08 12:40:53 -08002053 std::unique_lock<std::mutex> l(mLock);
2054 while (!inflightReq->errorCodeValid &&
2055 ((0 < inflightReq->numBuffersLeft) || (!inflightReq->haveResultMetadata))) {
2056 auto timeout = std::chrono::system_clock::now() +
2057 std::chrono::seconds(kStreamBufferTimeoutSec);
2058 ASSERT_NE(std::cv_status::timeout, mResultCondition.wait_until(l, timeout));
2059 }
2060
Shuzhen Wang0f56c562023-04-03 16:58:59 -07002061 waitForReleaseFence(inflightReq->resultOutputBuffers);
2062
Avichal Rakesh362242f2022-02-08 12:40:53 -08002063 ASSERT_FALSE(inflightReq->errorCodeValid);
2064 ASSERT_NE(inflightReq->resultOutputBuffers.size(), 0u);
2065 verify10BitMetadata(mHandleImporter, *inflightReq, profile);
2066 }
Emilian Peevdda1eb72022-07-28 16:37:40 -07002067
Avichal Rakesh362242f2022-02-08 12:40:53 -08002068 if (useHalBufManager) {
2069 std::vector<int32_t> streamIds(halStreams.size());
2070 for (size_t i = 0; i < streamIds.size(); i++) {
2071 streamIds[i] = halStreams[i].id;
2072 }
2073 mSession->signalStreamFlush(streamIds, /*streamConfigCounter*/ 0);
2074 cb->waitForBuffersReturned();
2075 }
2076
2077 ret = mSession->close();
2078 mSession = nullptr;
2079 ASSERT_TRUE(ret.isOk());
2080 }
2081 }
2082}
2083
Austin Borger4728fc42022-07-15 11:27:53 -07002084TEST_P(CameraAidlTest, process8BitColorSpaceRequests) {
Austin Borger54b22362023-03-22 11:25:06 -07002085 static int profiles[] = {ColorSpaceNamed::DISPLAY_P3, ColorSpaceNamed::SRGB};
Austin Borger4728fc42022-07-15 11:27:53 -07002086
2087 for (int32_t i = 0; i < sizeof(profiles) / sizeof(profiles[0]); i++) {
2088 processColorSpaceRequest(static_cast<RequestAvailableColorSpaceProfilesMap>(profiles[i]),
2089 static_cast<RequestAvailableDynamicRangeProfilesMap>(
2090 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD));
2091 }
2092}
2093
2094TEST_P(CameraAidlTest, process10BitColorSpaceRequests) {
2095 static const camera_metadata_enum_android_request_available_dynamic_range_profiles_map
2096 dynamicRangeProfiles[] = {
2097 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HLG10,
2098 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10,
2099 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10_PLUS,
2100 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF,
2101 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF_PO,
2102 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM,
2103 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM_PO,
2104 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_REF,
2105 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_REF_PO,
2106 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_OEM,
2107 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_OEM_PO
2108 };
2109
Austin Borger54b22362023-03-22 11:25:06 -07002110 // Process all dynamic range profiles with BT2020_HLG
Austin Borger4728fc42022-07-15 11:27:53 -07002111 for (int32_t i = 0; i < sizeof(dynamicRangeProfiles) / sizeof(dynamicRangeProfiles[0]); i++) {
2112 processColorSpaceRequest(
Austin Borger54b22362023-03-22 11:25:06 -07002113 static_cast<RequestAvailableColorSpaceProfilesMap>(ColorSpaceNamed::BT2020_HLG),
Austin Borger4728fc42022-07-15 11:27:53 -07002114 static_cast<RequestAvailableDynamicRangeProfilesMap>(dynamicRangeProfiles[i]));
2115 }
2116}
2117
Shuzhen Wang4dd6a512022-11-08 20:47:20 +00002118TEST_P(CameraAidlTest, processZoomSettingsOverrideRequests) {
2119 const int32_t kFrameCount = 5;
2120 const int32_t kTestCases = 2;
Shuzhen Wang38ddb272023-05-22 09:40:28 -07002121 const bool kOverrideSequence[kTestCases][kFrameCount] = {// ZOOM, ZOOM, ZOOM, ZOOM, ZOOM;
2122 {true, true, true, true, true},
2123 // OFF, ZOOM, ZOOM, ZOOM, OFF;
2124 {false, true, true, true, false}};
Shuzhen Wang4dd6a512022-11-08 20:47:20 +00002125 const bool kExpectedOverrideResults[kTestCases][kFrameCount] = {
Shuzhen Wang38ddb272023-05-22 09:40:28 -07002126 // All resuls should be overridden except the last one. The last result's
2127 // zoom doesn't have speed-up.
2128 {true, true, true, true, false},
2129 // Because we require at least 1 frame speed-up, request #1, #2 and #3
2130 // will be overridden.
2131 {true, true, true, false, false}};
Shuzhen Wang4dd6a512022-11-08 20:47:20 +00002132
2133 for (int i = 0; i < kTestCases; i++) {
2134 processZoomSettingsOverrideRequests(kFrameCount, kOverrideSequence[i],
2135 kExpectedOverrideResults[i]);
2136 }
2137}
2138
Avichal Rakesh362242f2022-02-08 12:40:53 -08002139// Generate and verify a burst containing alternating sensor sensitivity values
2140TEST_P(CameraAidlTest, processCaptureRequestBurstISO) {
2141 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
2142 AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
2143 static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
2144 int64_t bufferId = 1;
2145 int32_t frameNumber = 1;
2146 float isoTol = .03f;
2147 CameraMetadata settings;
2148
2149 for (const auto& name : cameraDeviceNames) {
2150 CameraMetadata meta;
2151 settings.metadata.clear();
2152 std::shared_ptr<ICameraDevice> unusedDevice;
2153 openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/,
2154 &unusedDevice /*out*/);
2155 camera_metadata_t* staticMetaBuffer =
2156 clone_camera_metadata(reinterpret_cast<camera_metadata_t*>(meta.metadata.data()));
2157 ::android::hardware::camera::common::V1_0::helper::CameraMetadata staticMeta(
2158 staticMetaBuffer);
2159
2160 camera_metadata_entry_t hwLevel = staticMeta.find(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL);
2161 ASSERT_TRUE(0 < hwLevel.count);
2162 if (ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED == hwLevel.data.u8[0] ||
2163 ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL == hwLevel.data.u8[0]) {
2164 // Limited/External devices can skip this test
2165 ndk::ScopedAStatus ret = mSession->close();
2166 mSession = nullptr;
2167 ASSERT_TRUE(ret.isOk());
2168 continue;
2169 }
2170
2171 camera_metadata_entry_t isoRange = staticMeta.find(ANDROID_SENSOR_INFO_SENSITIVITY_RANGE);
2172 ASSERT_EQ(isoRange.count, 2u);
2173
2174 ndk::ScopedAStatus ret = mSession->close();
2175 mSession = nullptr;
2176 ASSERT_TRUE(ret.isOk());
2177
2178 bool supportsPartialResults = false;
2179 bool useHalBufManager = false;
2180 int32_t partialResultCount = 0;
2181 Stream previewStream;
2182 std::vector<HalStream> halStreams;
2183 std::shared_ptr<DeviceCb> cb;
2184 configurePreviewStream(name, mProvider, &previewThreshold, &mSession /*out*/,
2185 &previewStream /*out*/, &halStreams /*out*/,
2186 &supportsPartialResults /*out*/, &partialResultCount /*out*/,
2187 &useHalBufManager /*out*/, &cb /*out*/);
2188
2189 ::aidl::android::hardware::common::fmq::MQDescriptor<
2190 int8_t, aidl::android::hardware::common::fmq::SynchronizedReadWrite>
2191 descriptor;
2192 auto resultQueueRet = mSession->getCaptureResultMetadataQueue(&descriptor);
2193 std::shared_ptr<ResultMetadataQueue> resultQueue =
2194 std::make_shared<ResultMetadataQueue>(descriptor);
2195 ASSERT_TRUE(resultQueueRet.isOk());
2196 if (!resultQueue->isValid() || resultQueue->availableToWrite() <= 0) {
2197 ALOGE("%s: HAL returns empty result metadata fmq, not use it", __func__);
2198 resultQueue = nullptr;
2199 // Don't use the queue onwards.
2200 }
2201
2202 ret = mSession->constructDefaultRequestSettings(RequestTemplate::PREVIEW, &settings);
2203 ASSERT_TRUE(ret.isOk());
2204
2205 ::android::hardware::camera::common::V1_0::helper::CameraMetadata requestMeta;
2206 std::vector<CaptureRequest> requests(kBurstFrameCount);
2207 std::vector<buffer_handle_t> buffers(kBurstFrameCount);
2208 std::vector<std::shared_ptr<InFlightRequest>> inflightReqs(kBurstFrameCount);
2209 std::vector<int32_t> isoValues(kBurstFrameCount);
2210 std::vector<CameraMetadata> requestSettings(kBurstFrameCount);
2211
2212 for (int32_t i = 0; i < kBurstFrameCount; i++) {
2213 std::unique_lock<std::mutex> l(mLock);
2214 CaptureRequest& request = requests[i];
2215 std::vector<StreamBuffer>& outputBuffers = request.outputBuffers;
2216 outputBuffers.resize(1);
2217 StreamBuffer& outputBuffer = outputBuffers[0];
2218
2219 isoValues[i] = ((i % 2) == 0) ? isoRange.data.i32[0] : isoRange.data.i32[1];
2220 if (useHalBufManager) {
2221 outputBuffer = {halStreams[0].id, 0,
2222 NativeHandle(), BufferStatus::OK,
2223 NativeHandle(), NativeHandle()};
2224 } else {
2225 allocateGraphicBuffer(previewStream.width, previewStream.height,
2226 android_convertGralloc1To0Usage(
2227 static_cast<uint64_t>(halStreams[0].producerUsage),
2228 static_cast<uint64_t>(halStreams[0].consumerUsage)),
2229 halStreams[0].overrideFormat, &buffers[i]);
2230 outputBuffer = {halStreams[0].id, bufferId + i, ::android::makeToAidl(buffers[i]),
2231 BufferStatus::OK, NativeHandle(), NativeHandle()};
2232 }
2233
2234 requestMeta.append(reinterpret_cast<camera_metadata_t*>(settings.metadata.data()));
2235
2236 // Disable all 3A routines
2237 uint8_t mode = static_cast<uint8_t>(ANDROID_CONTROL_MODE_OFF);
2238 ASSERT_EQ(::android::OK, requestMeta.update(ANDROID_CONTROL_MODE, &mode, 1));
2239 ASSERT_EQ(::android::OK,
2240 requestMeta.update(ANDROID_SENSOR_SENSITIVITY, &isoValues[i], 1));
2241 camera_metadata_t* metaBuffer = requestMeta.release();
2242 uint8_t* rawMetaBuffer = reinterpret_cast<uint8_t*>(metaBuffer);
2243 requestSettings[i].metadata = std::vector(
2244 rawMetaBuffer, rawMetaBuffer + get_camera_metadata_size(metaBuffer));
2245 overrideRotateAndCrop(&(requestSettings[i]));
2246
2247 request.frameNumber = frameNumber + i;
2248 request.fmqSettingsSize = 0;
2249 request.settings = requestSettings[i];
2250 request.inputBuffer = {
2251 -1, 0, NativeHandle(), BufferStatus::ERROR, NativeHandle(), NativeHandle()};
2252
2253 inflightReqs[i] = std::make_shared<InFlightRequest>(1, false, supportsPartialResults,
2254 partialResultCount, resultQueue);
2255 mInflightMap[frameNumber + i] = inflightReqs[i];
2256 }
2257
2258 int32_t numRequestProcessed = 0;
2259 std::vector<BufferCache> cachesToRemove;
2260
2261 ndk::ScopedAStatus returnStatus =
2262 mSession->processCaptureRequest(requests, cachesToRemove, &numRequestProcessed);
2263 ASSERT_TRUE(returnStatus.isOk());
2264 ASSERT_EQ(numRequestProcessed, kBurstFrameCount);
2265
2266 for (size_t i = 0; i < kBurstFrameCount; i++) {
2267 std::unique_lock<std::mutex> l(mLock);
2268 while (!inflightReqs[i]->errorCodeValid && ((0 < inflightReqs[i]->numBuffersLeft) ||
2269 (!inflightReqs[i]->haveResultMetadata))) {
2270 auto timeout = std::chrono::system_clock::now() +
2271 std::chrono::seconds(kStreamBufferTimeoutSec);
2272 ASSERT_NE(std::cv_status::timeout, mResultCondition.wait_until(l, timeout));
2273 }
2274
2275 ASSERT_FALSE(inflightReqs[i]->errorCodeValid);
2276 ASSERT_NE(inflightReqs[i]->resultOutputBuffers.size(), 0u);
2277 ASSERT_EQ(previewStream.id, inflightReqs[i]->resultOutputBuffers[0].buffer.streamId);
2278 ASSERT_FALSE(inflightReqs[i]->collectedResult.isEmpty());
2279 ASSERT_TRUE(inflightReqs[i]->collectedResult.exists(ANDROID_SENSOR_SENSITIVITY));
2280 camera_metadata_entry_t isoResult =
2281 inflightReqs[i]->collectedResult.find(ANDROID_SENSOR_SENSITIVITY);
2282 ASSERT_TRUE(std::abs(isoResult.data.i32[0] - isoValues[i]) <=
2283 std::round(isoValues[i] * isoTol));
2284 }
2285
2286 if (useHalBufManager) {
2287 verifyBuffersReturned(mSession, previewStream.id, cb);
2288 }
2289 ret = mSession->close();
2290 mSession = nullptr;
2291 ASSERT_TRUE(ret.isOk());
2292 }
2293}
2294
2295// Test whether an incorrect capture request with missing settings will
2296// be reported correctly.
2297TEST_P(CameraAidlTest, processCaptureRequestInvalidSinglePreview) {
2298 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
2299 std::vector<AvailableStream> outputPreviewStreams;
2300 AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
2301 static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
2302 int64_t bufferId = 1;
2303 int32_t frameNumber = 1;
2304 CameraMetadata settings;
2305
2306 for (const auto& name : cameraDeviceNames) {
2307 Stream previewStream;
2308 std::vector<HalStream> halStreams;
2309 std::shared_ptr<DeviceCb> cb;
2310 bool supportsPartialResults = false;
2311 bool useHalBufManager = false;
2312 int32_t partialResultCount = 0;
2313 configurePreviewStream(name, mProvider, &previewThreshold, &mSession /*out*/,
2314 &previewStream /*out*/, &halStreams /*out*/,
2315 &supportsPartialResults /*out*/, &partialResultCount /*out*/,
2316 &useHalBufManager /*out*/, &cb /*out*/);
2317 ASSERT_NE(mSession, nullptr);
2318 ASSERT_FALSE(halStreams.empty());
2319
2320 buffer_handle_t buffer_handle = nullptr;
2321
2322 if (useHalBufManager) {
2323 bufferId = 0;
2324 } else {
2325 allocateGraphicBuffer(previewStream.width, previewStream.height,
2326 android_convertGralloc1To0Usage(
2327 static_cast<uint64_t>(halStreams[0].producerUsage),
2328 static_cast<uint64_t>(halStreams[0].consumerUsage)),
2329 halStreams[0].overrideFormat, &buffer_handle);
2330 }
2331
2332 std::vector<CaptureRequest> requests(1);
2333 CaptureRequest& request = requests[0];
2334 std::vector<StreamBuffer>& outputBuffers = request.outputBuffers;
2335 outputBuffers.resize(1);
2336 StreamBuffer& outputBuffer = outputBuffers[0];
2337
2338 outputBuffer = {
2339 halStreams[0].id,
2340 bufferId,
2341 buffer_handle == nullptr ? NativeHandle() : ::android::makeToAidl(buffer_handle),
2342 BufferStatus::OK,
2343 NativeHandle(),
2344 NativeHandle()};
2345
2346 request.inputBuffer = {
2347 -1, 0, NativeHandle(), BufferStatus::ERROR, NativeHandle(), NativeHandle()};
2348 request.frameNumber = frameNumber;
2349 request.fmqSettingsSize = 0;
2350 request.settings = settings;
2351
2352 // Settings were not correctly initialized, we should fail here
2353 int32_t numRequestProcessed = 0;
2354 std::vector<BufferCache> cachesToRemove;
2355 ndk::ScopedAStatus ret =
2356 mSession->processCaptureRequest(requests, cachesToRemove, &numRequestProcessed);
2357 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT), ret.getServiceSpecificError());
2358 ASSERT_EQ(numRequestProcessed, 0u);
2359
2360 ret = mSession->close();
2361 mSession = nullptr;
2362 ASSERT_TRUE(ret.isOk());
2363 }
2364}
2365
2366// Verify camera offline session behavior
2367TEST_P(CameraAidlTest, switchToOffline) {
2368 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
2369 AvailableStream threshold = {kMaxStillWidth, kMaxStillHeight,
2370 static_cast<int32_t>(PixelFormat::BLOB)};
2371 int64_t bufferId = 1;
2372 int32_t frameNumber = 1;
2373 CameraMetadata settings;
2374
2375 for (const auto& name : cameraDeviceNames) {
2376 CameraMetadata meta;
2377 {
2378 std::shared_ptr<ICameraDevice> unusedDevice;
2379 openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/,
2380 &unusedDevice);
2381 camera_metadata_t* staticMetaBuffer = clone_camera_metadata(
2382 reinterpret_cast<camera_metadata_t*>(meta.metadata.data()));
2383 ::android::hardware::camera::common::V1_0::helper::CameraMetadata staticMeta(
2384 staticMetaBuffer);
2385
2386 if (isOfflineSessionSupported(staticMetaBuffer) != Status::OK) {
2387 ndk::ScopedAStatus ret = mSession->close();
2388 mSession = nullptr;
2389 ASSERT_TRUE(ret.isOk());
2390 continue;
2391 }
2392 ndk::ScopedAStatus ret = mSession->close();
2393 mSession = nullptr;
2394 ASSERT_TRUE(ret.isOk());
2395 }
2396
2397 bool supportsPartialResults = false;
2398 int32_t partialResultCount = 0;
2399 Stream stream;
2400 std::vector<HalStream> halStreams;
2401 std::shared_ptr<DeviceCb> cb;
2402 int32_t jpegBufferSize;
2403 bool useHalBufManager;
2404 configureOfflineStillStream(name, mProvider, &threshold, &mSession /*out*/, &stream /*out*/,
2405 &halStreams /*out*/, &supportsPartialResults /*out*/,
2406 &partialResultCount /*out*/, &cb /*out*/,
2407 &jpegBufferSize /*out*/, &useHalBufManager /*out*/);
2408
2409 auto ret = mSession->constructDefaultRequestSettings(RequestTemplate::STILL_CAPTURE,
2410 &settings);
2411 ASSERT_TRUE(ret.isOk());
2412
2413 ::aidl::android::hardware::common::fmq::MQDescriptor<
2414 int8_t, aidl::android::hardware::common::fmq::SynchronizedReadWrite>
2415 descriptor;
2416
2417 ndk::ScopedAStatus resultQueueRet = mSession->getCaptureResultMetadataQueue(&descriptor);
2418 ASSERT_TRUE(resultQueueRet.isOk());
2419 std::shared_ptr<ResultMetadataQueue> resultQueue =
2420 std::make_shared<ResultMetadataQueue>(descriptor);
2421 if (!resultQueue->isValid() || resultQueue->availableToWrite() <= 0) {
2422 ALOGE("%s: HAL returns empty result metadata fmq, not use it", __func__);
2423 resultQueue = nullptr;
2424 // Don't use the queue onwards.
2425 }
2426
2427 ::android::hardware::camera::common::V1_0::helper::CameraMetadata requestMeta;
2428
2429 std::vector<buffer_handle_t> buffers(kBurstFrameCount);
2430 std::vector<std::shared_ptr<InFlightRequest>> inflightReqs(kBurstFrameCount);
2431 std::vector<CameraMetadata> requestSettings(kBurstFrameCount);
2432
2433 std::vector<CaptureRequest> requests(kBurstFrameCount);
2434
2435 HalStream halStream = halStreams[0];
2436 for (uint32_t i = 0; i < kBurstFrameCount; i++) {
2437 CaptureRequest& request = requests[i];
2438 std::vector<StreamBuffer>& outputBuffers = request.outputBuffers;
2439 outputBuffers.resize(1);
2440 StreamBuffer& outputBuffer = outputBuffers[0];
2441
2442 std::unique_lock<std::mutex> l(mLock);
2443 if (useHalBufManager) {
2444 outputBuffer = {halStream.id, 0, NativeHandle(), BufferStatus::OK, NativeHandle(),
2445 NativeHandle()};
2446 } else {
2447 // jpeg buffer (w,h) = (blobLen, 1)
2448 allocateGraphicBuffer(jpegBufferSize, /*height*/ 1,
2449 android_convertGralloc1To0Usage(
2450 static_cast<uint64_t>(halStream.producerUsage),
2451 static_cast<uint64_t>(halStream.consumerUsage)),
2452 halStream.overrideFormat, &buffers[i]);
2453 outputBuffer = {halStream.id, bufferId + i, ::android::makeToAidl(buffers[i]),
2454 BufferStatus::OK, NativeHandle(), NativeHandle()};
2455 }
2456
2457 requestMeta.clear();
2458 requestMeta.append(reinterpret_cast<camera_metadata_t*>(settings.metadata.data()));
2459
2460 camera_metadata_t* metaBuffer = requestMeta.release();
2461 uint8_t* rawMetaBuffer = reinterpret_cast<uint8_t*>(metaBuffer);
2462 requestSettings[i].metadata = std::vector(
2463 rawMetaBuffer, rawMetaBuffer + get_camera_metadata_size(metaBuffer));
2464 overrideRotateAndCrop(&requestSettings[i]);
2465
2466 request.frameNumber = frameNumber + i;
2467 request.fmqSettingsSize = 0;
2468 request.settings = requestSettings[i];
2469 request.inputBuffer = {/*streamId*/ -1,
2470 /*bufferId*/ 0, NativeHandle(),
2471 BufferStatus::ERROR, NativeHandle(),
2472 NativeHandle()};
2473
2474 inflightReqs[i] = std::make_shared<InFlightRequest>(1, false, supportsPartialResults,
2475 partialResultCount, resultQueue);
2476 mInflightMap[frameNumber + i] = inflightReqs[i];
2477 }
2478
2479 int32_t numRequestProcessed = 0;
2480 std::vector<BufferCache> cachesToRemove;
2481
2482 ndk::ScopedAStatus returnStatus =
2483 mSession->processCaptureRequest(requests, cachesToRemove, &numRequestProcessed);
2484 ASSERT_TRUE(returnStatus.isOk());
2485 ASSERT_EQ(numRequestProcessed, kBurstFrameCount);
2486
2487 std::vector<int32_t> offlineStreamIds = {halStream.id};
2488 CameraOfflineSessionInfo offlineSessionInfo;
2489 std::shared_ptr<ICameraOfflineSession> offlineSession;
2490 returnStatus =
2491 mSession->switchToOffline(offlineStreamIds, &offlineSessionInfo, &offlineSession);
2492
2493 if (!halStreams[0].supportOffline) {
2494 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT),
2495 returnStatus.getServiceSpecificError());
2496 ret = mSession->close();
2497 mSession = nullptr;
2498 ASSERT_TRUE(ret.isOk());
2499 continue;
2500 }
2501
2502 ASSERT_TRUE(returnStatus.isOk());
2503 // Hal might be unable to find any requests qualified for offline mode.
2504 if (offlineSession == nullptr) {
2505 ret = mSession->close();
2506 mSession = nullptr;
2507 ASSERT_TRUE(ret.isOk());
2508 continue;
2509 }
2510
2511 ASSERT_EQ(offlineSessionInfo.offlineStreams.size(), 1u);
2512 ASSERT_EQ(offlineSessionInfo.offlineStreams[0].id, halStream.id);
2513 ASSERT_NE(offlineSessionInfo.offlineRequests.size(), 0u);
2514
2515 // close device session to make sure offline session does not rely on it
2516 ret = mSession->close();
2517 mSession = nullptr;
2518 ASSERT_TRUE(ret.isOk());
2519
2520 ::aidl::android::hardware::common::fmq::MQDescriptor<
2521 int8_t, aidl::android::hardware::common::fmq::SynchronizedReadWrite>
2522 offlineResultDescriptor;
2523
2524 auto offlineResultQueueRet =
2525 offlineSession->getCaptureResultMetadataQueue(&offlineResultDescriptor);
2526 std::shared_ptr<ResultMetadataQueue> offlineResultQueue =
2527 std::make_shared<ResultMetadataQueue>(descriptor);
2528 if (!offlineResultQueue->isValid() || offlineResultQueue->availableToWrite() <= 0) {
2529 ALOGE("%s: offline session returns empty result metadata fmq, not use it", __func__);
2530 offlineResultQueue = nullptr;
2531 // Don't use the queue onwards.
2532 }
2533 ASSERT_TRUE(offlineResultQueueRet.isOk());
2534
2535 updateInflightResultQueue(offlineResultQueue);
2536
2537 ret = offlineSession->setCallback(cb);
2538 ASSERT_TRUE(ret.isOk());
2539
2540 for (size_t i = 0; i < kBurstFrameCount; i++) {
2541 std::unique_lock<std::mutex> l(mLock);
2542 while (!inflightReqs[i]->errorCodeValid && ((0 < inflightReqs[i]->numBuffersLeft) ||
2543 (!inflightReqs[i]->haveResultMetadata))) {
2544 auto timeout = std::chrono::system_clock::now() +
2545 std::chrono::seconds(kStreamBufferTimeoutSec);
2546 ASSERT_NE(std::cv_status::timeout, mResultCondition.wait_until(l, timeout));
2547 }
2548
2549 ASSERT_FALSE(inflightReqs[i]->errorCodeValid);
2550 ASSERT_NE(inflightReqs[i]->resultOutputBuffers.size(), 0u);
2551 ASSERT_EQ(stream.id, inflightReqs[i]->resultOutputBuffers[0].buffer.streamId);
2552 ASSERT_FALSE(inflightReqs[i]->collectedResult.isEmpty());
2553 }
2554
2555 ret = offlineSession->close();
2556 ASSERT_TRUE(ret.isOk());
2557 }
2558}
2559
2560// Check whether an invalid capture request with missing output buffers
2561// will be reported correctly.
2562TEST_P(CameraAidlTest, processCaptureRequestInvalidBuffer) {
2563 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
2564 std::vector<AvailableStream> outputBlobStreams;
2565 AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
2566 static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
2567 int32_t frameNumber = 1;
2568 CameraMetadata settings;
2569
2570 for (const auto& name : cameraDeviceNames) {
2571 Stream previewStream;
2572 std::vector<HalStream> halStreams;
2573 std::shared_ptr<DeviceCb> cb;
2574 bool supportsPartialResults = false;
2575 bool useHalBufManager = false;
2576 int32_t partialResultCount = 0;
2577 configurePreviewStream(name, mProvider, &previewThreshold, &mSession /*out*/,
2578 &previewStream /*out*/, &halStreams /*out*/,
2579 &supportsPartialResults /*out*/, &partialResultCount /*out*/,
2580 &useHalBufManager /*out*/, &cb /*out*/);
2581
2582 RequestTemplate reqTemplate = RequestTemplate::PREVIEW;
2583 ndk::ScopedAStatus ret = mSession->constructDefaultRequestSettings(reqTemplate, &settings);
2584 ASSERT_TRUE(ret.isOk());
2585 overrideRotateAndCrop(&settings);
2586
2587 std::vector<CaptureRequest> requests(1);
2588 CaptureRequest& request = requests[0];
2589 std::vector<StreamBuffer>& outputBuffers = request.outputBuffers;
2590 outputBuffers.resize(1);
2591 // Empty output buffer
2592 outputBuffers[0] = {
2593 -1, 0, NativeHandle(), BufferStatus::ERROR, NativeHandle(), NativeHandle()};
2594
2595 request.inputBuffer = {
2596 -1, 0, NativeHandle(), BufferStatus::ERROR, NativeHandle(), NativeHandle()};
2597 request.frameNumber = frameNumber;
2598 request.fmqSettingsSize = 0;
2599 request.settings = settings;
2600
2601 // Output buffers are missing, we should fail here
2602 int32_t numRequestProcessed = 0;
2603 std::vector<BufferCache> cachesToRemove;
2604 ret = mSession->processCaptureRequest(requests, cachesToRemove, &numRequestProcessed);
2605 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT), ret.getServiceSpecificError());
2606 ASSERT_EQ(numRequestProcessed, 0u);
2607
2608 ret = mSession->close();
2609 mSession = nullptr;
2610 ASSERT_TRUE(ret.isOk());
2611 }
2612}
2613
2614// Generate, trigger and flush a preview request
2615TEST_P(CameraAidlTest, flushPreviewRequest) {
2616 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
2617 std::vector<AvailableStream> outputPreviewStreams;
2618 AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
2619 static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
2620 int64_t bufferId = 1;
2621 int32_t frameNumber = 1;
2622 CameraMetadata settings;
2623
2624 for (const auto& name : cameraDeviceNames) {
2625 Stream previewStream;
2626 std::vector<HalStream> halStreams;
2627 std::shared_ptr<DeviceCb> cb;
2628 bool supportsPartialResults = false;
2629 bool useHalBufManager = false;
2630 int32_t partialResultCount = 0;
2631
2632 configurePreviewStream(name, mProvider, &previewThreshold, &mSession /*out*/,
2633 &previewStream /*out*/, &halStreams /*out*/,
2634 &supportsPartialResults /*out*/, &partialResultCount /*out*/,
2635 &useHalBufManager /*out*/, &cb /*out*/);
2636
2637 ASSERT_NE(mSession, nullptr);
2638 ASSERT_NE(cb, nullptr);
2639 ASSERT_FALSE(halStreams.empty());
2640
2641 ::aidl::android::hardware::common::fmq::MQDescriptor<
2642 int8_t, aidl::android::hardware::common::fmq::SynchronizedReadWrite>
2643 descriptor;
2644
2645 auto resultQueueRet = mSession->getCaptureResultMetadataQueue(&descriptor);
2646 std::shared_ptr<ResultMetadataQueue> resultQueue =
2647 std::make_shared<ResultMetadataQueue>(descriptor);
2648 ASSERT_TRUE(resultQueueRet.isOk());
2649 if (!resultQueue->isValid() || resultQueue->availableToWrite() <= 0) {
2650 ALOGE("%s: HAL returns empty result metadata fmq, not use it", __func__);
2651 resultQueue = nullptr;
2652 // Don't use the queue onwards.
2653 }
2654
2655 std::shared_ptr<InFlightRequest> inflightReq = std::make_shared<InFlightRequest>(
2656 1, false, supportsPartialResults, partialResultCount, resultQueue);
2657 RequestTemplate reqTemplate = RequestTemplate::PREVIEW;
2658
2659 ndk::ScopedAStatus ret = mSession->constructDefaultRequestSettings(reqTemplate, &settings);
2660 ASSERT_TRUE(ret.isOk());
2661 overrideRotateAndCrop(&settings);
2662
2663 buffer_handle_t buffer_handle;
2664 std::vector<CaptureRequest> requests(1);
2665 CaptureRequest& request = requests[0];
2666 std::vector<StreamBuffer>& outputBuffers = request.outputBuffers;
2667 outputBuffers.resize(1);
2668 StreamBuffer& outputBuffer = outputBuffers[0];
2669 if (useHalBufManager) {
2670 bufferId = 0;
2671 outputBuffer = {halStreams[0].id, bufferId, NativeHandle(),
2672 BufferStatus::OK, NativeHandle(), NativeHandle()};
2673 } else {
2674 allocateGraphicBuffer(previewStream.width, previewStream.height,
2675 android_convertGralloc1To0Usage(
2676 static_cast<uint64_t>(halStreams[0].producerUsage),
2677 static_cast<uint64_t>(halStreams[0].consumerUsage)),
2678 halStreams[0].overrideFormat, &buffer_handle);
2679 outputBuffer = {halStreams[0].id, bufferId, ::android::makeToAidl(buffer_handle),
2680 BufferStatus::OK, NativeHandle(), NativeHandle()};
2681 }
2682
2683 request.frameNumber = frameNumber;
2684 request.fmqSettingsSize = 0;
2685 request.settings = settings;
2686 request.inputBuffer = {
2687 -1, 0, NativeHandle(), BufferStatus::ERROR, NativeHandle(), NativeHandle()};
2688
2689 {
2690 std::unique_lock<std::mutex> l(mLock);
2691 mInflightMap.clear();
2692 mInflightMap[frameNumber] = inflightReq;
2693 }
2694
2695 int32_t numRequestProcessed = 0;
2696 std::vector<BufferCache> cachesToRemove;
2697 ret = mSession->processCaptureRequest(requests, cachesToRemove, &numRequestProcessed);
2698 ASSERT_TRUE(ret.isOk());
2699 ASSERT_EQ(numRequestProcessed, 1u);
2700
2701 // Flush before waiting for request to complete.
2702 ndk::ScopedAStatus returnStatus = mSession->flush();
2703 ASSERT_TRUE(returnStatus.isOk());
2704
2705 {
2706 std::unique_lock<std::mutex> l(mLock);
2707 while (!inflightReq->errorCodeValid &&
2708 ((0 < inflightReq->numBuffersLeft) || (!inflightReq->haveResultMetadata))) {
2709 auto timeout = std::chrono::system_clock::now() +
2710 std::chrono::seconds(kStreamBufferTimeoutSec);
2711 ASSERT_NE(std::cv_status::timeout, mResultCondition.wait_until(l, timeout));
2712 }
2713
2714 if (!inflightReq->errorCodeValid) {
2715 ASSERT_NE(inflightReq->resultOutputBuffers.size(), 0u);
2716 ASSERT_EQ(previewStream.id, inflightReq->resultOutputBuffers[0].buffer.streamId);
2717 } else {
2718 switch (inflightReq->errorCode) {
2719 case ErrorCode::ERROR_REQUEST:
2720 case ErrorCode::ERROR_RESULT:
2721 case ErrorCode::ERROR_BUFFER:
2722 // Expected
2723 break;
2724 case ErrorCode::ERROR_DEVICE:
2725 default:
2726 FAIL() << "Unexpected error:"
2727 << static_cast<uint32_t>(inflightReq->errorCode);
2728 }
2729 }
2730 }
2731
2732 if (useHalBufManager) {
2733 verifyBuffersReturned(mSession, previewStream.id, cb);
2734 }
2735
2736 ret = mSession->close();
2737 mSession = nullptr;
2738 ASSERT_TRUE(ret.isOk());
2739 }
2740}
2741
2742// Verify that camera flushes correctly without any pending requests.
2743TEST_P(CameraAidlTest, flushEmpty) {
2744 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
2745 std::vector<AvailableStream> outputPreviewStreams;
2746 AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
2747 static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
2748
2749 for (const auto& name : cameraDeviceNames) {
2750 Stream previewStream;
2751 std::vector<HalStream> halStreams;
2752 std::shared_ptr<DeviceCb> cb;
2753 bool supportsPartialResults = false;
2754 bool useHalBufManager = false;
2755
2756 int32_t partialResultCount = 0;
2757 configurePreviewStream(name, mProvider, &previewThreshold, &mSession /*out*/,
2758 &previewStream /*out*/, &halStreams /*out*/,
2759 &supportsPartialResults /*out*/, &partialResultCount /*out*/,
2760 &useHalBufManager /*out*/, &cb /*out*/);
2761
2762 ndk::ScopedAStatus returnStatus = mSession->flush();
2763 ASSERT_TRUE(returnStatus.isOk());
2764
2765 {
2766 std::unique_lock<std::mutex> l(mLock);
2767 auto timeout = std::chrono::system_clock::now() +
2768 std::chrono::milliseconds(kEmptyFlushTimeoutMSec);
2769 ASSERT_EQ(std::cv_status::timeout, mResultCondition.wait_until(l, timeout));
2770 }
2771
2772 ndk::ScopedAStatus ret = mSession->close();
2773 mSession = nullptr;
2774 ASSERT_TRUE(ret.isOk());
2775 }
2776}
2777
2778// Test camera provider notify method
2779TEST_P(CameraAidlTest, providerDeviceStateNotification) {
2780 notifyDeviceState(ICameraProvider::DEVICE_STATE_BACK_COVERED);
2781 notifyDeviceState(ICameraProvider::DEVICE_STATE_NORMAL);
2782}
2783
2784// Verify that all supported stream formats and sizes can be configured
2785// successfully for injection camera.
2786TEST_P(CameraAidlTest, configureInjectionStreamsAvailableOutputs) {
2787 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
2788 std::vector<AvailableStream> outputStreams;
2789
2790 for (const auto& name : cameraDeviceNames) {
2791 CameraMetadata metadata;
2792
2793 std::shared_ptr<ICameraInjectionSession> injectionSession;
2794 std::shared_ptr<ICameraDevice> unusedDevice;
2795 openEmptyInjectionSession(name, mProvider, &injectionSession /*out*/, &metadata /*out*/,
2796 &unusedDevice /*out*/);
2797 if (injectionSession == nullptr) {
2798 continue;
2799 }
2800
2801 camera_metadata_t* staticMetaBuffer =
2802 reinterpret_cast<camera_metadata_t*>(metadata.metadata.data());
2803 CameraMetadata chars;
2804 chars.metadata = metadata.metadata;
2805
2806 outputStreams.clear();
2807 ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMetaBuffer, outputStreams));
2808 ASSERT_NE(0u, outputStreams.size());
2809
2810 int32_t jpegBufferSize = 0;
2811 ASSERT_EQ(Status::OK, getJpegBufferSize(staticMetaBuffer, &jpegBufferSize));
2812 ASSERT_NE(0u, jpegBufferSize);
2813
2814 int32_t streamId = 0;
2815 int32_t streamConfigCounter = 0;
2816 for (auto& it : outputStreams) {
2817 Dataspace dataspace = getDataspace(static_cast<PixelFormat>(it.format));
2818 Stream stream = {streamId,
2819 StreamType::OUTPUT,
2820 it.width,
2821 it.height,
2822 static_cast<PixelFormat>(it.format),
2823 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
2824 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
2825 dataspace,
2826 StreamRotation::ROTATION_0,
2827 std::string(),
2828 jpegBufferSize,
2829 0,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00002830 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
2831 RequestAvailableDynamicRangeProfilesMap::
2832 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08002833
2834 std::vector<Stream> streams = {stream};
2835 StreamConfiguration config;
2836 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
2837 jpegBufferSize);
2838
2839 config.streamConfigCounter = streamConfigCounter++;
2840 ndk::ScopedAStatus s = injectionSession->configureInjectionStreams(config, chars);
2841 ASSERT_TRUE(s.isOk());
2842 streamId++;
2843 }
2844
2845 std::shared_ptr<ICameraDeviceSession> session;
2846 ndk::ScopedAStatus ret = injectionSession->getCameraDeviceSession(&session);
2847 ASSERT_TRUE(ret.isOk());
2848 ASSERT_NE(session, nullptr);
2849 ret = session->close();
2850 ASSERT_TRUE(ret.isOk());
2851 }
2852}
2853
2854// Check for correct handling of invalid/incorrect configuration parameters for injection camera.
2855TEST_P(CameraAidlTest, configureInjectionStreamsInvalidOutputs) {
2856 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
2857 std::vector<AvailableStream> outputStreams;
2858
2859 for (const auto& name : cameraDeviceNames) {
2860 CameraMetadata metadata;
2861 std::shared_ptr<ICameraInjectionSession> injectionSession;
2862 std::shared_ptr<ICameraDevice> unusedDevice;
2863 openEmptyInjectionSession(name, mProvider, &injectionSession /*out*/, &metadata /*out*/,
2864 &unusedDevice);
2865 if (injectionSession == nullptr) {
2866 continue;
2867 }
2868
2869 camera_metadata_t* staticMetaBuffer =
2870 reinterpret_cast<camera_metadata_t*>(metadata.metadata.data());
2871 std::shared_ptr<ICameraDeviceSession> session;
2872 ndk::ScopedAStatus ret = injectionSession->getCameraDeviceSession(&session);
2873 ASSERT_TRUE(ret.isOk());
2874 ASSERT_NE(session, nullptr);
2875
2876 CameraMetadata chars;
2877 chars.metadata = metadata.metadata;
2878
2879 outputStreams.clear();
2880 ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMetaBuffer, outputStreams));
2881 ASSERT_NE(0u, outputStreams.size());
2882
2883 int32_t jpegBufferSize = 0;
2884 ASSERT_EQ(Status::OK, getJpegBufferSize(staticMetaBuffer, &jpegBufferSize));
2885 ASSERT_NE(0u, jpegBufferSize);
2886
2887 int32_t streamId = 0;
2888 Stream stream = {streamId++,
2889 StreamType::OUTPUT,
2890 0,
2891 0,
2892 static_cast<PixelFormat>(outputStreams[0].format),
2893 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
2894 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
2895 Dataspace::UNKNOWN,
2896 StreamRotation::ROTATION_0,
2897 std::string(),
2898 jpegBufferSize,
2899 0,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00002900 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
2901 RequestAvailableDynamicRangeProfilesMap::
2902 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08002903
2904 int32_t streamConfigCounter = 0;
2905 std::vector<Stream> streams = {stream};
2906 StreamConfiguration config;
2907 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
2908 jpegBufferSize);
2909
2910 config.streamConfigCounter = streamConfigCounter++;
2911 ndk::ScopedAStatus s = injectionSession->configureInjectionStreams(config, chars);
2912 ASSERT_TRUE(
2913 (static_cast<int32_t>(Status::ILLEGAL_ARGUMENT) == s.getServiceSpecificError()) ||
2914 (static_cast<int32_t>(Status::INTERNAL_ERROR) == s.getServiceSpecificError()));
2915
2916 stream = {streamId++,
2917 StreamType::OUTPUT,
2918 INT32_MAX,
2919 INT32_MAX,
2920 static_cast<PixelFormat>(outputStreams[0].format),
2921 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
2922 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
2923 Dataspace::UNKNOWN,
2924 StreamRotation::ROTATION_0,
2925 std::string(),
2926 jpegBufferSize,
2927 0,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00002928 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
2929 RequestAvailableDynamicRangeProfilesMap::
2930 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
2931
Avichal Rakesh362242f2022-02-08 12:40:53 -08002932 streams[0] = stream;
2933 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
2934 jpegBufferSize);
2935 config.streamConfigCounter = streamConfigCounter++;
2936 s = injectionSession->configureInjectionStreams(config, chars);
2937 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT), s.getServiceSpecificError());
2938
2939 for (auto& it : outputStreams) {
2940 stream = {streamId++,
2941 StreamType::OUTPUT,
2942 it.width,
2943 it.height,
2944 static_cast<PixelFormat>(INT32_MAX),
2945 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
2946 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
2947 Dataspace::UNKNOWN,
2948 StreamRotation::ROTATION_0,
2949 std::string(),
2950 jpegBufferSize,
2951 0,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00002952 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
2953 RequestAvailableDynamicRangeProfilesMap::
2954 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08002955 streams[0] = stream;
2956 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
2957 jpegBufferSize);
2958 config.streamConfigCounter = streamConfigCounter++;
2959 s = injectionSession->configureInjectionStreams(config, chars);
2960 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT), s.getServiceSpecificError());
2961
2962 stream = {streamId++,
2963 StreamType::OUTPUT,
2964 it.width,
2965 it.height,
2966 static_cast<PixelFormat>(it.format),
2967 static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
2968 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
2969 Dataspace::UNKNOWN,
2970 static_cast<StreamRotation>(INT32_MAX),
2971 std::string(),
2972 jpegBufferSize,
2973 0,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00002974 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
2975 RequestAvailableDynamicRangeProfilesMap::
2976 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08002977 streams[0] = stream;
2978 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config,
2979 jpegBufferSize);
2980 config.streamConfigCounter = streamConfigCounter++;
2981 s = injectionSession->configureInjectionStreams(config, chars);
2982 ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT), s.getServiceSpecificError());
2983 }
2984
2985 ret = session->close();
2986 ASSERT_TRUE(ret.isOk());
2987 }
2988}
2989
2990// Check whether session parameters are supported for injection camera. If Hal support for them
2991// exist, then try to configure a preview stream using them.
2992TEST_P(CameraAidlTest, configureInjectionStreamsWithSessionParameters) {
2993 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
2994 std::vector<AvailableStream> outputPreviewStreams;
2995 AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
2996 static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
2997
2998 for (const auto& name : cameraDeviceNames) {
2999 CameraMetadata metadata;
3000 std::shared_ptr<ICameraInjectionSession> injectionSession;
3001 std::shared_ptr<ICameraDevice> unusedDevice;
3002 openEmptyInjectionSession(name, mProvider, &injectionSession /*out*/, &metadata /*out*/,
3003 &unusedDevice /*out*/);
3004 if (injectionSession == nullptr) {
3005 continue;
3006 }
3007
3008 std::shared_ptr<ICameraDeviceSession> session;
3009 ndk::ScopedAStatus ret = injectionSession->getCameraDeviceSession(&session);
3010 ASSERT_TRUE(ret.isOk());
3011 ASSERT_NE(session, nullptr);
3012
3013 camera_metadata_t* staticMetaBuffer =
3014 reinterpret_cast<camera_metadata_t*>(metadata.metadata.data());
3015 CameraMetadata chars;
3016 chars.metadata = metadata.metadata;
3017
3018 std::unordered_set<int32_t> availableSessionKeys;
3019 Status rc = getSupportedKeys(staticMetaBuffer, ANDROID_REQUEST_AVAILABLE_SESSION_KEYS,
3020 &availableSessionKeys);
3021 ASSERT_EQ(Status::OK, rc);
3022 if (availableSessionKeys.empty()) {
3023 ret = session->close();
3024 ASSERT_TRUE(ret.isOk());
3025 continue;
3026 }
3027
3028 android::hardware::camera::common::V1_0::helper::CameraMetadata previewRequestSettings;
3029 android::hardware::camera::common::V1_0::helper::CameraMetadata sessionParams,
3030 modifiedSessionParams;
3031 constructFilteredSettings(session, availableSessionKeys, RequestTemplate::PREVIEW,
3032 &previewRequestSettings, &sessionParams);
3033 if (sessionParams.isEmpty()) {
3034 ret = session->close();
3035 ASSERT_TRUE(ret.isOk());
3036 continue;
3037 }
3038
3039 outputPreviewStreams.clear();
3040
3041 ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMetaBuffer, outputPreviewStreams,
3042 &previewThreshold));
3043 ASSERT_NE(0u, outputPreviewStreams.size());
3044
3045 Stream previewStream = {
3046 0,
3047 StreamType::OUTPUT,
3048 outputPreviewStreams[0].width,
3049 outputPreviewStreams[0].height,
3050 static_cast<PixelFormat>(outputPreviewStreams[0].format),
3051 static_cast<::aidl::android::hardware::graphics::common::BufferUsage>(
3052 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
3053 Dataspace::UNKNOWN,
3054 StreamRotation::ROTATION_0,
3055 std::string(),
3056 0,
3057 -1,
Avichal Rakeshd3503a32022-02-25 06:23:14 +00003058 {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
3059 RequestAvailableDynamicRangeProfilesMap::
3060 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
Avichal Rakesh362242f2022-02-08 12:40:53 -08003061 std::vector<Stream> streams = {previewStream};
3062 StreamConfiguration config;
3063 config.streams = streams;
3064 config.operationMode = StreamConfigurationMode::NORMAL_MODE;
3065
3066 modifiedSessionParams = sessionParams;
3067 camera_metadata_t* sessionParamsBuffer = sessionParams.release();
3068 uint8_t* rawSessionParamsBuffer = reinterpret_cast<uint8_t*>(sessionParamsBuffer);
3069 config.sessionParams.metadata =
3070 std::vector(rawSessionParamsBuffer,
3071 rawSessionParamsBuffer + get_camera_metadata_size(sessionParamsBuffer));
3072
3073 config.streamConfigCounter = 0;
3074 config.streamConfigCounter = 0;
3075 config.multiResolutionInputImage = false;
3076
3077 ndk::ScopedAStatus s = injectionSession->configureInjectionStreams(config, chars);
3078 ASSERT_TRUE(s.isOk());
3079
3080 sessionParams.acquire(sessionParamsBuffer);
3081 free_camera_metadata(staticMetaBuffer);
3082 ret = session->close();
3083 ASSERT_TRUE(ret.isOk());
3084 }
3085}
3086
Jayant Chowdharyde1909e2022-11-23 17:18:38 +00003087TEST_P(CameraAidlTest, configureStreamsUseCasesCroppedRaw) {
3088 AvailableStream rawStreamThreshold =
3089 {INT_MAX, INT_MAX, static_cast<int32_t>(PixelFormat::RAW16)};
3090 configureStreamUseCaseInternal(rawStreamThreshold);
3091}
3092
Avichal Rakesh362242f2022-02-08 12:40:53 -08003093// Verify that valid stream use cases can be configured successfully, and invalid use cases
3094// fail stream configuration.
3095TEST_P(CameraAidlTest, configureStreamsUseCases) {
Jayant Chowdharyde1909e2022-11-23 17:18:38 +00003096 AvailableStream previewStreamThreshold =
3097 {kMaxPreviewWidth, kMaxPreviewHeight, static_cast<int32_t>(PixelFormat::YCBCR_420_888)};
3098 configureStreamUseCaseInternal(previewStreamThreshold);
Avichal Rakesh362242f2022-02-08 12:40:53 -08003099}
3100
Austin Borger0918fc82023-03-21 18:48:18 -07003101// Validate the integrity of stream configuration metadata
3102TEST_P(CameraAidlTest, validateStreamConfigurations) {
3103 std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
3104 std::vector<AvailableStream> outputStreams;
3105
3106 const int32_t scalerSizesTag = ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS;
3107 const int32_t scalerMinFrameDurationsTag = ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS;
3108 const int32_t scalerStallDurationsTag = ANDROID_SCALER_AVAILABLE_STALL_DURATIONS;
3109
3110 for (const auto& name : cameraDeviceNames) {
3111 CameraMetadata meta;
3112 std::shared_ptr<ICameraDevice> cameraDevice;
3113
3114 openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/,
3115 &cameraDevice /*out*/);
3116 camera_metadata_t* staticMeta = reinterpret_cast<camera_metadata_t*>(meta.metadata.data());
3117
3118 if (is10BitDynamicRangeCapable(staticMeta)) {
3119 std::vector<std::tuple<size_t, size_t>> supportedP010Sizes, supportedBlobSizes;
3120
3121 getSupportedSizes(staticMeta, scalerSizesTag, HAL_PIXEL_FORMAT_BLOB,
3122 &supportedBlobSizes);
3123 getSupportedSizes(staticMeta, scalerSizesTag, HAL_PIXEL_FORMAT_YCBCR_P010,
3124 &supportedP010Sizes);
3125 ASSERT_FALSE(supportedP010Sizes.empty());
3126
3127 std::vector<int64_t> blobMinDurations, blobStallDurations;
3128 getSupportedDurations(staticMeta, scalerMinFrameDurationsTag, HAL_PIXEL_FORMAT_BLOB,
3129 supportedP010Sizes, &blobMinDurations);
3130 getSupportedDurations(staticMeta, scalerStallDurationsTag, HAL_PIXEL_FORMAT_BLOB,
3131 supportedP010Sizes, &blobStallDurations);
3132 ASSERT_FALSE(blobStallDurations.empty());
3133 ASSERT_FALSE(blobMinDurations.empty());
3134 ASSERT_EQ(supportedP010Sizes.size(), blobMinDurations.size());
3135 ASSERT_EQ(blobMinDurations.size(), blobStallDurations.size());
3136 }
3137
Austin Borger8e9ac022023-05-04 11:17:26 -07003138 // TODO (b/280887191): Validate other aspects of stream configuration metadata...
3139
3140 ndk::ScopedAStatus ret = mSession->close();
3141 mSession = nullptr;
3142 ASSERT_TRUE(ret.isOk());
Austin Borger0918fc82023-03-21 18:48:18 -07003143 }
3144}
3145
Avichal Rakesh362242f2022-02-08 12:40:53 -08003146GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(CameraAidlTest);
3147INSTANTIATE_TEST_SUITE_P(
3148 PerInstance, CameraAidlTest,
3149 testing::ValuesIn(android::getAidlHalInstanceNames(ICameraProvider::descriptor)),
Jayant Chowdharyde1909e2022-11-23 17:18:38 +00003150 android::hardware::PrintInstanceNameToString);