ICameraService: Add methods to query concurrent streaming camera support.
- getConcurrentStreamingCameraIds() :
returns a list of combinations of camera ids that may stream
concurrently.
- isConcurrentSessionConfigurationSupported() :
queries whether camera devices can support the
corresponding given session configurations concurrently.
Bug: 77960042
Test: GCA (sanity)
Test: CTS
Change-Id: Iba237118ccf145695a500a2c406713e416e66011
Signed-off-by: Jayant Chowdhary <jchowdhary@google.com>
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 8ed3ab6..ff9d274 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -492,7 +492,7 @@
return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
}
- res = checkOperatingModeLocked(operatingMode);
+ res = checkOperatingMode(operatingMode, mDevice->info(), mCameraIdStr);
if (!res.isOk()) {
return res;
}
@@ -550,8 +550,8 @@
return res;
}
-binder::Status CameraDeviceClient::checkSurfaceTypeLocked(size_t numBufferProducers,
- bool deferredConsumer, int surfaceType) const {
+binder::Status CameraDeviceClient::checkSurfaceType(size_t numBufferProducers,
+ bool deferredConsumer, int surfaceType) {
if (numBufferProducers > MAX_SURFACES_PER_STREAM) {
ALOGE("%s: GraphicBufferProducer count %zu for stream exceeds limit of %d",
__FUNCTION__, numBufferProducers, MAX_SURFACES_PER_STREAM);
@@ -572,28 +572,27 @@
return binder::Status::ok();
}
-binder::Status CameraDeviceClient::checkPhysicalCameraIdLocked(String8 physicalCameraId) {
- if (physicalCameraId.size() > 0) {
- std::vector<std::string> physicalCameraIds;
- bool logicalCamera =
- mProviderManager->isLogicalCamera(mCameraIdStr.string(), &physicalCameraIds);
- if (!logicalCamera ||
- std::find(physicalCameraIds.begin(), physicalCameraIds.end(),
- physicalCameraId.string()) == physicalCameraIds.end()) {
- String8 msg = String8::format("Camera %s: Camera doesn't support physicalCameraId %s.",
- mCameraIdStr.string(), physicalCameraId.string());
- ALOGE("%s: %s", __FUNCTION__, msg.string());
- return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
- }
+binder::Status CameraDeviceClient::checkPhysicalCameraId(
+ const std::vector<std::string> &physicalCameraIds, const String8 &physicalCameraId,
+ const String8 &logicalCameraId) {
+ if (physicalCameraId.size() == 0) {
+ return binder::Status::ok();
}
-
+ if (std::find(physicalCameraIds.begin(), physicalCameraIds.end(),
+ physicalCameraId.string()) == physicalCameraIds.end()) {
+ String8 msg = String8::format("Camera %s: Camera doesn't support physicalCameraId %s.",
+ logicalCameraId.string(), physicalCameraId.string());
+ ALOGE("%s: %s", __FUNCTION__, msg.string());
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+ }
return binder::Status::ok();
}
-binder::Status CameraDeviceClient::checkOperatingModeLocked(int operatingMode) const {
+binder::Status CameraDeviceClient::checkOperatingMode(int operatingMode,
+ const CameraMetadata &staticInfo, const String8 &cameraId) {
if (operatingMode < 0) {
String8 msg = String8::format(
- "Camera %s: Invalid operating mode %d requested", mCameraIdStr.string(), operatingMode);
+ "Camera %s: Invalid operating mode %d requested", cameraId.string(), operatingMode);
ALOGE("%s: %s", __FUNCTION__, msg.string());
return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
msg.string());
@@ -601,8 +600,7 @@
bool isConstrainedHighSpeed = (operatingMode == ICameraDeviceUser::CONSTRAINED_HIGH_SPEED_MODE);
if (isConstrainedHighSpeed) {
- CameraMetadata staticInfo = mDevice->info();
- camera_metadata_entry_t entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
+ camera_metadata_ro_entry_t entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
bool isConstrainedHighSpeedSupported = false;
for(size_t i = 0; i < entry.count; ++i) {
uint8_t capability = entry.data.u8[i];
@@ -614,7 +612,7 @@
if (!isConstrainedHighSpeedSupported) {
String8 msg = String8::format(
"Camera %s: Try to create a constrained high speed configuration on a device"
- " that doesn't support it.", mCameraIdStr.string());
+ " that doesn't support it.", cameraId.string());
ALOGE("%s: %s", __FUNCTION__, msg.string());
return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
msg.string());
@@ -645,39 +643,31 @@
stream->bufferSize = 0;
}
-binder::Status CameraDeviceClient::isSessionConfigurationSupported(
- const SessionConfiguration& sessionConfiguration, bool *status /*out*/) {
- ATRACE_CALL();
-
- binder::Status res;
- if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
-
- Mutex::Autolock icl(mBinderSerializationLock);
-
- if (!mDevice.get()) {
- return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
- }
-
+binder::Status
+CameraDeviceClient::convertToHALStreamCombination(const SessionConfiguration& sessionConfiguration,
+ const String8 &logicalCameraId, const CameraMetadata &deviceInfo,
+ metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
+ hardware::camera::device::V3_4::StreamConfiguration &streamConfiguration,
+ bool *unsupported) {
auto operatingMode = sessionConfiguration.getOperatingMode();
- res = checkOperatingModeLocked(operatingMode);
+ binder::Status res = checkOperatingMode(operatingMode, deviceInfo, logicalCameraId);
if (!res.isOk()) {
return res;
}
- if (status == nullptr) {
- String8 msg = String8::format( "Camera %s: Invalid status!", mCameraIdStr.string());
+ if (unsupported == nullptr) {
+ String8 msg("unsupported nullptr");
ALOGE("%s: %s", __FUNCTION__, msg.string());
return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
}
-
- hardware::camera::device::V3_4::StreamConfiguration streamConfiguration;
+ *unsupported = false;
auto ret = Camera3Device::mapToStreamConfigurationMode(
static_cast<camera3_stream_configuration_mode_t> (operatingMode),
/*out*/ &streamConfiguration.operationMode);
if (ret != OK) {
String8 msg = String8::format(
- "Camera %s: Failed mapping operating mode %d requested: %s (%d)", mCameraIdStr.string(),
- operatingMode, strerror(-ret), ret);
+ "Camera %s: Failed mapping operating mode %d requested: %s (%d)",
+ logicalCameraId.string(), operatingMode, strerror(-ret), ret);
ALOGE("%s: %s", __FUNCTION__, msg.string());
return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
msg.string());
@@ -711,12 +701,12 @@
bool isStreamInfoValid = false;
OutputStreamInfo streamInfo;
- res = checkSurfaceTypeLocked(numBufferProducers, deferredConsumer, it.getSurfaceType());
+ res = checkSurfaceType(numBufferProducers, deferredConsumer, it.getSurfaceType());
if (!res.isOk()) {
return res;
}
-
- res = checkPhysicalCameraIdLocked(physicalCameraId);
+ res = checkPhysicalCameraId(physicalCameraIds, physicalCameraId,
+ logicalCameraId);
if (!res.isOk()) {
return res;
}
@@ -742,8 +732,10 @@
for (auto& bufferProducer : bufferProducers) {
sp<Surface> surface;
+ const CameraMetadata &physicalDeviceInfo = getMetadata(physicalCameraId);
res = createSurfaceFromGbp(streamInfo, isStreamInfoValid, surface, bufferProducer,
- physicalCameraId);
+ logicalCameraId,
+ physicalCameraId.size() > 0 ? physicalDeviceInfo : deviceInfo );
if (!res.isOk())
return res;
@@ -759,15 +751,15 @@
std::vector<OutputStreamInfo> compositeStreams;
if (isDepthCompositeStream) {
ret = camera3::DepthCompositeStream::getCompositeStreamInfo(streamInfo,
- mDevice->info(), &compositeStreams);
+ deviceInfo, &compositeStreams);
} else {
ret = camera3::HeicCompositeStream::getCompositeStreamInfo(streamInfo,
- mDevice->info(), &compositeStreams);
+ deviceInfo, &compositeStreams);
}
if (ret != OK) {
String8 msg = String8::format(
"Camera %s: Failed adding composite streams: %s (%d)",
- mCameraIdStr.string(), strerror(-ret), ret);
+ logicalCameraId.string(), strerror(-ret), ret);
ALOGE("%s: %s", __FUNCTION__, msg.string());
return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
}
@@ -775,7 +767,7 @@
if (compositeStreams.size() == 0) {
// No internal streams means composite stream not
// supported.
- *status = false;
+ *unsupported = true;
return binder::Status::ok();
} else if (compositeStreams.size() > 1) {
streamCount += compositeStreams.size() - 1;
@@ -796,6 +788,49 @@
}
}
}
+ return binder::Status::ok();
+}
+
+binder::Status CameraDeviceClient::isSessionConfigurationSupported(
+ const SessionConfiguration& sessionConfiguration, bool *status /*out*/) {
+ ATRACE_CALL();
+
+ binder::Status res;
+ status_t ret = OK;
+ if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
+
+ Mutex::Autolock icl(mBinderSerializationLock);
+
+ if (!mDevice.get()) {
+ return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
+ }
+
+ auto operatingMode = sessionConfiguration.getOperatingMode();
+ res = checkOperatingMode(operatingMode, mDevice->info(), mCameraIdStr);
+ if (!res.isOk()) {
+ return res;
+ }
+
+ if (status == nullptr) {
+ String8 msg = String8::format( "Camera %s: Invalid status!", mCameraIdStr.string());
+ ALOGE("%s: %s", __FUNCTION__, msg.string());
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+ }
+ hardware::camera::device::V3_4::StreamConfiguration streamConfiguration;
+ bool earlyExit = false;
+ metadataGetter getMetadata = [this](const String8 &id) {return mDevice->info(id);};
+ std::vector<std::string> physicalCameraIds;
+ mProviderManager->isLogicalCamera(mCameraIdStr.string(), &physicalCameraIds);
+ res = convertToHALStreamCombination(sessionConfiguration, mCameraIdStr,
+ mDevice->info(), getMetadata, physicalCameraIds, streamConfiguration, &earlyExit);
+ if (!res.isOk()) {
+ return res;
+ }
+
+ if (earlyExit) {
+ *status = false;
+ return binder::Status::ok();
+ }
*status = false;
ret = mProviderManager->isSessionConfigurationSupported(mCameraIdStr.string(),
@@ -935,7 +970,7 @@
String8 physicalCameraId = String8(outputConfiguration.getPhysicalCameraId());
bool deferredConsumerOnly = deferredConsumer && numBufferProducers == 0;
- res = checkSurfaceTypeLocked(numBufferProducers, deferredConsumer,
+ res = checkSurfaceType(numBufferProducers, deferredConsumer,
outputConfiguration.getSurfaceType());
if (!res.isOk()) {
return res;
@@ -944,8 +979,9 @@
if (!mDevice.get()) {
return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
}
-
- res = checkPhysicalCameraIdLocked(physicalCameraId);
+ std::vector<std::string> physicalCameraIds;
+ mProviderManager->isLogicalCamera(mCameraIdStr.string(), &physicalCameraIds);
+ res = checkPhysicalCameraId(physicalCameraIds, physicalCameraId, mCameraIdStr);
if (!res.isOk()) {
return res;
}
@@ -974,7 +1010,7 @@
sp<Surface> surface;
res = createSurfaceFromGbp(streamInfo, isStreamInfoValid, surface, bufferProducer,
- physicalCameraId);
+ mCameraIdStr, mDevice->info(physicalCameraId));
if (!res.isOk())
return res;
@@ -1278,7 +1314,7 @@
OutputStreamInfo outInfo;
sp<Surface> surface;
res = createSurfaceFromGbp(outInfo, /*isStreamInfoValid*/ false, surface,
- newOutputsMap.valueAt(i), physicalCameraId);
+ newOutputsMap.valueAt(i), mCameraIdStr, mDevice->info(physicalCameraId));
if (!res.isOk())
return res;
@@ -1358,11 +1394,11 @@
binder::Status CameraDeviceClient::createSurfaceFromGbp(
OutputStreamInfo& streamInfo, bool isStreamInfoValid,
sp<Surface>& surface, const sp<IGraphicBufferProducer>& gbp,
- const String8& physicalId) {
+ const String8 &cameraId, const CameraMetadata &physicalCameraMetadata) {
// bufferProducer must be non-null
if (gbp == nullptr) {
- String8 msg = String8::format("Camera %s: Surface is NULL", mCameraIdStr.string());
+ String8 msg = String8::format("Camera %s: Surface is NULL", cameraId.string());
ALOGW("%s: %s", __FUNCTION__, msg.string());
return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
}
@@ -1374,13 +1410,13 @@
status_t err;
if ((err = gbp->getConsumerUsage(&consumerUsage)) != OK) {
String8 msg = String8::format("Camera %s: Failed to query Surface consumer usage: %s (%d)",
- mCameraIdStr.string(), strerror(-err), err);
+ cameraId.string(), strerror(-err), err);
ALOGE("%s: %s", __FUNCTION__, msg.string());
return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
}
if (consumerUsage & GraphicBuffer::USAGE_HW_TEXTURE) {
ALOGW("%s: Camera %s with consumer usage flag: %" PRIu64 ": Forcing asynchronous mode for stream",
- __FUNCTION__, mCameraIdStr.string(), consumerUsage);
+ __FUNCTION__, cameraId.string(), consumerUsage);
useAsync = true;
}
@@ -1399,26 +1435,26 @@
android_dataspace dataSpace;
if ((err = anw->query(anw, NATIVE_WINDOW_WIDTH, &width)) != OK) {
String8 msg = String8::format("Camera %s: Failed to query Surface width: %s (%d)",
- mCameraIdStr.string(), strerror(-err), err);
+ cameraId.string(), strerror(-err), err);
ALOGE("%s: %s", __FUNCTION__, msg.string());
return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
}
if ((err = anw->query(anw, NATIVE_WINDOW_HEIGHT, &height)) != OK) {
String8 msg = String8::format("Camera %s: Failed to query Surface height: %s (%d)",
- mCameraIdStr.string(), strerror(-err), err);
+ cameraId.string(), strerror(-err), err);
ALOGE("%s: %s", __FUNCTION__, msg.string());
return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
}
if ((err = anw->query(anw, NATIVE_WINDOW_FORMAT, &format)) != OK) {
String8 msg = String8::format("Camera %s: Failed to query Surface format: %s (%d)",
- mCameraIdStr.string(), strerror(-err), err);
+ cameraId.string(), strerror(-err), err);
ALOGE("%s: %s", __FUNCTION__, msg.string());
return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
}
if ((err = anw->query(anw, NATIVE_WINDOW_DEFAULT_DATASPACE,
reinterpret_cast<int*>(&dataSpace))) != OK) {
String8 msg = String8::format("Camera %s: Failed to query Surface dataspace: %s (%d)",
- mCameraIdStr.string(), strerror(-err), err);
+ cameraId.string(), strerror(-err), err);
ALOGE("%s: %s", __FUNCTION__, msg.string());
return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
}
@@ -1429,16 +1465,16 @@
((consumerUsage & GRALLOC_USAGE_HW_MASK) &&
((consumerUsage & GRALLOC_USAGE_SW_READ_MASK) == 0))) {
ALOGW("%s: Camera %s: Overriding format %#x to IMPLEMENTATION_DEFINED",
- __FUNCTION__, mCameraIdStr.string(), format);
+ __FUNCTION__, cameraId.string(), format);
format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
}
// Round dimensions to the nearest dimensions available for this format
if (flexibleConsumer && isPublicFormat(format) &&
!CameraDeviceClient::roundBufferDimensionNearest(width, height,
- format, dataSpace, mDevice->info(physicalId), /*out*/&width, /*out*/&height)) {
+ format, dataSpace, physicalCameraMetadata, /*out*/&width, /*out*/&height)) {
String8 msg = String8::format("Camera %s: No supported stream configurations with "
"format %#x defined, failed to create output stream",
- mCameraIdStr.string(), format);
+ cameraId.string(), format);
ALOGE("%s: %s", __FUNCTION__, msg.string());
return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
}
@@ -1453,26 +1489,26 @@
}
if (width != streamInfo.width) {
String8 msg = String8::format("Camera %s:Surface width doesn't match: %d vs %d",
- mCameraIdStr.string(), width, streamInfo.width);
+ cameraId.string(), width, streamInfo.width);
ALOGE("%s: %s", __FUNCTION__, msg.string());
return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
}
if (height != streamInfo.height) {
String8 msg = String8::format("Camera %s:Surface height doesn't match: %d vs %d",
- mCameraIdStr.string(), height, streamInfo.height);
+ cameraId.string(), height, streamInfo.height);
ALOGE("%s: %s", __FUNCTION__, msg.string());
return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
}
if (format != streamInfo.format) {
String8 msg = String8::format("Camera %s:Surface format doesn't match: %d vs %d",
- mCameraIdStr.string(), format, streamInfo.format);
+ cameraId.string(), format, streamInfo.format);
ALOGE("%s: %s", __FUNCTION__, msg.string());
return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
}
if (format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
if (dataSpace != streamInfo.dataSpace) {
String8 msg = String8::format("Camera %s:Surface dataSpace doesn't match: %d vs %d",
- mCameraIdStr.string(), dataSpace, streamInfo.dataSpace);
+ cameraId.string(), dataSpace, streamInfo.dataSpace);
ALOGE("%s: %s", __FUNCTION__, msg.string());
return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
}
@@ -1481,7 +1517,7 @@
if (consumerUsage != streamInfo.consumerUsage) {
String8 msg = String8::format(
"Camera %s:Surface usage flag doesn't match %" PRIu64 " vs %" PRIu64 "",
- mCameraIdStr.string(), consumerUsage, streamInfo.consumerUsage);
+ cameraId.string(), consumerUsage, streamInfo.consumerUsage);
ALOGE("%s: %s", __FUNCTION__, msg.string());
return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
}
@@ -1861,7 +1897,7 @@
sp<Surface> surface;
res = createSurfaceFromGbp(mStreamInfoMap[streamId], true /*isStreamInfoValid*/,
- surface, bufferProducer, physicalId);
+ surface, bufferProducer, mCameraIdStr, mDevice->info(physicalId));
if (!res.isOk())
return res;