/* * 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. */ #define LOG_TAG "GCH_AidlCameraProvider" //#define LOG_NDEBUG 0 #include "aidl_camera_provider.h" #include <log/log.h> #include <regex> #include "aidl_camera_device.h" #include "aidl_utils.h" #include "camera_device.h" namespace android { namespace hardware { namespace camera { namespace provider { namespace implementation { namespace aidl_utils = ::android::hardware::camera::implementation::aidl_utils; using aidl::android::hardware::camera::common::CameraDeviceStatus; using aidl::android::hardware::camera::common::Status; using aidl::android::hardware::camera::common::TorchModeStatus; using aidl::android::hardware::camera::common::VendorTagSection; using ::android::google_camera_hal::CameraDevice; const std::string AidlCameraProvider::kProviderName = "internal"; // "device@<version>/internal/<id>" const std::regex AidlCameraProvider::kDeviceNameRegex( "device@([0-9]+\\.[0-9]+)/internal/(.+)"); std::shared_ptr<AidlCameraProvider> AidlCameraProvider::Create() { std::shared_ptr<AidlCameraProvider> provider = ndk::SharedRefBase::make<AidlCameraProvider>(); status_t res = provider->Initialize(); if (res != OK) { ALOGE("%s: Initializing AidlCameraProvider failed: %s(%d)", __FUNCTION__, strerror(-res), res); return nullptr; } return provider; } status_t AidlCameraProvider::Initialize() { google_camera_provider_ = CameraProvider::Create(); if (google_camera_provider_ == nullptr) { ALOGE("%s: Creating CameraProvider failed.", __FUNCTION__); return NO_INIT; } camera_provider_callback_ = { .camera_device_status_change = google_camera_hal::CameraDeviceStatusChangeFunc( [this](std::string camera_id, google_camera_hal::CameraDeviceStatus new_status) { if (callbacks_ == nullptr) { ALOGE("%s: callbacks_ is null", __FUNCTION__); return; } CameraDeviceStatus aidl_camera_device_status; status_t res = aidl_utils::ConvertToAidlCameraDeviceStatus( new_status, &aidl_camera_device_status); if (res != OK) { ALOGE( "%s: Converting to aidl camera device status failed: %s(%d)", __FUNCTION__, strerror(-res), res); return; } std::unique_lock<std::mutex> lock(callbacks_lock_); auto aidl_res = callbacks_->cameraDeviceStatusChange( "device@" + device::implementation::AidlCameraDevice::kDeviceVersion + "/" + kProviderName + "/" + camera_id, aidl_camera_device_status); if (!aidl_res.isOk()) { ALOGE("%s: device status change transaction error: %s", __FUNCTION__, aidl_res.getMessage()); return; } }), .physical_camera_device_status_change = google_camera_hal::PhysicalCameraDeviceStatusChangeFunc( [this](std::string camera_id, std::string physical_camera_id, google_camera_hal::CameraDeviceStatus new_status) { if (callbacks_ == nullptr) { ALOGE("%s: callbacks_ is null", __FUNCTION__); return; } /*auto castResult = provider::V2_6::ICameraProviderCallback::castFrom(callbacks_); if (!castResult.isOk()) { ALOGE("%s: callbacks_ cannot be casted to version 2.6", __FUNCTION__); return; } sp<provider::V2_6::ICameraProviderCallback> callbacks_2_6_ = castResult; if (callbacks_2_6_ == nullptr) { ALOGE("%s: callbacks_2_6_ is null", __FUNCTION__); return; }*/ CameraDeviceStatus aidl_camera_device_status; status_t res = aidl_utils::ConvertToAidlCameraDeviceStatus( new_status, &aidl_camera_device_status); if (res != OK) { ALOGE( "%s: Converting to aidl camera device status failed: " "%s(%d)", __FUNCTION__, strerror(-res), res); return; } std::unique_lock<std::mutex> lock(callbacks_lock_); auto aidl_res = callbacks_->physicalCameraDeviceStatusChange( "device@" + device::implementation::AidlCameraDevice::kDeviceVersion + "/" + kProviderName + "/" + camera_id, physical_camera_id, aidl_camera_device_status); if (!aidl_res.isOk()) { ALOGE( "%s: physical camera status change transaction error: %s", __FUNCTION__, aidl_res.getMessage()); return; } }), .torch_mode_status_change = google_camera_hal::TorchModeStatusChangeFunc( [this](std::string camera_id, google_camera_hal::TorchModeStatus new_status) { if (callbacks_ == nullptr) { ALOGE("%s: callbacks_ is null", __FUNCTION__); return; } TorchModeStatus aidl_torch_status; status_t res = aidl_utils::ConvertToAidlTorchModeStatus( new_status, &aidl_torch_status); if (res != OK) { ALOGE("%s: Converting to aidl torch status failed: %s(%d)", __FUNCTION__, strerror(-res), res); return; } std::unique_lock<std::mutex> lock(callbacks_lock_); auto aidl_res = callbacks_->torchModeStatusChange( "device@" + device::implementation::AidlCameraDevice::kDeviceVersion + "/" + kProviderName + "/" + camera_id, aidl_torch_status); if (!aidl_res.isOk()) { ALOGE("%s: torch status change transaction error: %s", __FUNCTION__, aidl_res.getMessage()); return; } }), }; google_camera_provider_->SetCallback(&camera_provider_callback_); // purge pending malloc pages after initialization mallopt(M_PURGE, 0); return OK; } ScopedAStatus AidlCameraProvider::setCallback( const std::shared_ptr<ICameraProviderCallback>& callback) { if (callback == nullptr) { ALOGE("AidlCameraProvider::setCallback() called with nullptr"); return ScopedAStatus::fromServiceSpecificError( static_cast<int32_t>(Status::ILLEGAL_ARGUMENT)); } bool first_time = false; { std::unique_lock<std::mutex> lock(callbacks_lock_); first_time = callbacks_ == nullptr; callbacks_ = callback; } google_camera_provider_->TriggerDeferredCallbacks(); #ifdef __ANDROID_APEX__ if (first_time) { std::string ready_property_name = "vendor.camera.hal.ready.count"; int ready_count = property_get_int32(ready_property_name.c_str(), 0); property_set(ready_property_name.c_str(), std::to_string(++ready_count).c_str()); ALOGI("AidlCameraProvider::setCallback() first time ready count: %d ", ready_count); } #endif return ScopedAStatus::ok(); } ScopedAStatus AidlCameraProvider::getVendorTags( std::vector<VendorTagSection>* vts) { if (vts == nullptr) { return ScopedAStatus::fromServiceSpecificError( static_cast<int32_t>(Status::ILLEGAL_ARGUMENT)); } vts->clear(); std::vector<google_camera_hal::VendorTagSection> hal_vendor_tag_sections; status_t res = google_camera_provider_->GetVendorTags(&hal_vendor_tag_sections); if (res != OK) { ALOGE("%s: Getting vendor tags failed: %s(%d)", __FUNCTION__, strerror(-res), res); return ScopedAStatus::fromServiceSpecificError( static_cast<int32_t>(Status::INTERNAL_ERROR)); } res = aidl_utils::ConvertToAidlVendorTagSections(hal_vendor_tag_sections, vts); if (res != OK) { ALOGE("%s: Converting to aidl vendor tags failed: %s(%d)", __FUNCTION__, strerror(-res), res); return ScopedAStatus::fromServiceSpecificError( static_cast<int32_t>(Status::INTERNAL_ERROR)); } return ScopedAStatus::ok(); } ScopedAStatus AidlCameraProvider::getCameraIdList( std::vector<std::string>* camera_ids_ret) { if (camera_ids_ret == nullptr) { return ScopedAStatus::fromServiceSpecificError( static_cast<int32_t>(Status::ILLEGAL_ARGUMENT)); } camera_ids_ret->clear(); std::vector<uint32_t> camera_ids; status_t res = google_camera_provider_->GetCameraIdList(&camera_ids); if (res != OK) { ALOGE("%s: Getting camera ID list failed: %s(%d)", __FUNCTION__, strerror(-res), res); return ScopedAStatus::fromServiceSpecificError( static_cast<int32_t>(Status::INTERNAL_ERROR)); } camera_ids_ret->resize(camera_ids.size()); for (uint32_t i = 0; i < camera_ids_ret->size(); i++) { // camera ID is in the form of "device@<major>.<minor>/<type>/<id>" (*camera_ids_ret)[i] = "device@" + device::implementation::AidlCameraDevice::kDeviceVersion + "/" + kProviderName + "/" + std::to_string(camera_ids[i]); } return ScopedAStatus::ok(); } ScopedAStatus AidlCameraProvider::getConcurrentCameraIds( std::vector<ConcurrentCameraIdCombination>* aidl_camera_id_combinations) { if (aidl_camera_id_combinations == nullptr) { return ScopedAStatus::fromServiceSpecificError( static_cast<int32_t>(Status::ILLEGAL_ARGUMENT)); } aidl_camera_id_combinations->clear(); std::vector<std::unordered_set<uint32_t>> camera_id_combinations; status_t res = google_camera_provider_->GetConcurrentStreamingCameraIds( &camera_id_combinations); if (res != OK) { ALOGE( "%s: Getting the combinations of concurrent streaming camera ids " "failed: %s(%d)", __FUNCTION__, strerror(-res), res); return ScopedAStatus::fromServiceSpecificError( static_cast<int32_t>(Status::INTERNAL_ERROR)); } aidl_camera_id_combinations->resize(camera_id_combinations.size()); int i = 0; for (auto& combination : camera_id_combinations) { std::vector<std::string> aidl_combination(combination.size()); int c = 0; for (auto& camera_id : combination) { aidl_combination[c] = std::to_string(camera_id); c++; } (*aidl_camera_id_combinations)[i].combination = aidl_combination; i++; } return ScopedAStatus::ok(); } ScopedAStatus AidlCameraProvider::isConcurrentStreamCombinationSupported( const std::vector<CameraIdAndStreamCombination>& configs, bool* supported) { *supported = false; std::vector<google_camera_hal::CameraIdAndStreamConfiguration> devices_stream_configs(configs.size()); status_t res = OK; size_t c = 0; std::vector<CameraIdAndStreamCombination> configsWithOverriddenSensorPixelModes = configs; for (auto& config : configsWithOverriddenSensorPixelModes) { aidl_utils::FixSensorPixelModesInStreamConfig(&config.streamConfiguration); } for (auto& config : configsWithOverriddenSensorPixelModes) { res = aidl_utils::ConvertToHalStreamConfig( config.streamConfiguration, &devices_stream_configs[c].stream_configuration); if (res != OK) { ALOGE("%s: ConverToHalStreamConfig failed", __FUNCTION__); return ScopedAStatus::fromServiceSpecificError( static_cast<int32_t>(Status::INTERNAL_ERROR)); } uint32_t camera_id = atoi(config.cameraId.c_str()); devices_stream_configs[c].camera_id = camera_id; c++; } res = google_camera_provider_->IsConcurrentStreamCombinationSupported( devices_stream_configs, supported); if (res != OK) { ALOGE("%s: IsConcurrentStreamCombinationSupported failed", __FUNCTION__); return ScopedAStatus::fromServiceSpecificError( static_cast<int32_t>(Status::INTERNAL_ERROR)); } return ScopedAStatus::ok(); } bool AidlCameraProvider::ParseDeviceName(const std::string& device_name, std::string* device_version, std::string* camera_id) { std::string device_name_std(device_name.c_str()); std::smatch sm; if (std::regex_match(device_name_std, sm, AidlCameraProvider::kDeviceNameRegex)) { if (device_version != nullptr) { *device_version = sm[1]; } if (camera_id != nullptr) { *camera_id = sm[2]; } return true; } return false; } ScopedAStatus AidlCameraProvider::getCameraDeviceInterface( const std::string& camera_device_name, std::shared_ptr<ICameraDevice>* device) { std::unique_ptr<CameraDevice> google_camera_device; if (device == nullptr) { ALOGE("%s: device is nullptr. ", __FUNCTION__); return ScopedAStatus::fromServiceSpecificError( static_cast<int32_t>(Status::ILLEGAL_ARGUMENT)); } // Parse camera_device_name. std::string camera_id, device_version; bool match = ParseDeviceName(camera_device_name, &device_version, &camera_id); if (!match) { ALOGE("%s: Device name parse fail. ", __FUNCTION__); return ScopedAStatus::fromServiceSpecificError( static_cast<int32_t>(Status::ILLEGAL_ARGUMENT)); } status_t res = google_camera_provider_->CreateCameraDevice( atoi(camera_id.c_str()), &google_camera_device); if (res != OK) { ALOGE("%s: Creating CameraDevice failed: %s(%d)", __FUNCTION__, strerror(-res), res); return aidl_utils::ConvertToAidlReturn(res); } *device = device::implementation::AidlCameraDevice::Create( std::move(google_camera_device)); if (*device == nullptr) { ALOGE("%s: Creating AidlCameraDevice failed", __FUNCTION__); return ScopedAStatus::fromServiceSpecificError( static_cast<int32_t>(Status::INTERNAL_ERROR)); } return ScopedAStatus::ok(); } ScopedAStatus AidlCameraProvider::notifyDeviceStateChange(int64_t new_state) { google_camera_hal::DeviceState device_state = google_camera_hal::DeviceState::kNormal; ::android::hardware::camera::implementation::aidl_utils::ConvertToHalDeviceState( new_state, device_state); google_camera_provider_->NotifyDeviceStateChange(device_state); return ScopedAStatus::ok(); } } // namespace implementation } // namespace provider } // namespace camera } // namespace hardware } // namespace android