/* * Copyright (C) 2022 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 "AidlProviderInfo.h" #include "common/HalConversionsTemplated.h" #include "common/CameraProviderInfoTemplated.h" #include #include #include #include #include #include "device3/ZoomRatioMapper.h" #include #include namespace { const bool kEnableLazyHal(property_get_bool("ro.camera.enableLazyHal", false)); } // anonymous namespace namespace android { namespace SessionConfigurationUtils = ::android::camera3::SessionConfigurationUtils; using namespace aidl::android::hardware; using namespace hardware::camera; using hardware::camera2::utils::CameraIdAndSessionConfiguration; using hardware::ICameraService; using HalDeviceStatusType = aidl::android::hardware::camera::common::CameraDeviceStatus; using ICameraProvider = aidl::android::hardware::camera::provider::ICameraProvider; using StatusListener = CameraProviderManager::StatusListener; static status_t mapExceptionCodeToStatusT(binder_exception_t binderException) { switch (binderException) { case EX_NONE: return OK; case EX_ILLEGAL_ARGUMENT: case EX_NULL_POINTER: case EX_BAD_PARCELABLE: case EX_ILLEGAL_STATE: return BAD_VALUE; case EX_UNSUPPORTED_OPERATION: return INVALID_OPERATION; case EX_TRANSACTION_FAILED: return DEAD_OBJECT; default: return UNKNOWN_ERROR; } } status_t AidlProviderInfo::mapToStatusT(const ndk::ScopedAStatus& s) { using Status = aidl::android::hardware::camera::common::Status; auto exceptionCode = s.getExceptionCode(); if (exceptionCode != EX_SERVICE_SPECIFIC) { return mapExceptionCodeToStatusT(exceptionCode); } Status st = static_cast(s.getServiceSpecificError()); switch (st) { case Status::OK: return OK; case Status::ILLEGAL_ARGUMENT: return BAD_VALUE; case Status::CAMERA_IN_USE: return -EBUSY; case Status::MAX_CAMERAS_IN_USE: return -EUSERS; case Status::OPERATION_NOT_SUPPORTED: return INVALID_OPERATION; case Status::CAMERA_DISCONNECTED: return DEAD_OBJECT; case Status::INTERNAL_ERROR: return INVALID_OPERATION; } ALOGW("Unexpected HAL status code %d", static_cast(st)); return INVALID_OPERATION; } AidlProviderInfo::AidlProviderInfo( const std::string &providerName, const std::string &providerInstance, CameraProviderManager *manager) : CameraProviderManager::ProviderInfo(providerName, providerInstance, manager) {} status_t AidlProviderInfo::initializeAidlProvider( std::shared_ptr& interface, int64_t currentDeviceState) { status_t res = parseProviderName(mProviderName, &mType, &mId); if (res != OK) { ALOGE("%s: Invalid provider name, ignoring", __FUNCTION__); return BAD_VALUE; } ALOGI("Connecting to new camera provider: %s, isRemote? %d", mProviderName.c_str(), interface->isRemote()); // cameraDeviceStatusChange callbacks may be called (and causing new devices added) // before setCallback returns mCallbacks = ndk::SharedRefBase::make(this); ndk::ScopedAStatus status = interface->setCallback(mCallbacks); if (!status.isOk()) { ALOGE("%s: Transaction error setting up callbacks with camera provider '%s': %s", __FUNCTION__, mProviderName.c_str(), status.getMessage()); return mapToStatusT(status); } mDeathRecipient = ndk::ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient_new(binderDied)); auto link = AIBinder_linkToDeath(interface->asBinder().get(), mDeathRecipient.get(), this); if (link != STATUS_OK) { ALOGW("%s: Unable to link to provider '%s' death notifications", __FUNCTION__, mProviderName.c_str()); return DEAD_OBJECT; } if (!kEnableLazyHal) { // Save HAL reference indefinitely mSavedInterface = interface; } else { mActiveInterface = interface; } ALOGV("%s: Setting device state for %s: 0x%" PRIx64, __FUNCTION__, mProviderName.c_str(), mDeviceState); notifyDeviceStateChange(currentDeviceState); res = setUpVendorTags(); if (res != OK) { ALOGE("%s: Unable to set up vendor tags from provider '%s'", __FUNCTION__, mProviderName.c_str()); return res; } // Get initial list of camera devices, if any std::vector devices; std::vector retDevices; status = interface->getCameraIdList(&retDevices); if (!status.isOk()) { ALOGE("%s: Transaction error in getting camera ID list from provider '%s': %s", __FUNCTION__, mProviderName.c_str(), status.getMessage()); return mapToStatusT(status); } for (auto& name : retDevices) { uint16_t major, minor; std::string type, id; status_t res = parseDeviceName(name, &major, &minor, &type, &id); if (res != OK) { ALOGE("%s: Error parsing deviceName: %s: %d", __FUNCTION__, name.c_str(), res); return res; } else { devices.push_back(name); mProviderPublicCameraIds.push_back(id); } } // Get list of concurrent streaming camera device combinations res = getConcurrentCameraIdsInternalLocked(interface); if (res != OK) { return res; } mSetTorchModeSupported = true; mIsRemote = interface->isRemote(); initializeProviderInfoCommon(devices); return OK; } void AidlProviderInfo::binderDied(void *cookie) { AidlProviderInfo *provider = reinterpret_cast(cookie); ALOGI("Camera provider '%s' has died; removing it", provider->mProviderInstance.c_str()); provider->mManager->removeProvider(provider->mProviderInstance); } status_t AidlProviderInfo::setUpVendorTags() { if (mVendorTagDescriptor != nullptr) return OK; std::vector vts; ::ndk::ScopedAStatus status; const std::shared_ptr interface = startProviderInterface(); if (interface == nullptr) { return DEAD_OBJECT; } status = interface->getVendorTags(&vts); if (!status.isOk()) { ALOGE("%s: Transaction error getting vendor tags from provider '%s': %s", __FUNCTION__, mProviderName.c_str(), status.getMessage()); return mapToStatusT(status); } // Read all vendor tag definitions into a descriptor status_t res; if ((res = IdlVendorTagDescriptor:: createDescriptorFromIdl, camera::common::VendorTagSection>(vts, /*out*/mVendorTagDescriptor)) != OK) { ALOGE("%s: Could not generate descriptor from vendor tag operations," "received error %s (%d). Camera clients will not be able to use" "vendor tags", __FUNCTION__, strerror(res), res); return res; } return OK; } status_t AidlProviderInfo::notifyDeviceStateChange(int64_t newDeviceState) { mDeviceState = newDeviceState; // Check if the provider is currently active - not going to start it up for this notification auto interface = mSavedInterface != nullptr ? mSavedInterface : mActiveInterface.lock(); if (interface != nullptr) { // Send current device state interface->notifyDeviceStateChange(mDeviceState); } return OK; } bool AidlProviderInfo::successfullyStartedProviderInterface() { return startProviderInterface() != nullptr; } std::shared_ptr AidlProviderInfo::startDeviceInterface(const std::string &name) { ::ndk::ScopedAStatus status; std::shared_ptr cameraInterface; const std::shared_ptr interface = startProviderInterface(); if (interface == nullptr) { return nullptr; } status = interface->getCameraDeviceInterface(name, &cameraInterface); if (!status.isOk()) { ALOGE("%s: Transaction error trying to obtain interface for camera device %s: %s", __FUNCTION__, name.c_str(), status.getMessage()); return nullptr; } return cameraInterface; } const std::shared_ptr AidlProviderInfo::startProviderInterface() { ATRACE_CALL(); ALOGV("Request to start camera provider: %s", mProviderName.c_str()); if (mSavedInterface != nullptr) { return mSavedInterface; } if (!kEnableLazyHal) { ALOGE("Bad provider state! Should not be here on a non-lazy HAL!"); return nullptr; } auto interface = mActiveInterface.lock(); if (interface == nullptr) { // Try to get service without starting interface = ICameraProvider::fromBinder( ndk::SpAIBinder(AServiceManager_checkService(mProviderName.c_str()))); if (interface == nullptr) { ALOGV("Camera provider actually needs restart, calling getService(%s)", mProviderName.c_str()); interface = ICameraProvider::fromBinder( ndk::SpAIBinder( AServiceManager_getService(mProviderName.c_str()))); // Set all devices as ENUMERATING, provider should update status // to PRESENT after initializing. // This avoids failing getCameraDeviceInterface_V3_x before devices // are ready. for (auto& device : mDevices) { device->mIsDeviceAvailable = false; } interface->setCallback(mCallbacks); auto link = AIBinder_linkToDeath(interface->asBinder().get(), mDeathRecipient.get(), this); if (link != STATUS_OK) { ALOGW("%s: Unable to link to provider '%s' death notifications", __FUNCTION__, mProviderName.c_str()); mManager->removeProvider(mProviderName); return nullptr; } // Send current device state interface->notifyDeviceStateChange(mDeviceState); } mActiveInterface = interface; } else { ALOGV("Camera provider (%s) already in use. Re-using instance.", mProviderName.c_str()); } return interface; } ::ndk::ScopedAStatus AidlProviderInfo::AidlProviderCallbacks::cameraDeviceStatusChange( const std::string& cameraDeviceName, HalDeviceStatusType newStatus) { sp parent = mParent.promote(); if (parent == nullptr) { ALOGE("%s: Parent provider not alive", __FUNCTION__); return ::ndk::ScopedAStatus::ok(); } return parent->cameraDeviceStatusChange(cameraDeviceName, newStatus); } ::ndk::ScopedAStatus AidlProviderInfo::AidlProviderCallbacks::torchModeStatusChange( const std::string& cameraDeviceName, aidl::android::hardware::camera::common::TorchModeStatus newStatus) { sp parent = mParent.promote(); if (parent == nullptr) { ALOGE("%s: Parent provider not alive", __FUNCTION__); return ::ndk::ScopedAStatus::ok(); } return parent->torchModeStatusChange(cameraDeviceName, newStatus); }; ::ndk::ScopedAStatus AidlProviderInfo::AidlProviderCallbacks::physicalCameraDeviceStatusChange( const std::string& cameraDeviceName, const std::string& physicalCameraDeviceName, HalDeviceStatusType newStatus) { sp parent = mParent.promote(); if (parent == nullptr) { ALOGE("%s: Parent provider not alive", __FUNCTION__); return ::ndk::ScopedAStatus::ok(); } return parent->physicalCameraDeviceStatusChange(cameraDeviceName, physicalCameraDeviceName, newStatus); }; ::ndk::ScopedAStatus AidlProviderInfo::cameraDeviceStatusChange(const std::string& cameraDeviceName, HalDeviceStatusType newStatus) { cameraDeviceStatusChangeInternal(cameraDeviceName, HalToFrameworkCameraDeviceStatus(newStatus)); return ::ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus AidlProviderInfo::torchModeStatusChange(const std::string& cameraDeviceName, aidl::android::hardware::camera::common::TorchModeStatus newStatus) { torchModeStatusChangeInternal(cameraDeviceName, HalToFrameworkTorchModeStatus(newStatus)); return ::ndk::ScopedAStatus::ok(); }; ::ndk::ScopedAStatus AidlProviderInfo::physicalCameraDeviceStatusChange( const std::string& cameraDeviceName, const std::string& physicalCameraDeviceName, HalDeviceStatusType newStatus) { physicalCameraDeviceStatusChangeInternal(cameraDeviceName, physicalCameraDeviceName, HalToFrameworkCameraDeviceStatus(newStatus)); return ::ndk::ScopedAStatus::ok(); }; std::unique_ptr AidlProviderInfo::initializeDeviceInfo( const std::string &name, const metadata_vendor_id_t tagId, const std::string &id, uint16_t minorVersion) { ::ndk::ScopedAStatus status; auto cameraInterface = startDeviceInterface(name); if (cameraInterface == nullptr) return nullptr; camera::common::CameraResourceCost resourceCost; status = cameraInterface->getResourceCost(&resourceCost); if (!status.isOk()) { ALOGE("%s: Unable to obtain resource costs for camera device %s: %s", __FUNCTION__, name.c_str(), status.getMessage()); return nullptr; } for (auto& conflictName : resourceCost.conflictingDevices) { uint16_t major, minor; std::string type, id; status_t res = parseDeviceName(conflictName, &major, &minor, &type, &id); if (res != OK) { ALOGE("%s: Failed to parse conflicting device %s", __FUNCTION__, conflictName.c_str()); return nullptr; } conflictName = id; } return std::unique_ptr( new AidlDeviceInfo3(name, tagId, id, minorVersion, HalToFrameworkResourceCost(resourceCost), this, mProviderPublicCameraIds, cameraInterface)); } status_t AidlProviderInfo::reCacheConcurrentStreamingCameraIdsLocked() { // Check if the provider is currently active - not going to start it up for this notification auto interface = mSavedInterface != nullptr ? mSavedInterface : mActiveInterface.lock(); if (interface == nullptr) { ALOGE("%s: camera provider interface for %s is not valid", __FUNCTION__, mProviderName.c_str()); return INVALID_OPERATION; } return getConcurrentCameraIdsInternalLocked(interface); } status_t AidlProviderInfo::getConcurrentCameraIdsInternalLocked( std::shared_ptr &interface) { if (interface == nullptr) { ALOGE("%s: null interface provided", __FUNCTION__); return BAD_VALUE; } std::vector combs; ::ndk::ScopedAStatus status = interface->getConcurrentCameraIds(&combs); if (!status.isOk()) { ALOGE("%s: Transaction error in getting concurrent camera ID list from provider '%s'", __FUNCTION__, mProviderName.c_str()); return mapToStatusT(status); } mConcurrentCameraIdCombinations.clear(); for (const auto& combination : combs) { std::unordered_set deviceIds; for (const auto &cameraDeviceId : combination.combination) { deviceIds.insert(cameraDeviceId.c_str()); } mConcurrentCameraIdCombinations.push_back(std::move(deviceIds)); } return OK; } AidlProviderInfo::AidlDeviceInfo3::AidlDeviceInfo3( const std::string& name, const metadata_vendor_id_t tagId, const std::string &id, uint16_t minorVersion, const CameraResourceCost& resourceCost, sp parentProvider, const std::vector& publicCameraIds, std::shared_ptr interface) : DeviceInfo3(name, tagId, id, minorVersion, resourceCost, parentProvider, publicCameraIds) { // Get camera characteristics and initialize flash unit availability aidl::android::hardware::camera::device::CameraMetadata chars; ::ndk::ScopedAStatus status = interface->getCameraCharacteristics(&chars); std::vector &metadata = chars.metadata; camera_metadata_t *buffer = reinterpret_cast(metadata.data()); size_t expectedSize = metadata.size(); int resV = validate_camera_metadata_structure(buffer, &expectedSize); if (resV == OK || resV == CAMERA_METADATA_VALIDATION_SHIFTED) { set_camera_metadata_vendor_id(buffer, mProviderTagid); mCameraCharacteristics = buffer; } else { ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__); return; } if (!status.isOk()) { ALOGE("%s: Transaction error getting camera characteristics for device %s" " to check for a flash unit: %s", __FUNCTION__, id.c_str(), status.getMessage()); return; } if (mCameraCharacteristics.exists(ANDROID_INFO_DEVICE_STATE_ORIENTATIONS)) { const auto &stateMap = mCameraCharacteristics.find(ANDROID_INFO_DEVICE_STATE_ORIENTATIONS); if ((stateMap.count > 0) && ((stateMap.count % 2) == 0)) { for (size_t i = 0; i < stateMap.count; i += 2) { mDeviceStateOrientationMap.emplace(stateMap.data.i64[i], stateMap.data.i64[i+1]); } } else { ALOGW("%s: Invalid ANDROID_INFO_DEVICE_STATE_ORIENTATIONS map size: %zu", __FUNCTION__, stateMap.count); } } mSystemCameraKind = getSystemCameraKind(); status_t res = fixupMonochromeTags(); if (OK != res) { ALOGE("%s: Unable to fix up monochrome tags based for older HAL version: %s (%d)", __FUNCTION__, strerror(-res), res); return; } auto stat = addDynamicDepthTags(); if (OK != stat) { ALOGE("%s: Failed appending dynamic depth tags: %s (%d)", __FUNCTION__, strerror(-stat), stat); } res = deriveHeicTags(); if (OK != res) { ALOGE("%s: Unable to derive HEIC tags based on camera and media capabilities: %s (%d)", __FUNCTION__, strerror(-res), res); } if (camera3::SessionConfigurationUtils::isUltraHighResolutionSensor(mCameraCharacteristics)) { status_t status = addDynamicDepthTags(/*maxResolution*/true); if (OK != status) { ALOGE("%s: Failed appending dynamic depth tags for maximum resolution mode: %s (%d)", __FUNCTION__, strerror(-status), status); } status = deriveHeicTags(/*maxResolution*/true); if (OK != status) { ALOGE("%s: Unable to derive HEIC tags based on camera and media capabilities for" "maximum resolution mode: %s (%d)", __FUNCTION__, strerror(-status), status); } } res = addRotateCropTags(); if (OK != res) { ALOGE("%s: Unable to add default SCALER_ROTATE_AND_CROP tags: %s (%d)", __FUNCTION__, strerror(-res), res); } res = addPreCorrectionActiveArraySize(); if (OK != res) { ALOGE("%s: Unable to add PRE_CORRECTION_ACTIVE_ARRAY_SIZE: %s (%d)", __FUNCTION__, strerror(-res), res); } res = camera3::ZoomRatioMapper::overrideZoomRatioTags( &mCameraCharacteristics, &mSupportNativeZoomRatio); if (OK != res) { ALOGE("%s: Unable to override zoomRatio related tags: %s (%d)", __FUNCTION__, strerror(-res), res); } res = addReadoutTimestampTag(); if (OK != res) { ALOGE("%s: Unable to add sensorReadoutTimestamp tag: %s (%d)", __FUNCTION__, strerror(-res), res); } camera_metadata_entry flashAvailable = mCameraCharacteristics.find(ANDROID_FLASH_INFO_AVAILABLE); if (flashAvailable.count == 1 && flashAvailable.data.u8[0] == ANDROID_FLASH_INFO_AVAILABLE_TRUE) { mHasFlashUnit = true; // Fix up flash strength tags for devices without these keys. res = fixupTorchStrengthTags(); if (OK != res) { ALOGE("%s: Unable to add default ANDROID_FLASH_INFO_STRENGTH_DEFAULT_LEVEL and" "ANDROID_FLASH_INFO_STRENGTH_MAXIMUM_LEVEL tags: %s (%d)", __FUNCTION__, strerror(-res), res); } } else { mHasFlashUnit = false; } camera_metadata_entry entry = mCameraCharacteristics.find(ANDROID_FLASH_INFO_STRENGTH_DEFAULT_LEVEL); if (entry.count == 1) { mTorchDefaultStrengthLevel = entry.data.i32[0]; } else { mTorchDefaultStrengthLevel = 0; } entry = mCameraCharacteristics.find(ANDROID_FLASH_INFO_STRENGTH_MAXIMUM_LEVEL); if (entry.count == 1) { mTorchMaximumStrengthLevel = entry.data.i32[0]; } else { mTorchMaximumStrengthLevel = 0; } mTorchStrengthLevel = 0; queryPhysicalCameraIds(); // Get physical camera characteristics if applicable if (mIsLogicalCamera) { for (auto& id : mPhysicalIds) { if (std::find(mPublicCameraIds.begin(), mPublicCameraIds.end(), id) != mPublicCameraIds.end()) { continue; } aidl::android::hardware::camera::device::CameraMetadata pChars; status = interface->getPhysicalCameraCharacteristics(id, &pChars); if (!status.isOk()) { ALOGE("%s: Transaction error getting physical camera %s characteristics for %s: %s", __FUNCTION__, id.c_str(), id.c_str(), status.getMessage()); return; } std::vector &pMetadata = pChars.metadata; camera_metadata_t *pBuffer = reinterpret_cast(pMetadata.data()); size_t expectedSize = pMetadata.size(); int res = validate_camera_metadata_structure(pBuffer, &expectedSize); if (res == OK || res == CAMERA_METADATA_VALIDATION_SHIFTED) { set_camera_metadata_vendor_id(pBuffer, mProviderTagid); mPhysicalCameraCharacteristics[id] = pBuffer; } else { ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__); return; } res = camera3::ZoomRatioMapper::overrideZoomRatioTags( &mPhysicalCameraCharacteristics[id], &mSupportNativeZoomRatio); if (OK != res) { ALOGE("%s: Unable to override zoomRatio related tags: %s (%d)", __FUNCTION__, strerror(-res), res); } } } if (!kEnableLazyHal) { // Save HAL reference indefinitely mSavedInterface = interface; } } status_t AidlProviderInfo::AidlDeviceInfo3::setTorchMode(bool enabled) { const std::shared_ptr interface = startDeviceInterface(); ::ndk::ScopedAStatus s = interface->setTorchMode(enabled); if (!s.isOk()) { ALOGE("%s Unable to set torch mode: %s", __FUNCTION__, s.getMessage()); return mapToStatusT(s); } return OK; } status_t AidlProviderInfo::AidlDeviceInfo3::turnOnTorchWithStrengthLevel( int32_t torchStrength) { const std::shared_ptr interface = startDeviceInterface(); if (interface == nullptr) { return DEAD_OBJECT; } ::ndk::ScopedAStatus s = interface->turnOnTorchWithStrengthLevel(torchStrength); if (!s.isOk()) { ALOGE("%s Unable to set torch mode strength %d : %s", __FUNCTION__, torchStrength, s.getMessage()); return mapToStatusT(s); } mTorchStrengthLevel = torchStrength; return OK; } status_t AidlProviderInfo::AidlDeviceInfo3::getTorchStrengthLevel(int32_t *torchStrength) { if (torchStrength == nullptr) { return BAD_VALUE; } const std::shared_ptr interface = startDeviceInterface(); if (interface == nullptr) { return DEAD_OBJECT; } ::ndk::ScopedAStatus status = interface->getTorchStrengthLevel(torchStrength); if (!status.isOk()) { ALOGE("%s: Couldn't get torch strength level: %s", __FUNCTION__, status.getMessage()); return mapToStatusT(status); } return OK; } std::shared_ptr AidlProviderInfo::AidlDeviceInfo3::startDeviceInterface() { Mutex::Autolock l(mDeviceAvailableLock); std::shared_ptr device; ATRACE_CALL(); if (mSavedInterface == nullptr) { sp parentProvider = static_cast(mParentProvider.promote().get()); if (parentProvider != nullptr) { // Wait for lazy HALs to confirm device availability if (parentProvider->isExternalLazyHAL() && !mIsDeviceAvailable) { ALOGV("%s: Wait for external device to become available %s", __FUNCTION__, mId.c_str()); auto res = mDeviceAvailableSignal.waitRelative(mDeviceAvailableLock, kDeviceAvailableTimeout); if (res != OK) { ALOGE("%s: Failed waiting for device to become available", __FUNCTION__); return nullptr; } } device = parentProvider->startDeviceInterface(mName); } } else { device = mSavedInterface; } return device; } status_t AidlProviderInfo::AidlDeviceInfo3::dumpState(int fd) { const std::shared_ptr interface = startDeviceInterface(); if (interface == nullptr) { return DEAD_OBJECT; } const char *args = nullptr; auto ret = interface->dump(fd, &args, /*numArgs*/0); if (ret != OK) { return ret; } return OK; } status_t AidlProviderInfo::AidlDeviceInfo3::isSessionConfigurationSupported( const SessionConfiguration &configuration, bool overrideForPerfClass, camera3::metadataGetter getMetadata, bool *status) { camera::device::StreamConfiguration streamConfiguration; bool earlyExit = false; auto bRes = SessionConfigurationUtils::convertToHALStreamCombination(configuration, String8(mId.c_str()), mCameraCharacteristics, getMetadata, mPhysicalIds, streamConfiguration, overrideForPerfClass, &earlyExit); if (!bRes.isOk()) { return UNKNOWN_ERROR; } if (earlyExit) { *status = false; return OK; } const std::shared_ptr interface = startDeviceInterface(); if (interface == nullptr) { return DEAD_OBJECT; } ::ndk::ScopedAStatus ret = interface->isStreamCombinationSupported(streamConfiguration, status); if (!ret.isOk()) { *status = false; ALOGE("%s: Unexpected binder error: %s", __FUNCTION__, ret.getMessage()); return mapToStatusT(ret); } return OK; } status_t AidlProviderInfo::convertToAidlHALStreamCombinationAndCameraIdsLocked( const std::vector &cameraIdsAndSessionConfigs, const std::set& perfClassPrimaryCameraIds, int targetSdkVersion, std::vector *halCameraIdsAndStreamCombinations, bool *earlyExit) { binder::Status bStatus = binder::Status::ok(); std::vector halCameraIdsAndStreamsV; bool shouldExit = false; status_t res = OK; for (auto &cameraIdAndSessionConfig : cameraIdsAndSessionConfigs) { const std::string& cameraId = cameraIdAndSessionConfig.mCameraId; camera::device::StreamConfiguration streamConfiguration; CameraMetadata deviceInfo; bool overrideForPerfClass = SessionConfigurationUtils::targetPerfClassPrimaryCamera( perfClassPrimaryCameraIds, cameraId, targetSdkVersion); res = mManager->getCameraCharacteristicsLocked(cameraId, overrideForPerfClass, &deviceInfo, /*overrideToPortrait*/false); if (res != OK) { return res; } camera3::metadataGetter getMetadata = [this](const String8 &id, bool overrideForPerfClass) { CameraMetadata physicalDeviceInfo; mManager->getCameraCharacteristicsLocked(id.string(), overrideForPerfClass, &physicalDeviceInfo, /*overrideToPortrait*/false); return physicalDeviceInfo; }; std::vector physicalCameraIds; mManager->isLogicalCameraLocked(cameraId, &physicalCameraIds); bStatus = SessionConfigurationUtils::convertToHALStreamCombination( cameraIdAndSessionConfig.mSessionConfiguration, String8(cameraId.c_str()), deviceInfo, getMetadata, physicalCameraIds, streamConfiguration, overrideForPerfClass, &shouldExit); if (!bStatus.isOk()) { ALOGE("%s: convertToHALStreamCombination failed", __FUNCTION__); return INVALID_OPERATION; } if (shouldExit) { *earlyExit = true; return OK; } camera::provider::CameraIdAndStreamCombination halCameraIdAndStream; halCameraIdAndStream.cameraId = cameraId; halCameraIdAndStream.streamConfiguration = streamConfiguration; halCameraIdsAndStreamsV.push_back(halCameraIdAndStream); } *halCameraIdsAndStreamCombinations = halCameraIdsAndStreamsV; return OK; } status_t AidlProviderInfo::isConcurrentSessionConfigurationSupported( const std::vector &cameraIdsAndSessionConfigs, const std::set& perfClassPrimaryCameraIds, int targetSdkVersion, bool *isSupported) { std::vector halCameraIdsAndStreamCombinations; bool knowUnsupported = false; status_t res = convertToAidlHALStreamCombinationAndCameraIdsLocked( cameraIdsAndSessionConfigs, perfClassPrimaryCameraIds, targetSdkVersion, &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; } // Check if the provider is currently active - not going to start it up for this notification auto interface = mSavedInterface != nullptr ? mSavedInterface : mActiveInterface.lock(); if (interface == nullptr) { // TODO: This might be some other problem return INVALID_OPERATION; } ::ndk::ScopedAStatus status = interface->isConcurrentStreamCombinationSupported( halCameraIdsAndStreamCombinations, isSupported); if (!status.isOk()) { *isSupported = false; ALOGE("%s: hal interface session configuration query failed", __FUNCTION__); return mapToStatusT(status); } return OK; } } //namespace android