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/Android.bp b/services/camera/libcameraservice/Android.bp
index da44e56..109ce7d 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -66,15 +66,16 @@
"device3/Camera3OutputStreamInterface.cpp",
"device3/Camera3OutputUtils.cpp",
"gui/RingBufferConsumer.cpp",
- "utils/CameraThreadState.cpp",
"hidl/AidlCameraDeviceCallbacks.cpp",
"hidl/AidlCameraServiceListener.cpp",
"hidl/Convert.cpp",
"hidl/HidlCameraDeviceUser.cpp",
"hidl/HidlCameraService.cpp",
+ "utils/CameraThreadState.cpp",
"utils/CameraTraces.cpp",
"utils/AutoConditionLock.cpp",
"utils/ExifUtils.cpp",
+ "utils/SessionConfigurationUtils.cpp",
"utils/TagMonitor.cpp",
"utils/LatencyHistogram.cpp",
],
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 01d6c8e..f1d5d16 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -62,6 +62,7 @@
#include <utils/String16.h>
#include <utils/SystemClock.h>
#include <utils/Trace.h>
+#include <utils/CallStack.h>
#include <private/android_filesystem_config.h>
#include <system/camera_vendor_tags.h>
#include <system/camera_metadata.h>
@@ -91,6 +92,8 @@
using hardware::ICameraServiceListener;
using hardware::camera::common::V1_0::CameraDeviceStatus;
using hardware::camera::common::V1_0::TorchModeStatus;
+using hardware::camera2::utils::CameraIdAndSessionConfiguration;
+using hardware::camera2::utils::ConcurrentCameraIdCombination;
// ----------------------------------------------------------------------------
// Logging support -- this is for debugging only
@@ -2040,6 +2043,83 @@
return Status::ok();
}
+ Status CameraService::getConcurrentStreamingCameraIds(
+ std::vector<ConcurrentCameraIdCombination>* concurrentCameraIds) {
+ ATRACE_CALL();
+ if (!concurrentCameraIds) {
+ ALOGE("%s: concurrentCameraIds is NULL", __FUNCTION__);
+ return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, "concurrentCameraIds is NULL");
+ }
+
+ if (!mInitialized) {
+ ALOGE("%s: Camera HAL couldn't be initialized", __FUNCTION__);
+ return STATUS_ERROR(ERROR_DISCONNECTED,
+ "Camera subsystem is not available");
+ }
+ // First call into the provider and get the set of concurrent camera
+ // combinations
+ std::vector<std::unordered_set<std::string>> concurrentCameraCombinations =
+ mCameraProviderManager->getConcurrentStreamingCameraIds();
+ for (auto &combination : concurrentCameraCombinations) {
+ std::vector<std::string> validCombination;
+ for (auto &cameraId : combination) {
+ // if the camera state is not present, skip
+ String8 cameraIdStr(cameraId.c_str());
+ auto state = getCameraState(cameraIdStr);
+ if (state == nullptr) {
+ ALOGW("%s: camera id %s does not exist", __FUNCTION__, cameraId.c_str());
+ continue;
+ }
+ StatusInternal status = state->getStatus();
+ if (status == StatusInternal::NOT_PRESENT || status == StatusInternal::ENUMERATING) {
+ continue;
+ }
+ if (shouldRejectSystemCameraConnection(cameraIdStr)) {
+ continue;
+ }
+ validCombination.push_back(cameraId);
+ }
+ if (validCombination.size() != 0) {
+ concurrentCameraIds->push_back(std::move(validCombination));
+ }
+ }
+ return Status::ok();
+}
+
+Status CameraService::isConcurrentSessionConfigurationSupported(
+ const std::vector<CameraIdAndSessionConfiguration>& cameraIdsAndSessionConfigurations,
+ /*out*/bool* isSupported) {
+ if (!isSupported) {
+ ALOGE("%s: isSupported is NULL", __FUNCTION__);
+ return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, "isSupported is NULL");
+ }
+
+ if (!mInitialized) {
+ ALOGE("%s: Camera HAL couldn't be initialized", __FUNCTION__);
+ return STATUS_ERROR(ERROR_DISCONNECTED,
+ "Camera subsystem is not available");
+ }
+
+ // Check for camera permissions
+ int callingPid = CameraThreadState::getCallingPid();
+ int callingUid = CameraThreadState::getCallingUid();
+ if ((callingPid != getpid()) && !checkPermission(sCameraPermission, callingPid, callingUid)) {
+ ALOGE("%s: pid %d doesn't have camera permissions", __FUNCTION__, callingPid);
+ return STATUS_ERROR(ERROR_PERMISSION_DENIED,
+ "android.permission.CAMERA needed to call"
+ "isConcurrentSessionConfigurationSupported");
+ }
+
+ status_t res =
+ mCameraProviderManager->isConcurrentSessionConfigurationSupported(
+ cameraIdsAndSessionConfigurations, isSupported);
+ if (res != OK) {
+ return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Unable to query session configuration "
+ "support %s (%d)", strerror(-res), res);
+ }
+ return Status::ok();
+}
+
Status CameraService::addListener(const sp<ICameraServiceListener>& listener,
/*out*/
std::vector<hardware::CameraStatus> *cameraStatuses) {
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 8d73183..e433544 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -37,6 +37,7 @@
#include <camera/VendorTagDescriptor.h>
#include <camera/CaptureResult.h>
#include <camera/CameraParameters.h>
+#include <camera/camera2/ConcurrentCamera.h>
#include "CameraFlashlight.h"
@@ -150,6 +151,14 @@
virtual binder::Status removeListener(
const sp<hardware::ICameraServiceListener>& listener);
+ virtual binder::Status getConcurrentStreamingCameraIds(
+ /*out*/
+ std::vector<hardware::camera2::utils::ConcurrentCameraIdCombination>* concurrentCameraIds);
+
+ virtual binder::Status isConcurrentSessionConfigurationSupported(
+ const std::vector<hardware::camera2::utils::CameraIdAndSessionConfiguration>& sessions,
+ /*out*/bool* supported);
+
virtual binder::Status getLegacyParameters(
int32_t cameraId,
/*out*/
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;
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 7d38f9f..888fcce 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -34,6 +34,8 @@
namespace android {
+typedef std::function<CameraMetadata (const String8 &)> metadataGetter;
+
struct CameraDeviceClientBase :
public CameraService::BasicClient,
public hardware::camera2::BnCameraDeviceUser
@@ -202,6 +204,16 @@
virtual void notifyRequestQueueEmpty();
virtual void notifyRepeatingRequestError(long lastFrameNumber);
+ // utility function to convert AIDL SessionConfiguration to HIDL
+ // streamConfiguration. Also checks for sanity of SessionConfiguration and
+ // returns a non-ok binder::Status if the passed in session configuration
+ // isn't valid.
+ static binder::Status
+ convertToHALStreamCombination(const SessionConfiguration& sessionConfiguration,
+ const String8 &cameraId, const CameraMetadata &deviceInfo,
+ metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
+ hardware::camera::device::V3_4::StreamConfiguration &streamConfiguration,
+ bool *earlyExit);
/**
* Interface used by independent components of CameraDeviceClient.
*/
@@ -256,10 +268,10 @@
/** Utility members */
binder::Status checkPidStatus(const char* checkLocation);
- binder::Status checkOperatingModeLocked(int operatingMode) const;
- binder::Status checkPhysicalCameraIdLocked(String8 physicalCameraId);
- binder::Status checkSurfaceTypeLocked(size_t numBufferProducers, bool deferredConsumer,
- int surfaceType) const;
+ static binder::Status checkOperatingMode(int operatingMode, const CameraMetadata &staticInfo,
+ const String8 &cameraId);
+ static binder::Status checkSurfaceType(size_t numBufferProducers, bool deferredConsumer,
+ int surfaceType);
static void mapStreamInfo(const OutputStreamInfo &streamInfo,
camera3_stream_rotation_t rotation, String8 physicalId,
hardware::camera::device::V3_4::Stream *stream /*out*/);
@@ -290,9 +302,9 @@
// Create a Surface from an IGraphicBufferProducer. Returns error if
// IGraphicBufferProducer's property doesn't match with streamInfo
- binder::Status createSurfaceFromGbp(OutputStreamInfo& streamInfo, bool isStreamInfoValid,
- sp<Surface>& surface, const sp<IGraphicBufferProducer>& gbp,
- const String8& physicalCameraId);
+ static binder::Status createSurfaceFromGbp(OutputStreamInfo& streamInfo, bool isStreamInfoValid,
+ sp<Surface>& surface, const sp<IGraphicBufferProducer>& gbp, const String8 &cameraId,
+ const CameraMetadata &physicalCameraMetadata);
// Utility method to insert the surface into SurfaceMap
@@ -302,7 +314,8 @@
// Check that the physicalCameraId passed in is spported by the camera
// device.
- bool checkPhysicalCameraId(const String8& physicalCameraId);
+ static binder::Status checkPhysicalCameraId(const std::vector<std::string> &physicalCameraIds,
+ const String8 &physicalCameraId, const String8 &logicalCameraId);
// IGraphicsBufferProducer binder -> Stream ID + Surface ID for output streams
KeyedVector<sp<IBinder>, StreamSurfaceId> mStreamMap;
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index 1401ba7..b20774a 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -37,6 +37,7 @@
#include <android-base/logging.h>
#include <cutils/properties.h>
#include <hwbinder/IPCThreadState.h>
+#include <utils/SessionConfigurationUtils.h>
#include <utils/Trace.h>
#include "api2/HeicCompositeStream.h"
@@ -47,6 +48,8 @@
using namespace ::android::hardware::camera;
using namespace ::android::hardware::camera::common::V1_0;
using std::literals::chrono_literals::operator""s;
+using hardware::camera2::utils::CameraIdAndSessionConfiguration;
+using hardware::camera::provider::V2_6::CameraIdAndStreamCombination;
namespace {
const bool kEnableLazyHal(property_get_bool("ro.camera.enableLazyHal", false));
@@ -267,7 +270,6 @@
const hardware::camera::device::V3_4::StreamConfiguration &configuration,
bool *status /*out*/) const {
std::lock_guard<std::mutex> lock(mInterfaceMutex);
-
auto deviceInfo = findDeviceInfoLocked(id);
if (deviceInfo == nullptr) {
return NAME_NOT_FOUND;
@@ -1083,10 +1085,8 @@
return OK;
}
-bool CameraProviderManager::isLogicalCamera(const std::string& id,
+bool CameraProviderManager::isLogicalCameraLocked(const std::string& id,
std::vector<std::string>* physicalCameraIds) {
- std::lock_guard<std::mutex> lock(mInterfaceMutex);
-
auto deviceInfo = findDeviceInfoLocked(id);
if (deviceInfo == nullptr) return false;
@@ -1096,6 +1096,12 @@
return deviceInfo->mIsLogicalCamera;
}
+bool CameraProviderManager::isLogicalCamera(const std::string& id,
+ std::vector<std::string>* physicalCameraIds) {
+ std::lock_guard<std::mutex> lock(mInterfaceMutex);
+ return isLogicalCameraLocked(id, physicalCameraIds);
+}
+
status_t CameraProviderManager::getSystemCameraKind(const std::string& id,
SystemCameraKind *kind) const {
std::lock_guard<std::mutex> lock(mInterfaceMutex);
@@ -1261,11 +1267,27 @@
mProviderName.c_str(), interface->isRemote());
// Determine minor version
- auto castResult = provider::V2_5::ICameraProvider::castFrom(interface);
- if (castResult.isOk()) {
- mMinorVersion = 5;
- } else {
- mMinorVersion = 4;
+ mMinorVersion = 4;
+ auto cast2_6 = provider::V2_6::ICameraProvider::castFrom(interface);
+ sp<provider::V2_6::ICameraProvider> interface2_6 = nullptr;
+ if (cast2_6.isOk()) {
+ interface2_6 = cast2_6;
+ if (interface2_6 != nullptr) {
+ mMinorVersion = 6;
+ }
+ }
+ // We need to check again since cast2_6.isOk() succeeds even if the provider
+ // version isn't actually 2.6.
+ if (interface2_6 == nullptr){
+ auto cast2_5 =
+ provider::V2_5::ICameraProvider::castFrom(interface);
+ sp<provider::V2_5::ICameraProvider> interface2_5 = nullptr;
+ if (cast2_5.isOk()) {
+ interface2_5 = cast2_5;
+ if (interface != nullptr) {
+ mMinorVersion = 5;
+ }
+ }
}
hardware::Return<bool> linked = interface->linkToDeath(this, /*cookie*/ mId);
@@ -1328,6 +1350,34 @@
return mapToStatusT(status);
}
+ // Get list of concurrent streaming camera device combinations
+ if (mMinorVersion >= 6) {
+ hardware::Return<void> ret = interface2_6->getConcurrentStreamingCameraIds([&status, this](
+ Status concurrentIdStatus, // TODO: Move all instances of hidl_string to 'using'
+ const hardware::hidl_vec<hardware::hidl_vec<hardware::hidl_string>>&
+ cameraDeviceIdCombinations) {
+ status = concurrentIdStatus;
+ if (status == Status::OK) {
+ for (auto& combination : cameraDeviceIdCombinations) {
+ std::unordered_set<std::string> deviceIds;
+ for (auto &cameraDeviceId : combination) {
+ deviceIds.insert(cameraDeviceId.c_str());
+ }
+ mConcurrentCameraIdCombinations.push_back(std::move(deviceIds));
+ }
+ } });
+ if (!ret.isOk()) {
+ ALOGE("%s: Transaction error in getting camera ID list from provider '%s': %s",
+ __FUNCTION__, mProviderName.c_str(), linked.description().c_str());
+ return DEAD_OBJECT;
+ }
+ if (status != Status::OK) {
+ ALOGE("%s: Unable to query for camera devices from provider '%s'",
+ __FUNCTION__, mProviderName.c_str());
+ return mapToStatusT(status);
+ }
+ }
+
ret = interface->isSetTorchModeSupported(
[this](auto status, bool supported) {
if (status == Status::OK) {
@@ -1780,6 +1830,55 @@
return OK;
}
+status_t CameraProviderManager::ProviderInfo::isConcurrentSessionConfigurationSupported(
+ const hardware::hidl_vec<CameraIdAndStreamCombination> &halCameraIdsAndStreamCombinations,
+ bool *isSupported) {
+ status_t res = OK;
+ if (mMinorVersion >= 6) {
+ // Check if the provider is currently active - not going to start it up for this notification
+ auto interface = mSavedInterface != nullptr ? mSavedInterface : mActiveInterface.promote();
+ if (interface == nullptr) {
+ // TODO: This might be some other problem
+ return INVALID_OPERATION;
+ }
+ auto castResult = provider::V2_6::ICameraProvider::castFrom(interface);
+ if (castResult.isOk()) {
+ sp<provider::V2_6::ICameraProvider> interface_2_6 = castResult;
+ if (interface_2_6 != nullptr) {
+ Status callStatus;
+ auto cb =
+ [&isSupported, &callStatus](Status s, bool supported) {
+ callStatus = s;
+ *isSupported = supported; };
+
+ auto ret = interface_2_6->isConcurrentStreamCombinationSupported(
+ halCameraIdsAndStreamCombinations, cb);
+ if (ret.isOk()) {
+ switch (callStatus) {
+ case Status::OK:
+ // Expected case, do nothing.
+ res = OK;
+ break;
+ case Status::METHOD_NOT_SUPPORTED:
+ res = INVALID_OPERATION;
+ break;
+ default:
+ ALOGE("%s: Session configuration query failed: %d", __FUNCTION__,
+ callStatus);
+ res = UNKNOWN_ERROR;
+ }
+ } else {
+ ALOGE("%s: Unexpected binder error: %s", __FUNCTION__, ret.description().c_str());
+ res = UNKNOWN_ERROR;
+ }
+ return res;
+ }
+ }
+ }
+ // unsupported operation
+ return INVALID_OPERATION;
+}
+
template<class DeviceInfoT>
std::unique_ptr<CameraProviderManager::ProviderInfo::DeviceInfo>
CameraProviderManager::ProviderInfo::initializeDeviceInfo(
@@ -2642,6 +2741,125 @@
return OK;
}
+// Expects to have mInterfaceMutex locked
+std::vector<std::unordered_set<std::string>>
+CameraProviderManager::getConcurrentStreamingCameraIds() const {
+ std::vector<std::unordered_set<std::string>> deviceIdCombinations;
+ std::lock_guard<std::mutex> lock(mInterfaceMutex);
+ for (auto &provider : mProviders) {
+ for (auto &combinations : provider->mConcurrentCameraIdCombinations) {
+ deviceIdCombinations.push_back(combinations);
+ }
+ }
+ return deviceIdCombinations;
+}
+
+status_t CameraProviderManager::convertToHALStreamCombinationAndCameraIdsLocked(
+ const std::vector<CameraIdAndSessionConfiguration> &cameraIdsAndSessionConfigs,
+ hardware::hidl_vec<CameraIdAndStreamCombination> *halCameraIdsAndStreamCombinations,
+ bool *earlyExit) {
+ binder::Status bStatus = binder::Status::ok();
+ std::vector<CameraIdAndStreamCombination> halCameraIdsAndStreamsV;
+ bool shouldExit = false;
+ status_t res = OK;
+ for (auto &cameraIdAndSessionConfig : cameraIdsAndSessionConfigs) {
+ hardware::camera::device::V3_4::StreamConfiguration streamConfiguration;
+ CameraMetadata deviceInfo;
+ res = getCameraCharacteristicsLocked(cameraIdAndSessionConfig.mCameraId, &deviceInfo);
+ if (res != OK) {
+ return res;
+ }
+ metadataGetter getMetadata =
+ [this](const String8 &id) {
+ CameraMetadata physicalDeviceInfo;
+ getCameraCharacteristicsLocked(id.string(), &physicalDeviceInfo);
+ return physicalDeviceInfo;
+ };
+ std::vector<std::string> physicalCameraIds;
+ isLogicalCameraLocked(cameraIdAndSessionConfig.mCameraId, &physicalCameraIds);
+ bStatus =
+ SessionConfigurationUtils::convertToHALStreamCombination(
+ cameraIdAndSessionConfig.mSessionConfiguration,
+ String8(cameraIdAndSessionConfig.mCameraId.c_str()), deviceInfo, getMetadata,
+ physicalCameraIds, streamConfiguration, &shouldExit);
+ if (!bStatus.isOk()) {
+ ALOGE("%s: convertToHALStreamCombination failed", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+ if (shouldExit) {
+ *earlyExit = true;
+ return OK;
+ }
+ CameraIdAndStreamCombination halCameraIdAndStream;
+ halCameraIdAndStream.cameraId = cameraIdAndSessionConfig.mCameraId;
+ halCameraIdAndStream.streamConfiguration = streamConfiguration;
+ halCameraIdsAndStreamsV.push_back(halCameraIdAndStream);
+ }
+ *halCameraIdsAndStreamCombinations = halCameraIdsAndStreamsV;
+ return OK;
+}
+
+// Checks if the containing vector of sets has any set that contains all of the
+// camera ids in cameraIdsAndSessionConfigs.
+static bool checkIfSetContainsAll(
+ const std::vector<CameraIdAndSessionConfiguration> &cameraIdsAndSessionConfigs,
+ const std::vector<std::unordered_set<std::string>> &containingSets) {
+ for (auto &containingSet : containingSets) {
+ bool didHaveAll = true;
+ for (auto &cameraIdAndSessionConfig : cameraIdsAndSessionConfigs) {
+ if (containingSet.find(cameraIdAndSessionConfig.mCameraId) == containingSet.end()) {
+ // a camera id doesn't belong to this set, keep looking in other
+ // sets
+ didHaveAll = false;
+ break;
+ }
+ }
+ if (didHaveAll) {
+ // found a set that has all camera ids, lets return;
+ return true;
+ }
+ }
+ return false;
+}
+
+status_t CameraProviderManager::isConcurrentSessionConfigurationSupported(
+ const std::vector<CameraIdAndSessionConfiguration> &cameraIdsAndSessionConfigs,
+ bool *isSupported) {
+ std::lock_guard<std::mutex> lock(mInterfaceMutex);
+ // Check if all the devices are a subset of devices advertised by the
+ // same provider through getConcurrentStreamingCameraIds()
+ // TODO: we should also do a findDeviceInfoLocked here ?
+ for (auto &provider : mProviders) {
+ if (checkIfSetContainsAll(cameraIdsAndSessionConfigs,
+ provider->mConcurrentCameraIdCombinations)) {
+ // For each camera device in cameraIdsAndSessionConfigs collect
+ // the streamConfigs and create the HAL
+ // CameraIdAndStreamCombination, exit early if needed
+ hardware::hidl_vec<CameraIdAndStreamCombination> halCameraIdsAndStreamCombinations;
+ bool knowUnsupported = false;
+ status_t res = convertToHALStreamCombinationAndCameraIdsLocked(
+ cameraIdsAndSessionConfigs, &halCameraIdsAndStreamCombinations,
+ &knowUnsupported);
+ if (res != OK) {
+ ALOGE("%s unable to convert session configurations provided to HAL stream"
+ "combinations", __FUNCTION__);
+ return res;
+ }
+ if (knowUnsupported) {
+ // We got to know the streams aren't valid before doing the HAL
+ // call itself.
+ *isSupported = false;
+ return OK;
+ }
+ return provider->isConcurrentSessionConfigurationSupported(
+ halCameraIdsAndStreamCombinations, isSupported);
+ }
+ }
+ *isSupported = false;
+ //The set of camera devices were not found
+ return INVALID_OPERATION;
+}
+
status_t CameraProviderManager::getCameraCharacteristicsLocked(const std::string &id,
CameraMetadata* characteristics) const {
auto deviceInfo = findDeviceInfoLocked(id, /*minVersion*/ {3,0}, /*maxVersion*/ {5,0});
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index 49a93cc..42da227 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -23,6 +23,7 @@
#include <string>
#include <mutex>
+#include <camera/camera2/ConcurrentCamera.h>
#include <camera/CameraParameters2.h>
#include <camera/CameraMetadata.h>
#include <camera/CameraBase.h>
@@ -30,6 +31,7 @@
#include <android/hardware/camera/common/1.0/types.h>
#include <android/hardware/camera/provider/2.5/ICameraProvider.h>
#include <android/hardware/camera/provider/2.6/ICameraProviderCallback.h>
+#include <android/hardware/camera/provider/2.6/ICameraProvider.h>
#include <android/hardware/camera/device/3.4/ICameraDeviceSession.h>
#include <android/hidl/manager/1.0/IServiceNotification.h>
#include <camera/VendorTagDescriptor.h>
@@ -214,6 +216,12 @@
status_t getCameraCharacteristics(const std::string &id,
CameraMetadata* characteristics) const;
+ status_t isConcurrentSessionConfigurationSupported(
+ const std::vector<hardware::camera2::utils::CameraIdAndSessionConfiguration>
+ &cameraIdsAndSessionConfigs,
+ bool *isSupported);
+
+ std::vector<std::unordered_set<std::string>> getConcurrentStreamingCameraIds() const;
/**
* Check for device support of specific stream combination.
*/
@@ -409,6 +417,14 @@
status_t notifyDeviceStateChange(
hardware::hidl_bitfield<hardware::camera::provider::V2_5::DeviceState>
newDeviceState);
+ /**
+ * Query the camera provider for concurrent stream configuration support
+ */
+ status_t isConcurrentSessionConfigurationSupported(
+ const hardware::hidl_vec<
+ hardware::camera::provider::V2_6::CameraIdAndStreamCombination>
+ &halCameraIdsAndStreamCombinations,
+ bool *isSupported);
// Basic device information, common to all camera devices
struct DeviceInfo {
@@ -494,6 +510,8 @@
// physical camera IDs.
std::vector<std::string> mProviderPublicCameraIds;
+ std::vector<std::unordered_set<std::string>> mConcurrentCameraIdCombinations;
+
// HALv1-specific camera fields, including the actual device interface
struct DeviceInfo1 : public DeviceInfo {
typedef hardware::camera::device::V1_0::ICameraDevice InterfaceT;
@@ -618,6 +636,8 @@
status_t addProviderLocked(const std::string& newProvider);
+ bool isLogicalCameraLocked(const std::string& id, std::vector<std::string>* physicalCameraIds);
+
status_t removeProvider(const std::string& provider);
sp<StatusListener> getStatusListener() const;
@@ -648,6 +668,13 @@
void collectDeviceIdsLocked(const std::vector<std::string> deviceIds,
std::vector<std::string>& normalDeviceIds,
std::vector<std::string>& systemCameraDeviceIds) const;
+
+ status_t convertToHALStreamCombinationAndCameraIdsLocked(
+ const std::vector<hardware::camera2::utils::CameraIdAndSessionConfiguration>
+ &cameraIdsAndSessionConfigs,
+ hardware::hidl_vec<hardware::camera::provider::V2_6::CameraIdAndStreamCombination>
+ *halCameraIdsAndStreamCombinations,
+ bool *earlyExit);
};
} // namespace android
diff --git a/services/camera/libcameraservice/tests/Android.mk b/services/camera/libcameraservice/tests/Android.mk
index 8784c95..fa5d69e 100644
--- a/services/camera/libcameraservice/tests/Android.mk
+++ b/services/camera/libcameraservice/tests/Android.mk
@@ -25,6 +25,7 @@
liblog \
libcamera_client \
libcamera_metadata \
+ libui \
libutils \
libjpeg \
libexif \
@@ -34,7 +35,8 @@
android.hardware.camera.provider@2.6 \
android.hardware.camera.device@1.0 \
android.hardware.camera.device@3.2 \
- android.hardware.camera.device@3.4
+ android.hardware.camera.device@3.4 \
+ android.hidl.token@1.0-utils
LOCAL_STATIC_LIBRARIES := \
libgmock
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
new file mode 100644
index 0000000..888671c
--- /dev/null
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "SessionConfigurationUtils.h"
+#include "../api2/CameraDeviceClient.h"
+
+namespace android {
+
+binder::Status
+SessionConfigurationUtils::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 *earlyExit) {
+ // TODO: http://b/148329298 Move the other dependencies from
+ // CameraDeviceClient into SessionConfigurationUtils.
+ return CameraDeviceClient::convertToHALStreamCombination(sessionConfiguration, logicalCameraId,
+ deviceInfo, getMetadata, physicalCameraIds, streamConfiguration, earlyExit);
+}
+
+}// namespace android
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.h b/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
new file mode 100644
index 0000000..fb519d9
--- /dev/null
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef ANDROID_SERVERS_CAMERA_SESSION_CONFIGURATION_UTILS_H
+#define ANDROID_SERVERS_CAMERA_SESSION_CONFIGURATION_UTILS_H
+
+#include <android/hardware/camera2/BnCameraDeviceUser.h>
+#include <android/hardware/camera2/ICameraDeviceCallbacks.h>
+#include <camera/camera2/OutputConfiguration.h>
+#include <camera/camera2/SessionConfiguration.h>
+#include <camera/camera2/SubmitInfo.h>
+#include <android/hardware/camera/device/3.4/ICameraDeviceSession.h>
+
+#include <stdint.h>
+
+namespace android {
+
+typedef std::function<CameraMetadata (const String8 &)> metadataGetter;
+
+class SessionConfigurationUtils {
+public:
+ // utility function to convert AIDL SessionConfiguration to HIDL
+ // streamConfiguration. Also checks for sanity of SessionConfiguration and
+ // returns a non-ok binder::Status if the passed in session configuration
+ // isn't valid.
+ static binder::Status
+ convertToHALStreamCombination(const SessionConfiguration& sessionConfiguration,
+ const String8 &cameraId, const CameraMetadata &deviceInfo,
+ metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
+ hardware::camera::device::V3_4::StreamConfiguration &streamConfiguration,
+ bool *earlyExit);
+};
+
+} // android
+#endif