Merge "ICameraService: Add methods to query concurrent streaming camera support."

gugelfrei
Jayant Chowdhary 4 years ago committed by Android (Google) Code Review
commit 6425bcd8d5

@ -40,6 +40,7 @@ cc_library_shared {
"ICameraRecordingProxy.cpp",
"ICameraRecordingProxyListener.cpp",
"camera2/CaptureRequest.cpp",
"camera2/ConcurrentCamera.cpp",
"camera2/OutputConfiguration.cpp",
"camera2/SessionConfiguration.cpp",
"camera2/SubmitInfo.cpp",
@ -66,7 +67,7 @@ cc_library_shared {
"include",
"include/camera"
],
export_shared_lib_headers: ["libcamera_metadata"],
export_shared_lib_headers: ["libcamera_metadata", "libnativewindow", "libgui"],
cflags: [
"-Werror",

@ -22,6 +22,8 @@ import android.hardware.camera2.ICameraDeviceUser;
import android.hardware.camera2.ICameraDeviceCallbacks;
import android.hardware.camera2.params.VendorTagDescriptor;
import android.hardware.camera2.params.VendorTagDescriptorCache;
import android.hardware.camera2.utils.ConcurrentCameraIdCombination;
import android.hardware.camera2.utils.CameraIdAndSessionConfiguration;
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.ICameraServiceListener;
import android.hardware.CameraInfo;
@ -113,6 +115,25 @@ interface ICameraService
*/
CameraStatus[] addListener(ICameraServiceListener listener);
/**
* Get a list of combinations of camera ids which support concurrent streaming.
*
*/
ConcurrentCameraIdCombination[] getConcurrentStreamingCameraIds();
/**
* Check whether a particular set of session configurations are concurrently supported by the
* corresponding camera ids.
*
* @param sessions the set of camera id and session configuration pairs to be queried.
* @return true - the set of concurrent camera id and stream combinations is supported.
* false - the set of concurrent camera id and stream combinations is not supported
* OR the method was called with a set of camera ids not returned by
* getConcurrentMultiStreamingCameraIds().
*/
boolean isConcurrentSessionConfigurationSupported(
in CameraIdAndSessionConfiguration[] sessions);
/**
* Remove listener for changes to camera device and flashlight state.
*/

@ -0,0 +1,20 @@
/*
* 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.
*/
package android.hardware.camera2.utils;
/** @hide */
parcelable CameraIdAndSessionConfiguration cpp_header "camera/camera2/ConcurrentCamera.h";

@ -0,0 +1,20 @@
/*
* 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.
*/
package android.hardware.camera2.utils;
/** @hide */
parcelable ConcurrentCameraIdCombination cpp_header "camera/camera2/ConcurrentCamera.h";

@ -0,0 +1,129 @@
/*
* 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.
*/
// #define LOG_NDEBUG 0
#define LOG_TAG "ConcurrentCamera"
#include <utils/Log.h>
#include <utils/String16.h>
#include <camera/camera2/ConcurrentCamera.h>
#include <binder/Parcel.h>
namespace android {
namespace hardware {
namespace camera2 {
namespace utils {
ConcurrentCameraIdCombination::ConcurrentCameraIdCombination() = default;
ConcurrentCameraIdCombination::ConcurrentCameraIdCombination(
std::vector<std::string> &&combination) : mConcurrentCameraIds(std::move(combination)) { }
ConcurrentCameraIdCombination::~ConcurrentCameraIdCombination() = default;
status_t ConcurrentCameraIdCombination::readFromParcel(const android::Parcel* parcel) {
if (parcel == nullptr) {
ALOGE("%s: Null parcel", __FUNCTION__);
return BAD_VALUE;
}
status_t err = OK;
mConcurrentCameraIds.clear();
int32_t cameraIdCount = 0;
if ((err = parcel->readInt32(&cameraIdCount)) != OK) {
ALOGE("%s: Failed to read the camera id count from parcel: %d", __FUNCTION__, err);
return err;
}
for (int32_t i = 0; i < cameraIdCount; i++) {
String16 id;
if ((err = parcel->readString16(&id)) != OK) {
ALOGE("%s: Failed to read camera id!", __FUNCTION__);
return err;
}
mConcurrentCameraIds.push_back(std::string(String8(id).string()));
}
return OK;
}
status_t ConcurrentCameraIdCombination::writeToParcel(android::Parcel* parcel) const {
if (parcel == nullptr) {
ALOGE("%s: Null parcel", __FUNCTION__);
return BAD_VALUE;
}
status_t err = OK;
if ((err = parcel->writeInt32(mConcurrentCameraIds.size())) != OK) {
ALOGE("%s: Failed to write the camera id count to parcel: %d", __FUNCTION__, err);
return err;
}
for (const auto &it : mConcurrentCameraIds) {
if ((err = parcel->writeString16(String16(it.c_str()))) != OK) {
ALOGE("%s: Failed to write the camera id string to parcel: %d", __FUNCTION__, err);
return err;
}
}
return OK;
}
CameraIdAndSessionConfiguration::CameraIdAndSessionConfiguration() = default;
CameraIdAndSessionConfiguration::~CameraIdAndSessionConfiguration() = default;
status_t CameraIdAndSessionConfiguration::readFromParcel(const android::Parcel* parcel) {
if (parcel == nullptr) {
ALOGE("%s: Null parcel", __FUNCTION__);
return BAD_VALUE;
}
status_t err = OK;
String16 id;
if ((err = parcel->readString16(&id)) != OK) {
ALOGE("%s: Failed to read camera id!", __FUNCTION__);
return err;
}
if ((err = mSessionConfiguration.readFromParcel(parcel)) != OK) {
ALOGE("%s: Failed to read sessionConfiguration!", __FUNCTION__);
return err;
}
mCameraId = std::string(String8(id).string());
return OK;
}
status_t CameraIdAndSessionConfiguration::writeToParcel(android::Parcel* parcel) const {
if (parcel == nullptr) {
ALOGE("%s: Null parcel", __FUNCTION__);
return BAD_VALUE;
}
status_t err = OK;
if ((err = parcel->writeString16(String16(mCameraId.c_str()))) != OK) {
ALOGE("%s: Failed to write camera id!", __FUNCTION__);
return err;
}
if ((err = mSessionConfiguration.writeToParcel(parcel) != OK)) {
ALOGE("%s: Failed to write session configuration!", __FUNCTION__);
return err;
}
return OK;
}
} // namespace utils
} // namespace camera2
} // namespace hardware
} // namespace android

@ -0,0 +1,56 @@
/*
* 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_HARDWARE_CAMERA2_UTIL_CONCURRENTCAMERA_H
#define ANDROID_HARDWARE_CAMERA2_UTIL_CONCURRENTCAMERA_H
#include <binder/Parcel.h>
#include <binder/Parcelable.h>
#include <camera2/OutputConfiguration.h>
#include <camera2/SessionConfiguration.h>
namespace android {
namespace hardware {
namespace camera2 {
namespace utils {
struct ConcurrentCameraIdCombination : public Parcelable {
std::vector<std::string> mConcurrentCameraIds;
ConcurrentCameraIdCombination();
ConcurrentCameraIdCombination(std::vector<std::string> &&combination);
virtual ~ConcurrentCameraIdCombination();
virtual status_t writeToParcel(android::Parcel *parcel) const override;
virtual status_t readFromParcel(const android::Parcel* parcel) override;
};
struct CameraIdAndSessionConfiguration : public Parcelable {
std::string mCameraId;
SessionConfiguration mSessionConfiguration;
CameraIdAndSessionConfiguration();
virtual ~CameraIdAndSessionConfiguration();
virtual status_t writeToParcel(android::Parcel *parcel) const override;
virtual status_t readFromParcel(const android::Parcel* parcel) override;
};
} // namespace utils
} // namespace camera2
} // namespace hardware
} // namespace android
#endif

@ -66,15 +66,16 @@ cc_library_shared {
"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",
],

@ -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::ICameraServiceProxy;
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 @@ Status CameraService::notifyDeviceStateChange(int64_t newState) {
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) {

@ -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 @@ public:
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*/

@ -492,7 +492,7 @@ binder::Status CameraDeviceClient::endConfigure(int operatingMode,
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 @@ binder::Status CameraDeviceClient::endConfigure(int operatingMode,
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 @@ binder::Status CameraDeviceClient::checkSurfaceTypeLocked(size_t numBufferProduc
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 @@ binder::Status CameraDeviceClient::checkOperatingModeLocked(int operatingMode) c
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 @@ binder::Status CameraDeviceClient::checkOperatingModeLocked(int operatingMode) c
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 @@ void CameraDeviceClient::mapStreamInfo(const OutputStreamInfo &streamInfo,
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 @@ binder::Status CameraDeviceClient::isSessionConfigurationSupported(
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 @@ binder::Status CameraDeviceClient::isSessionConfigurationSupported(
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 @@ binder::Status CameraDeviceClient::isSessionConfigurationSupported(
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 @@ binder::Status CameraDeviceClient::isSessionConfigurationSupported(
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 @@ binder::Status CameraDeviceClient::isSessionConfigurationSupported(
}
}
}
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 @@ binder::Status CameraDeviceClient::createStream(
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 @@ binder::Status CameraDeviceClient::createStream(
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 @@ binder::Status CameraDeviceClient::createStream(
sp<Surface> surface;
res = createSurfaceFromGbp(streamInfo, isStreamInfoValid, surface, bufferProducer,
physicalCameraId);
mCameraIdStr, mDevice->info(physicalCameraId));
if (!res.isOk())
return res;
@ -1278,7 +1314,7 @@ binder::Status CameraDeviceClient::updateOutputConfiguration(int streamId,
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 @@ bool CameraDeviceClient::isPublicFormat(int32_t format)
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 @@ binder::Status CameraDeviceClient::createSurfaceFromGbp(
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 @@ binder::Status CameraDeviceClient::createSurfaceFromGbp(
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 @@ binder::Status CameraDeviceClient::createSurfaceFromGbp(
((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 @@ binder::Status CameraDeviceClient::createSurfaceFromGbp(
}
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 @@ binder::Status CameraDeviceClient::createSurfaceFromGbp(
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 @@ binder::Status CameraDeviceClient::finalizeOutputConfigurations(int32_t streamId
sp<Surface> surface;
res = createSurfaceFromGbp(mStreamInfoMap[streamId], true /*isStreamInfoValid*/,
surface, bufferProducer, physicalId);
surface, bufferProducer, mCameraIdStr, mDevice->info(physicalId));
if (!res.isOk())
return res;

@ -34,6 +34,8 @@ using android::camera3::CompositeStream;
namespace android {
typedef std::function<CameraMetadata (const String8 &)> metadataGetter;
struct CameraDeviceClientBase :
public CameraService::BasicClient,
public hardware::camera2::BnCameraDeviceUser
@ -202,6 +204,16 @@ public:
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 @@ private:
/** 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 @@ private:
// 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 @@ private:
// 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;

@ -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 @@ namespace android {
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 @@ status_t CameraProviderManager::isSessionConfigurationSupported(const std::strin
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 @@ status_t CameraProviderManager::ProviderInfo::DeviceInfo3::deriveHeicTags() {
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 @@ bool CameraProviderManager::isLogicalCamera(const std::string& id,
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 @@ status_t CameraProviderManager::ProviderInfo::initialize(
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 @@ status_t CameraProviderManager::ProviderInfo::initialize(
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 @@ status_t CameraProviderManager::ProviderInfo::notifyDeviceStateChange(
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 @@ status_t HidlVendorTagDescriptor::createDescriptorFromHidl(
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});

@ -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 @@ public:
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 @@ private:
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 @@ private:
// 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 @@ private:
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 @@ private:
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

@ -25,6 +25,7 @@ LOCAL_SHARED_LIBRARIES := \
liblog \
libcamera_client \
libcamera_metadata \
libui \
libutils \
libjpeg \
libexif \
@ -34,7 +35,8 @@ LOCAL_SHARED_LIBRARIES := \
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

@ -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

@ -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
Loading…
Cancel
Save