diff options
Diffstat (limited to 'common/hal/aidl_service/aidl_camera_device_session.cc')
-rw-r--r-- | common/hal/aidl_service/aidl_camera_device_session.cc | 805 |
1 files changed, 805 insertions, 0 deletions
diff --git a/common/hal/aidl_service/aidl_camera_device_session.cc b/common/hal/aidl_service/aidl_camera_device_session.cc new file mode 100644 index 0000000..9af6de1 --- /dev/null +++ b/common/hal/aidl_service/aidl_camera_device_session.cc @@ -0,0 +1,805 @@ +/* + * 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_AidlCameraDeviceSession" +#define ATRACE_TAG ATRACE_TAG_CAMERA +//#define LOG_NDEBUG 0 +#include "aidl_camera_device_session.h" + +#include <cutils/properties.h> +#include <cutils/trace.h> +#include <log/log.h> +#include <malloc.h> +#include <utils/Trace.h> + +#include "aidl_profiler.h" +#include "aidl_utils.h" +namespace android { +namespace hardware { +namespace camera { +namespace device { +namespace implementation { + +namespace aidl_utils = ::android::hardware::camera::implementation::aidl_utils; + +using aidl::android::hardware::camera::common::Status; +using aidl::android::hardware::camera::device::BufferRequest; +using aidl::android::hardware::camera::device::BufferRequestStatus; +using aidl::android::hardware::camera::device::CaptureResult; +using aidl::android::hardware::camera::device::HalStream; +using aidl::android::hardware::camera::device::NotifyMsg; +using aidl::android::hardware::camera::device::StreamBuffer; +using aidl::android::hardware::camera::device::StreamBufferRet; +using aidl::android::hardware::camera::device::StreamBuffersVal; +using aidl_utils::ConvertToAidlReturn; +using ::android::hardware::thermal::V1_0::ThermalStatus; +using ::android::hardware::thermal::V1_0::ThermalStatusCode; +using ::android::hardware::thermal::V2_0::Temperature; +using ::android::hardware::thermal::V2_0::TemperatureType; + +std::shared_ptr<AidlCameraDeviceSession> AidlCameraDeviceSession::Create( + const std::shared_ptr<ICameraDeviceCallback>& callback, + std::unique_ptr<google_camera_hal::CameraDeviceSession> device_session, + std::shared_ptr<AidlProfiler> aidl_profiler) { + ATRACE_NAME("AidlCameraDeviceSession::Create"); + auto session = ndk::SharedRefBase::make<AidlCameraDeviceSession>(); + if (session == nullptr) { + ALOGE("%s: Cannot create a AidlCameraDeviceSession.", __FUNCTION__); + return nullptr; + } + + status_t res = + session->Initialize(callback, std::move(device_session), aidl_profiler); + if (res != OK) { + ALOGE("%s: Initializing AidlCameraDeviceSession failed: %s(%d)", + __FUNCTION__, strerror(-res), res); + return nullptr; + } + + return session; +} + +AidlCameraDeviceSession::~AidlCameraDeviceSession() { + ATRACE_NAME("AidlCameraDeviceSession::~AidlCameraDeviceSession"); + close(); + // camera's closing, so flush any unused malloc pages + mallopt(M_PURGE, 0); +} + +void AidlCameraDeviceSession::ProcessCaptureResult( + std::unique_ptr<google_camera_hal::CaptureResult> hal_result) { + std::shared_lock lock(aidl_device_callback_lock_); + if (aidl_device_callback_ == nullptr) { + ALOGE("%s: aidl_device_callback_ is nullptr", __FUNCTION__); + return; + } + + { + std::lock_guard<std::mutex> pending_lock(pending_first_frame_buffers_mutex_); + if (!hal_result->output_buffers.empty() && + num_pending_first_frame_buffers_ > 0 && + first_request_frame_number_ == hal_result->frame_number) { + num_pending_first_frame_buffers_ -= hal_result->output_buffers.size(); + if (num_pending_first_frame_buffers_ == 0) { + ALOGI("%s: First frame done", __FUNCTION__); + aidl_profiler_->FirstFrameEnd(); + ATRACE_ASYNC_END("first_frame", 0); + ATRACE_ASYNC_END("switch_mode", 0); + } + } + } + for (auto& buffer : hal_result->output_buffers) { + aidl_profiler_->ProfileFrameRate("Stream " + + std::to_string(buffer.stream_id)); + } + + std::vector<CaptureResult> aidl_results(1); + status_t res = aidl_utils::ConvertToAidlCaptureResult( + result_metadata_queue_.get(), std::move(hal_result), &aidl_results[0]); + if (res != OK) { + ALOGE("%s: Converting to AIDL result failed: %s(%d)", __FUNCTION__, + strerror(-res), res); + return; + } + + auto aidl_res = aidl_device_callback_->processCaptureResult(aidl_results); + if (!aidl_res.isOk()) { + ALOGE("%s: processCaptureResult transaction failed: %s.", __FUNCTION__, + aidl_res.getMessage()); + return; + } +} + +void AidlCameraDeviceSession::NotifyHalMessage( + const google_camera_hal::NotifyMessage& hal_message) { + std::shared_lock lock(aidl_device_callback_lock_); + if (aidl_device_callback_ == nullptr) { + ALOGE("%s: aidl_device_callback_ is nullptr", __FUNCTION__); + return; + } + + std::vector<NotifyMsg> aidl_messages(1); + status_t res = + aidl_utils::ConverToAidlNotifyMessage(hal_message, &aidl_messages[0]); + if (res != OK) { + ALOGE("%s: Converting to AIDL message failed: %s(%d)", __FUNCTION__, + strerror(-res), res); + return; + } + + auto aidl_res = aidl_device_callback_->notify(aidl_messages); + if (!aidl_res.isOk()) { + ALOGE("%s: notify transaction failed: %s.", __FUNCTION__, + aidl_res.getMessage()); + return; + } +} + +static void cleanupHandles(std::vector<native_handle_t*>& handles_to_delete) { + for (auto& handle : handles_to_delete) { + native_handle_delete(handle); + } +} + +google_camera_hal::BufferRequestStatus +AidlCameraDeviceSession::RequestStreamBuffers( + const std::vector<google_camera_hal::BufferRequest>& hal_buffer_requests, + std::vector<google_camera_hal::BufferReturn>* hal_buffer_returns) { + std::shared_lock lock(aidl_device_callback_lock_); + if (aidl_device_callback_ == nullptr) { + ALOGE("%s: aidl_device_callback_ is nullptr", __FUNCTION__); + return google_camera_hal::BufferRequestStatus::kFailedUnknown; + } + + if (hal_buffer_returns == nullptr) { + ALOGE("%s: hal_buffer_returns is nullptr", __FUNCTION__); + return google_camera_hal::BufferRequestStatus::kFailedUnknown; + } + + std::vector<BufferRequest> aidl_buffer_requests; + status_t res = aidl_utils::ConvertToAidlBufferRequest(hal_buffer_requests, + &aidl_buffer_requests); + if (res != OK) { + ALOGE("%s: Converting to Aidl buffer request failed: %s(%d)", __FUNCTION__, + strerror(-res), res); + return google_camera_hal::BufferRequestStatus::kFailedUnknown; + } + + BufferRequestStatus aidl_status; + std::vector<StreamBufferRet> stream_buffer_returns; + auto cb_status = aidl_device_callback_->requestStreamBuffers( + aidl_buffer_requests, &stream_buffer_returns, &aidl_status); + + if (!cb_status.isOk()) { + ALOGE("%s: Transaction request stream buffers error: %s", __FUNCTION__, + cb_status.getMessage()); + return google_camera_hal::BufferRequestStatus::kFailedUnknown; + } + + google_camera_hal::BufferRequestStatus hal_buffer_request_status; + res = aidl_utils::ConvertToHalBufferRequestStatus(aidl_status, + &hal_buffer_request_status); + if (res != OK) { + ALOGE("%s: Converting to Hal buffer request status failed: %s(%d)", + __FUNCTION__, strerror(-res), res); + return google_camera_hal::BufferRequestStatus::kFailedUnknown; + } + + hal_buffer_returns->clear(); + // Converting AIDL stream buffer returns to HAL stream buffer returns. + for (auto& stream_buffer_return : stream_buffer_returns) { + google_camera_hal::BufferReturn hal_buffer_return; + res = aidl_utils::ConvertToHalBufferReturnStatus(stream_buffer_return, + &hal_buffer_return); + if (res != OK) { + ALOGE("%s: Converting to Hal buffer return status failed: %s(%d)", + __FUNCTION__, strerror(-res), res); + return google_camera_hal::BufferRequestStatus::kFailedUnknown; + } + + using Tag = aidl::android::hardware::camera::device::StreamBuffersVal::Tag; + if (stream_buffer_return.val.getTag() == Tag::buffers) { + const std::vector<StreamBuffer>& aidl_buffers = + stream_buffer_return.val.get<Tag::buffers>(); + std::vector<native_handle_t*> native_handles_to_delete; + for (auto& aidl_buffer : aidl_buffers) { + google_camera_hal::StreamBuffer hal_buffer = {}; + aidl_utils::ConvertToHalStreamBuffer(aidl_buffer, &hal_buffer, + &native_handles_to_delete); + if (res != OK) { + ALOGE("%s: Converting to Hal stream buffer failed: %s(%d)", + __FUNCTION__, strerror(-res), res); + return google_camera_hal::BufferRequestStatus::kFailedUnknown; + } + + if (!aidl_utils::IsAidlNativeHandleNull(aidl_buffer.acquireFence)) { + hal_buffer.acquire_fence = dupFromAidl(aidl_buffer.acquireFence); + if (hal_buffer.acquire_fence == nullptr) { + ALOGE("%s: Cloning Hal stream buffer acquire fence failed", + __FUNCTION__); + } + } + + hal_buffer.release_fence = nullptr; + // If buffer handle is not null, we need to import buffer handle and + // return to the caller. + if (!aidl_utils::IsAidlNativeHandleNull(aidl_buffer.buffer)) { + native_handle_t* aidl_buffer_native_handle = + makeFromAidl(aidl_buffer.buffer); + if (buffer_mapper_v4_ != nullptr) { + hal_buffer.buffer = ImportBufferHandle< + android::hardware::graphics::mapper::V4_0::IMapper, + android::hardware::graphics::mapper::V4_0::Error>( + buffer_mapper_v4_, aidl_buffer_native_handle); + } else if (buffer_mapper_v3_ != nullptr) { + hal_buffer.buffer = ImportBufferHandle< + android::hardware::graphics::mapper::V3_0::IMapper, + android::hardware::graphics::mapper::V3_0::Error>( + buffer_mapper_v3_, aidl_buffer_native_handle); + } else { + hal_buffer.buffer = ImportBufferHandle< + android::hardware::graphics::mapper::V2_0::IMapper, + android::hardware::graphics::mapper::V2_0::Error>( + buffer_mapper_v2_, aidl_buffer_native_handle); + } + native_handle_delete(aidl_buffer_native_handle); + } + + hal_buffer_return.val.buffers.push_back(hal_buffer); + } + + cleanupHandles(native_handles_to_delete); + } + + hal_buffer_returns->push_back(hal_buffer_return); + } + + return hal_buffer_request_status; +} + +template <class T, class U> +buffer_handle_t AidlCameraDeviceSession::ImportBufferHandle( + const sp<T> buffer_mapper_, const hidl_handle& buffer_hidl_handle) { + U mapper_error; + buffer_handle_t imported_buffer_handle; + + auto hidl_res = buffer_mapper_->importBuffer( + buffer_hidl_handle, [&](const auto& error, const auto& buffer_handle) { + mapper_error = error; + imported_buffer_handle = static_cast<buffer_handle_t>(buffer_handle); + }); + if (!hidl_res.isOk() || mapper_error != U::NONE) { + ALOGE("%s: Importing buffer failed: %s, mapper error %u", __FUNCTION__, + hidl_res.description().c_str(), mapper_error); + return nullptr; + } + + return imported_buffer_handle; +} + +void AidlCameraDeviceSession::ReturnStreamBuffers( + const std::vector<google_camera_hal::StreamBuffer>& return_hal_buffers) { + std::shared_lock lock(aidl_device_callback_lock_); + if (aidl_device_callback_ == nullptr) { + ALOGE("%s: aidl_device_callback_ is nullptr", __FUNCTION__); + return; + } + + status_t res = OK; + std::vector<StreamBuffer> aidl_return_buffers; + aidl_return_buffers.resize(return_hal_buffers.size()); + for (uint32_t i = 0; i < return_hal_buffers.size(); i++) { + res = aidl_utils::ConvertToAidlStreamBuffer(return_hal_buffers[i], + &aidl_return_buffers[i]); + if (res != OK) { + ALOGE("%s: Converting to Aidl stream buffer failed: %s(%d)", __FUNCTION__, + strerror(-res), res); + return; + } + } + + auto aidl_res = + aidl_device_callback_->returnStreamBuffers(aidl_return_buffers); + if (!aidl_res.isOk()) { + ALOGE("%s: return stream buffers transaction failed: %s", __FUNCTION__, + aidl_res.getMessage()); + return; + } +} + +status_t AidlCameraDeviceSession::InitializeBufferMapper() { + buffer_mapper_v4_ = + android::hardware::graphics::mapper::V4_0::IMapper::getService(); + if (buffer_mapper_v4_ != nullptr) { + return OK; + } + + buffer_mapper_v3_ = + android::hardware::graphics::mapper::V3_0::IMapper::getService(); + if (buffer_mapper_v3_ != nullptr) { + return OK; + } + + buffer_mapper_v2_ = + android::hardware::graphics::mapper::V2_0::IMapper::getService(); + if (buffer_mapper_v2_ != nullptr) { + return OK; + } + + ALOGE("%s: Getting buffer mapper failed.", __FUNCTION__); + return UNKNOWN_ERROR; +} + +status_t AidlCameraDeviceSession::Initialize( + const std::shared_ptr<ICameraDeviceCallback>& callback, + std::unique_ptr<google_camera_hal::CameraDeviceSession> device_session, + std::shared_ptr<AidlProfiler> aidl_profiler) { + ATRACE_NAME("AidlCameraDeviceSession::Initialize"); + if (device_session == nullptr) { + ALOGE("%s: device_session is nullptr.", __FUNCTION__); + return BAD_VALUE; + } + + if (aidl_profiler == nullptr) { + ALOGE("%s: aidl_profiler is nullptr.", __FUNCTION__); + return BAD_VALUE; + } + + status_t res = CreateMetadataQueue(&request_metadata_queue_, + kRequestMetadataQueueSizeBytes, + "ro.vendor.camera.req.fmq.size"); + if (res != OK) { + ALOGE("%s: Creating request metadata queue failed: %s(%d)", __FUNCTION__, + strerror(-res), res); + return res; + } + + res = CreateMetadataQueue(&result_metadata_queue_, + kResultMetadataQueueSizeBytes, + "ro.vendor.camera.res.fmq.size"); + if (res != OK) { + ALOGE("%s: Creating result metadata queue failed: %s(%d)", __FUNCTION__, + strerror(-res), res); + return res; + } + + // Initialize buffer mapper + res = InitializeBufferMapper(); + if (res != OK) { + ALOGE("%s: Initialize buffer mapper failed: %s(%d)", __FUNCTION__, + strerror(-res), res); + return res; + } + + thermal_ = android::hardware::thermal::V2_0::IThermal::getService(); + if (thermal_ == nullptr) { + ALOGE("%s: Getting thermal failed.", __FUNCTION__); + // Continue without getting thermal information. + } + + aidl_device_callback_ = callback; + device_session_ = std::move(device_session); + aidl_profiler_ = aidl_profiler; + + SetSessionCallbacks(); + return OK; +} + +void AidlCameraDeviceSession::SetSessionCallbacks() { + google_camera_hal::CameraDeviceSessionCallback session_callback = { + .process_capture_result = google_camera_hal::ProcessCaptureResultFunc( + [this](std::unique_ptr<google_camera_hal::CaptureResult> result) { + ProcessCaptureResult(std::move(result)); + }), + .notify = google_camera_hal::NotifyFunc( + [this](const google_camera_hal::NotifyMessage& message) { + NotifyHalMessage(message); + }), + .request_stream_buffers = google_camera_hal::RequestStreamBuffersFunc( + [this]( + const std::vector<google_camera_hal::BufferRequest>& + hal_buffer_requests, + std::vector<google_camera_hal::BufferReturn>* hal_buffer_returns) { + return RequestStreamBuffers(hal_buffer_requests, hal_buffer_returns); + }), + .return_stream_buffers = google_camera_hal::ReturnStreamBuffersFunc( + [this](const std::vector<google_camera_hal::StreamBuffer>& + return_hal_buffers) { + ReturnStreamBuffers(return_hal_buffers); + }), + }; + + google_camera_hal::ThermalCallback thermal_callback = { + .register_thermal_changed_callback = + google_camera_hal::RegisterThermalChangedCallbackFunc( + [this](google_camera_hal::NotifyThrottlingFunc notify_throttling, + bool filter_type, google_camera_hal::TemperatureType type) { + return RegisterThermalChangedCallback(notify_throttling, + filter_type, type); + }), + .unregister_thermal_changed_callback = + google_camera_hal::UnregisterThermalChangedCallbackFunc( + [this]() { UnregisterThermalChangedCallback(); }), + }; + + device_session_->SetSessionCallback(session_callback, thermal_callback); +} + +status_t AidlCameraDeviceSession::RegisterThermalChangedCallback( + google_camera_hal::NotifyThrottlingFunc notify_throttling, bool filter_type, + google_camera_hal::TemperatureType type) { + std::lock_guard<std::mutex> lock(hidl_thermal_mutex_); + if (thermal_ == nullptr) { + ALOGE("%s: thermal was not initialized.", __FUNCTION__); + return NO_INIT; + } + + if (thermal_changed_callback_ != nullptr) { + ALOGE("%s: thermal changed callback is already registered.", __FUNCTION__); + return ALREADY_EXISTS; + } + + TemperatureType hidl_type; + status_t res = + hidl_thermal_utils::ConvertToHidlTemperatureType(type, &hidl_type); + if (res != OK) { + ALOGE("%s: Converting to HIDL type failed: %s(%d)", __FUNCTION__, + strerror(-res), res); + return res; + } + + std::unique_ptr<hidl_thermal_utils::HidlThermalChangedCallback> callback = + hidl_thermal_utils::HidlThermalChangedCallback::Create(notify_throttling); + thermal_changed_callback_ = callback.release(); + ThermalStatus thermal_status; + auto hidl_res = thermal_->registerThermalChangedCallback( + thermal_changed_callback_, filter_type, hidl_type, + [&](ThermalStatus status) { thermal_status = status; }); + if (!hidl_res.isOk() || thermal_status.code != ThermalStatusCode::SUCCESS) { + thermal_changed_callback_ = nullptr; + return UNKNOWN_ERROR; + } + + return OK; +} + +void AidlCameraDeviceSession::UnregisterThermalChangedCallback() { + std::lock_guard<std::mutex> lock(hidl_thermal_mutex_); + if (thermal_changed_callback_ == nullptr) { + // no-op if no thermal changed callback is registered. + return; + } + + if (thermal_ == nullptr) { + ALOGE("%s: thermal was not initialized.", __FUNCTION__); + return; + } + + ThermalStatus thermal_status; + auto hidl_res = thermal_->unregisterThermalChangedCallback( + thermal_changed_callback_, + [&](ThermalStatus status) { thermal_status = status; }); + if (!hidl_res.isOk() || thermal_status.code != ThermalStatusCode::SUCCESS) { + ALOGW("%s: Unregstering thermal callback failed: %s", __FUNCTION__, + thermal_status.debugMessage.c_str()); + } + + thermal_changed_callback_ = nullptr; +} + +status_t AidlCameraDeviceSession::CreateMetadataQueue( + std::unique_ptr<MetadataQueue>* metadata_queue, uint32_t default_size_bytes, + const char* override_size_property) { + if (metadata_queue == nullptr) { + ALOGE("%s: metadata_queue is nullptr", __FUNCTION__); + return BAD_VALUE; + } + + int32_t size = default_size_bytes; + if (override_size_property != nullptr) { + // Try to read the override size from the system property. + size = property_get_int32(override_size_property, default_size_bytes); + ALOGV("%s: request metadata queue size overridden to %d", __FUNCTION__, + size); + } + + *metadata_queue = + std::make_unique<MetadataQueue>(static_cast<size_t>(size), + /*configureEventFlagWord*/ false); + if (!(*metadata_queue)->isValid()) { + ALOGE("%s: Creating metadata queue (size %d) failed.", __FUNCTION__, size); + return NO_INIT; + } + + return OK; +} + +ScopedAStatus AidlCameraDeviceSession::constructDefaultRequestSettings( + RequestTemplate type, CameraMetadata* aidl_return) { + ATRACE_NAME("AidlCameraDeviceSession::constructDefaultRequestSettings"); + if (aidl_return == nullptr) { + return ScopedAStatus::fromServiceSpecificError( + static_cast<int32_t>(Status::ILLEGAL_ARGUMENT)); + } + aidl_return->metadata.clear(); + if (device_session_ == nullptr) { + return ScopedAStatus::fromServiceSpecificError( + static_cast<int32_t>(Status::INTERNAL_ERROR)); + } + + google_camera_hal::RequestTemplate hal_type; + status_t res = aidl_utils::ConvertToHalTemplateType(type, &hal_type); + if (res != OK) { + return ScopedAStatus::fromServiceSpecificError( + static_cast<int32_t>(Status::ILLEGAL_ARGUMENT)); + } + + std::unique_ptr<google_camera_hal::HalCameraMetadata> settings = nullptr; + res = device_session_->ConstructDefaultRequestSettings(hal_type, &settings); + if (res != OK) { + return aidl_utils::ConvertToAidlReturn(res); + } + + uint32_t metadata_size = settings->GetCameraMetadataSize(); + uint8_t* settings_p = (uint8_t*)settings->ReleaseCameraMetadata(); + aidl_return->metadata.assign(settings_p, settings_p + metadata_size); + return ScopedAStatus::ok(); +} + +ScopedAStatus AidlCameraDeviceSession::configureStreams( + const StreamConfiguration& requestedConfiguration, + std::vector<HalStream>* aidl_return) { + ATRACE_NAME("AidlCameraDeviceSession::configureStreams"); + if (aidl_return == nullptr) { + return ScopedAStatus::fromServiceSpecificError( + static_cast<int32_t>(Status::ILLEGAL_ARGUMENT)); + } + aidl_return->clear(); + if (device_session_ == nullptr) { + return ScopedAStatus::fromServiceSpecificError( + static_cast<int32_t>(Status::ILLEGAL_ARGUMENT)); + } + + auto profiler = aidl_profiler_->MakeScopedProfiler( + AidlProfiler::ScopedType::kConfigureStream, + device_session_->GetProfiler(aidl_profiler_->GetCameraId(), + aidl_profiler_->GetLatencyFlag()), + device_session_->GetProfiler(aidl_profiler_->GetCameraId(), + aidl_profiler_->GetFpsFlag())); + + first_frame_requested_ = false; + num_pending_first_frame_buffers_ = 0; + + google_camera_hal::StreamConfiguration hal_stream_config; + status_t res = aidl_utils::ConvertToHalStreamConfig(requestedConfiguration, + &hal_stream_config); + if (res != OK) { + return ScopedAStatus::fromServiceSpecificError( + static_cast<int32_t>(Status::ILLEGAL_ARGUMENT)); + } + + std::vector<google_camera_hal::HalStream> hal_configured_streams; + res = device_session_->ConfigureStreams(hal_stream_config, + &hal_configured_streams); + if (res != OK) { + ALOGE("%s: Configuring streams failed: %s(%d)", __FUNCTION__, + strerror(-res), res); + return aidl_utils::ConvertToAidlReturn(res); + } + + res = aidl_utils::ConvertToAidlHalStreamConfig(hal_configured_streams, + aidl_return); + if (res != OK) { + return aidl_utils::ConvertToAidlReturn(res); + } + return ScopedAStatus::ok(); +} + +ScopedAStatus AidlCameraDeviceSession::getCaptureRequestMetadataQueue( + ::aidl::android::hardware::common::fmq::MQDescriptor< + int8_t, SynchronizedReadWrite>* aidl_return) { + *aidl_return = request_metadata_queue_->dupeDesc(); + return ScopedAStatus::ok(); +} + +ScopedAStatus AidlCameraDeviceSession::getCaptureResultMetadataQueue( + ::aidl::android::hardware::common::fmq::MQDescriptor< + int8_t, SynchronizedReadWrite>* aidl_return) { + *aidl_return = result_metadata_queue_->dupeDesc(); + return ScopedAStatus::ok(); +} + +ScopedAStatus AidlCameraDeviceSession::processCaptureRequest( + const std::vector<CaptureRequest>& requests, + const std::vector<BufferCache>& cachesToRemove, int32_t* aidl_return) { + if (aidl_return == nullptr || device_session_ == nullptr) { + return ScopedAStatus::fromServiceSpecificError( + static_cast<int32_t>(Status::ILLEGAL_ARGUMENT)); + } + *aidl_return = 0; + bool profile_first_request = false; + if (!first_frame_requested_) { + first_frame_requested_ = true; + profile_first_request = true; + ATRACE_BEGIN("AidlCameraDeviceSession::FirstRequest"); + num_pending_first_frame_buffers_ = requests[0].outputBuffers.size(); + first_request_frame_number_ = requests[0].frameNumber; + aidl_profiler_->FirstFrameStart(); + ATRACE_ASYNC_BEGIN("first_frame", 0); + } + + std::vector<google_camera_hal::BufferCache> hal_buffer_caches; + + status_t res = + aidl_utils::ConvertToHalBufferCaches(cachesToRemove, &hal_buffer_caches); + if (res != OK) { + if (profile_first_request) { + ATRACE_END(); + } + return ScopedAStatus::fromServiceSpecificError( + static_cast<int32_t>(Status::ILLEGAL_ARGUMENT)); + } + + device_session_->RemoveBufferCache(hal_buffer_caches); + + // Converting AIDL requests to HAL requests. + std::vector<native_handle_t*> handles_to_delete; + std::vector<google_camera_hal::CaptureRequest> hal_requests; + for (auto& request : requests) { + google_camera_hal::CaptureRequest hal_request = {}; + res = aidl_utils::ConvertToHalCaptureRequest( + request, request_metadata_queue_.get(), &hal_request, + &handles_to_delete); + if (res != OK) { + ALOGE("%s: Converting to HAL capture request failed: %s(%d)", + __FUNCTION__, strerror(-res), res); + if (profile_first_request) { + ATRACE_END(); + } + cleanupHandles(handles_to_delete); + return aidl_utils::ConvertToAidlReturn(res); + } + + hal_requests.push_back(std::move(hal_request)); + } + + uint32_t num_processed_requests = 0; + res = device_session_->ProcessCaptureRequest(hal_requests, + &num_processed_requests); + if (res != OK) { + ALOGE( + "%s: Processing capture request failed: %s(%d). Only processed %u" + " out of %zu.", + __FUNCTION__, strerror(-res), res, num_processed_requests, + hal_requests.size()); + } + if (num_processed_requests > INT_MAX) { + cleanupHandles(handles_to_delete); + return ScopedAStatus::fromServiceSpecificError( + static_cast<int32_t>(Status::ILLEGAL_ARGUMENT)); + } + *aidl_return = (int32_t)num_processed_requests; + if (profile_first_request) { + ATRACE_END(); + } + cleanupHandles(handles_to_delete); + return aidl_utils::ConvertToAidlReturn(res); +} + +ScopedAStatus AidlCameraDeviceSession::signalStreamFlush( + const std::vector<int32_t>&, int32_t) { + // TODO(b/143902312): Implement this. + return ScopedAStatus::ok(); +} + +ScopedAStatus AidlCameraDeviceSession::flush() { + ATRACE_NAME("AidlCameraDeviceSession::flush"); + ATRACE_ASYNC_BEGIN("switch_mode", 0); + if (device_session_ == nullptr) { + return ScopedAStatus::fromServiceSpecificError( + static_cast<int32_t>(Status::INTERNAL_ERROR)); + } + + auto profiler = aidl_profiler_->MakeScopedProfiler( + AidlProfiler::ScopedType::kFlush, + device_session_->GetProfiler(aidl_profiler_->GetCameraId(), + aidl_profiler_->GetLatencyFlag()), + device_session_->GetProfiler(aidl_profiler_->GetCameraId(), + aidl_profiler_->GetFpsFlag())); + + status_t res = device_session_->Flush(); + if (res != OK) { + ALOGE("%s: Flushing device failed: %s(%d).", __FUNCTION__, strerror(-res), + res); + return ScopedAStatus::fromServiceSpecificError( + static_cast<int32_t>(Status::INTERNAL_ERROR)); + } + + return ScopedAStatus::ok(); +} + +ScopedAStatus AidlCameraDeviceSession::close() { + ATRACE_NAME("AidlCameraDeviceSession::close"); + if (device_session_ != nullptr) { + auto profiler = aidl_profiler_->MakeScopedProfiler( + AidlProfiler::ScopedType::kClose, + device_session_->GetProfiler(aidl_profiler_->GetCameraId(), + aidl_profiler_->GetLatencyFlag()), + device_session_->GetProfiler(aidl_profiler_->GetCameraId(), + aidl_profiler_->GetFpsFlag())); + device_session_ = nullptr; + } + return ScopedAStatus::ok(); +} + +ScopedAStatus AidlCameraDeviceSession::switchToOffline( + const std::vector<int32_t>&, + CameraOfflineSessionInfo* out_offlineSessionInfo, + std::shared_ptr<ICameraOfflineSession>* aidl_return) { + *out_offlineSessionInfo = CameraOfflineSessionInfo(); + *aidl_return = nullptr; + return ScopedAStatus::fromServiceSpecificError( + static_cast<int32_t>(Status::INTERNAL_ERROR)); +} + +ScopedAStatus AidlCameraDeviceSession::isReconfigurationRequired( + const CameraMetadata& oldSessionParams, + const CameraMetadata& newSessionParams, bool* reconfiguration_required) { + ATRACE_NAME("AidlCameraDeviceSession::isReconfigurationRequired"); + if (reconfiguration_required == nullptr) { + return ScopedAStatus::fromServiceSpecificError( + static_cast<int32_t>(Status::ILLEGAL_ARGUMENT)); + } + *reconfiguration_required = true; + std::unique_ptr<google_camera_hal::HalCameraMetadata> old_hal_session_metadata; + status_t res = aidl_utils::ConvertToHalMetadata( + 0, nullptr, oldSessionParams.metadata, &old_hal_session_metadata); + if (res != OK) { + ALOGE("%s: Converting to old session metadata failed: %s(%d)", __FUNCTION__, + strerror(-res), res); + return ScopedAStatus::fromServiceSpecificError( + static_cast<int32_t>(Status::INTERNAL_ERROR)); + } + + std::unique_ptr<google_camera_hal::HalCameraMetadata> new_hal_session_metadata; + res = aidl_utils::ConvertToHalMetadata(0, nullptr, newSessionParams.metadata, + &new_hal_session_metadata); + if (res != OK) { + ALOGE("%s: Converting to new session metadata failed: %s(%d)", __FUNCTION__, + strerror(-res), res); + return ScopedAStatus::fromServiceSpecificError( + static_cast<int32_t>(Status::INTERNAL_ERROR)); + } + + res = device_session_->IsReconfigurationRequired( + old_hal_session_metadata.get(), new_hal_session_metadata.get(), + reconfiguration_required); + + if (res != OK) { + ALOGE("%s: IsReconfigurationRequired failed: %s(%d)", __FUNCTION__, + strerror(-res), res); + return ScopedAStatus::fromServiceSpecificError( + static_cast<int32_t>(Status::INTERNAL_ERROR)); + } + + return ScopedAStatus::ok(); +} + +} // namespace implementation +} // namespace device +} // namespace camera +} // namespace hardware +} // namespace android |