/* * Copyright 2023 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 "VirtualCameraProvider" #include "VirtualCameraProvider.h" #include #include #include #include #include #include "VirtualCameraDevice.h" #include "aidl/android/hardware/camera/common/Status.h" #include "log/log.h" #include "util/Util.h" namespace android { namespace companion { namespace virtualcamera { using ::aidl::android::companion::virtualcamera::VirtualCameraConfiguration; using ::aidl::android::hardware::camera::common::CameraDeviceStatus; using ::aidl::android::hardware::camera::common::Status; using ::aidl::android::hardware::camera::common::VendorTagSection; using ::aidl::android::hardware::camera::device::ICameraDevice; using ::aidl::android::hardware::camera::provider::CameraIdAndStreamCombination; using ::aidl::android::hardware::camera::provider::ConcurrentCameraIdCombination; using ::aidl::android::hardware::camera::provider::ICameraProviderCallback; ndk::ScopedAStatus VirtualCameraProvider::setCallback( const std::shared_ptr& in_callback) { ALOGV("%s", __func__); if (in_callback == nullptr) { return cameraStatus(Status::ILLEGAL_ARGUMENT); } { const std::lock_guard lock(mLock); mCameraProviderCallback = in_callback; for (const auto& [cameraName, _] : mCameras) { auto ret = mCameraProviderCallback->cameraDeviceStatusChange( cameraName, CameraDeviceStatus::PRESENT); if (!ret.isOk()) { ALOGE("Failed to announce camera status change: %s", ret.getDescription().c_str()); } } } return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus VirtualCameraProvider::getVendorTags( std::vector* _aidl_return) { ALOGV("%s", __func__); if (_aidl_return == nullptr) { return cameraStatus(Status::ILLEGAL_ARGUMENT); } // No vendor tags supported. _aidl_return->clear(); return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus VirtualCameraProvider::getCameraIdList( std::vector* _aidl_return) { ALOGV("%s", __func__); if (_aidl_return == nullptr) { return cameraStatus(Status::ILLEGAL_ARGUMENT); } { const std::lock_guard lock(mLock); _aidl_return->clear(); _aidl_return->reserve(mCameras.size()); for (const auto& [cameraName, _] : mCameras) { _aidl_return->emplace_back(cameraName); } } return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus VirtualCameraProvider::getCameraDeviceInterface( const std::string& in_cameraDeviceName, std::shared_ptr* _aidl_return) { ALOGV("%s cameraDeviceName %s", __func__, in_cameraDeviceName.c_str()); if (_aidl_return == nullptr) { return cameraStatus(Status::ILLEGAL_ARGUMENT); } { const std::lock_guard lock(mLock); const auto it = mCameras.find(in_cameraDeviceName); *_aidl_return = (it == mCameras.end()) ? nullptr : it->second; } return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus VirtualCameraProvider::notifyDeviceStateChange( int64_t in_deviceState) { ALOGV("%s", __func__); (void)in_deviceState; return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus VirtualCameraProvider::getConcurrentCameraIds( std::vector* _aidl_return) { ALOGV("%s", __func__); if (_aidl_return == nullptr) { return cameraStatus(Status::ILLEGAL_ARGUMENT); } // No support for any concurrent combination. _aidl_return->clear(); return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus VirtualCameraProvider::isConcurrentStreamCombinationSupported( const std::vector& in_configs, bool* _aidl_return) { ALOGV("%s", __func__); (void)in_configs; if (_aidl_return == nullptr) { return cameraStatus(Status::ILLEGAL_ARGUMENT); } // No support for any stream combination at the moment. *_aidl_return = false; return ndk::ScopedAStatus::ok(); } std::shared_ptr VirtualCameraProvider::createCamera( const VirtualCameraConfiguration& configuration, const std::string& cameraId, const int32_t deviceId) { if (cameraId.empty()) { ALOGE("%s: Cannot create camera with empty cameraId", __func__); return nullptr; } auto camera = ndk::SharedRefBase::make( cameraId, configuration, deviceId); std::shared_ptr callback; { const std::lock_guard lock(mLock); if (mCameras.find(camera->getCameraName()) != mCameras.end()) { ALOGE("Camera with identical name already exists."); return nullptr; } mCameras.emplace(std::piecewise_construct, std::forward_as_tuple(camera->getCameraName()), std::forward_as_tuple(camera)); callback = mCameraProviderCallback; } if (callback != nullptr) { auto ret = callback->cameraDeviceStatusChange(camera->getCameraName(), CameraDeviceStatus::PRESENT); if (!ret.isOk()) { ALOGE("Failed to announce camera %s status change (PRESENT): %s", camera->getCameraName().c_str(), ret.getDescription().c_str()); } } return camera; } std::shared_ptr VirtualCameraProvider::getCamera( const std::string& cameraName) { const std::lock_guard lock(mLock); auto it = mCameras.find(cameraName); return it == mCameras.end() ? nullptr : it->second; } bool VirtualCameraProvider::removeCamera(const std::string& name) { std::shared_ptr callback; { const std::lock_guard lock(mLock); auto it = mCameras.find(name); if (it == mCameras.end()) { ALOGE("Cannot remove camera %s: no such camera", name.c_str()); return false; } // TODO(b/301023410) Gracefully shut down camera. mCameras.erase(it); callback = mCameraProviderCallback; } if (callback != nullptr) { auto ret = callback->cameraDeviceStatusChange( name, CameraDeviceStatus::NOT_PRESENT); if (!ret.isOk()) { ALOGE("Failed to announce camera %s status change (NOT_PRESENT): %s", name.c_str(), ret.getDescription().c_str()); } } return true; } } // namespace virtualcamera } // namespace companion } // namespace android