/* * Copyright (C) 2021 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 "GCH_ZslSnapshotCaptureSession" #define ATRACE_TAG ATRACE_TAG_CAMERA #include "zsl_snapshot_capture_session.h" #include #include #include #include #include "hal_utils.h" #include "snapshot_request_processor.h" #include "snapshot_result_processor.h" #include "system/graphics-base-v1.0.h" #include "utils.h" #include "utils/Errors.h" #include "vendor_tag_defs.h" namespace android { namespace google_camera_hal { namespace { #if GCH_HWL_USE_DLOPEN // HAL external process block library path #if defined(_LP64) constexpr char kExternalProcessBlockDir[] = "/vendor/lib64/camera/google_proprietary/"; #else // defined(_LP64) constexpr char kExternalProcessBlockDir[] = "/vendor/lib/camera/google_proprietary/"; #endif #endif // GCH_HWL_USE_DLOPEN bool IsSwDenoiseSnapshotCompatible(const CaptureRequest& request) { if (request.settings == nullptr) { return false; } camera_metadata_ro_entry entry; if (request.settings->Get(ANDROID_CONTROL_CAPTURE_INTENT, &entry) != OK || *entry.data.u8 != ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE) { ALOGV("%s: ANDROID_CONTROL_CAPTURE_INTENT is not STILL_CAPTURE", __FUNCTION__); return false; } if (request.settings->Get(ANDROID_NOISE_REDUCTION_MODE, &entry) != OK || *entry.data.u8 != ANDROID_NOISE_REDUCTION_MODE_HIGH_QUALITY) { ALOGI("%s: ANDROID_NOISE_REDUCTION_MODE is not HQ", __FUNCTION__); return false; } if (request.settings->Get(ANDROID_EDGE_MODE, &entry) != OK || *entry.data.u8 != ANDROID_EDGE_MODE_HIGH_QUALITY) { ALOGI("%s: ANDROID_EDGE_MODE is not HQ", __FUNCTION__); return false; } if (request.settings->Get(ANDROID_CONTROL_EFFECT_MODE, &entry) != OK || *entry.data.u8 != ANDROID_CONTROL_EFFECT_MODE_OFF) { ALOGI("%s: ANDROID_CONTROL_EFFECT_MODE is not off", __FUNCTION__); return false; } if (request.settings->Get(ANDROID_TONEMAP_MODE, &entry) != OK || *entry.data.u8 != ANDROID_TONEMAP_MODE_HIGH_QUALITY) { ALOGI("%s: ANDROID_TONEMAP_MODE is not HQ", __FUNCTION__); return false; } return true; } } // namespace std::unique_ptr ZslSnapshotCaptureSession::CreateSnapshotProcessBlock() { ATRACE_CALL(); #if GCH_HWL_USE_DLOPEN bool found_process_block = false; for (const auto& lib_path : utils::FindLibraryPaths(kExternalProcessBlockDir)) { ALOGI("%s: Loading %s", __FUNCTION__, lib_path.c_str()); void* lib_handle = nullptr; lib_handle = dlopen(lib_path.c_str(), RTLD_NOW); if (lib_handle == nullptr) { ALOGW("Failed loading %s.", lib_path.c_str()); continue; } GetProcessBlockFactoryFunc external_process_block_t = reinterpret_cast( dlsym(lib_handle, "GetProcessBlockFactory")); if (external_process_block_t == nullptr) { ALOGE("%s: dlsym failed (%s) when loading %s.", __FUNCTION__, "GetProcessBlockFactoryFunc", lib_path.c_str()); dlclose(lib_handle); lib_handle = nullptr; continue; } if (external_process_block_t()->GetBlockName() == "SnapshotProcessBlock") { snapshot_process_block_factory_ = external_process_block_t; snapshot_process_block_lib_handle_ = lib_handle; found_process_block = true; break; } } if (!found_process_block) { ALOGE("%s: snapshot process block does not exist", __FUNCTION__); return nullptr; } return snapshot_process_block_factory_()->CreateProcessBlock( camera_device_session_hwl_); #else if (GetSnapshotProcessBlockFactory == nullptr) { ALOGE("%s: snapshot process block does not exist", __FUNCTION__); return nullptr; } snapshot_process_block_factory_ = GetSnapshotProcessBlockFactory; return GetSnapshotProcessBlockFactory()->CreateProcessBlock( camera_device_session_hwl_); #endif } std::unique_ptr ZslSnapshotCaptureSession::CreateDenoiseProcessBlock() { ATRACE_CALL(); #if GCH_HWL_USE_DLOPEN bool found_process_block = false; for (const auto& lib_path : utils::FindLibraryPaths(kExternalProcessBlockDir)) { ALOGI("%s: Loading %s", __FUNCTION__, lib_path.c_str()); void* lib_handle = nullptr; lib_handle = dlopen(lib_path.c_str(), RTLD_NOW); if (lib_handle == nullptr) { ALOGW("Failed loading %s.", lib_path.c_str()); continue; } GetProcessBlockFactoryFunc external_process_block_t = reinterpret_cast( dlsym(lib_handle, "GetProcessBlockFactory")); if (external_process_block_t == nullptr) { ALOGE("%s: dlsym failed (%s) when loading %s.", __FUNCTION__, "GetProcessBlockFactoryFunc", lib_path.c_str()); dlclose(lib_handle); lib_handle = nullptr; continue; } if (external_process_block_t()->GetBlockName() == "DenoiseProcessBlock") { denoise_process_block_factory_ = external_process_block_t; denoise_process_block_lib_handle_ = lib_handle; found_process_block = true; break; } } if (!found_process_block) { ALOGE("%s: denoise process block does not exist", __FUNCTION__); return nullptr; } return denoise_process_block_factory_()->CreateProcessBlock( camera_device_session_hwl_); #else if (GetDenoiseProcessBlockFactory == nullptr) { ALOGE("%s: denoise process block does not exist", __FUNCTION__); return nullptr; } denoise_process_block_factory_ = GetDenoiseProcessBlockFactory; return GetDenoiseProcessBlockFactory()->CreateProcessBlock( camera_device_session_hwl_); #endif } bool ZslSnapshotCaptureSession::IsStreamConfigurationSupported( CameraDeviceSessionHwl* device_session_hwl, const StreamConfiguration& stream_config) { ATRACE_CALL(); if (device_session_hwl == nullptr) { ALOGE("%s: device_session_hwl is nullptr", __FUNCTION__); return false; } std::unique_ptr characteristics; status_t res = device_session_hwl->GetCameraCharacteristics(&characteristics); if (res != OK) { ALOGE("%s: GetCameraCharacteristics failed.", __FUNCTION__); return false; } camera_metadata_ro_entry entry; res = characteristics->Get(VendorTagIds::kSwDenoiseEnabled, &entry); if (res != OK || entry.data.u8[0] != 1) { ALOGE("%s: Software denoised not enabled", __FUNCTION__); return false; } bool has_eligible_snapshot_stream = false; bool has_preview_stream = false; for (const auto& stream : stream_config.streams) { if (stream.is_physical_camera_stream) { ALOGE("%s: support logical camera only", __FUNCTION__); return false; } if (utils::IsJPEGSnapshotStream(stream) || utils::IsYUVSnapshotStream(stream)) { if (utils::IsSoftwareDenoiseEligibleSnapshotStream(stream)) { has_eligible_snapshot_stream = true; } } else if (utils::IsPreviewStream(stream)) { has_preview_stream = true; } else { ALOGE("%s: only support preview + (snapshot and/or YUV) streams", __FUNCTION__); return false; } } if (!has_eligible_snapshot_stream) { ALOGE("%s: no eligible JPEG or YUV stream", __FUNCTION__); return false; } if (!has_preview_stream) { ALOGE("%s: no preview stream", __FUNCTION__); return false; } ALOGD("%s: ZslSnapshotCaptureSession supports the stream config", __FUNCTION__); return true; } std::unique_ptr ZslSnapshotCaptureSession::Create( const StreamConfiguration& stream_config, const std::vector& external_capture_session_entries, const std::vector& capture_session_entries, HwlSessionCallback hwl_session_callback, CameraBufferAllocatorHwl* camera_buffer_allocator_hwl, CameraDeviceSessionHwl* camera_device_session_hwl, std::vector* hal_configured_streams, ProcessCaptureResultFunc process_capture_result, NotifyFunc notify) { ATRACE_CALL(); auto session = std::unique_ptr(new ZslSnapshotCaptureSession( external_capture_session_entries, capture_session_entries, hwl_session_callback, camera_buffer_allocator_hwl, camera_device_session_hwl)); if (session == nullptr) { ALOGE("%s: Creating ZslSnapshotCaptureSession failed.", __FUNCTION__); return nullptr; } status_t res = session->Initialize(camera_device_session_hwl, stream_config, process_capture_result, notify, hal_configured_streams); if (res != OK) { ALOGE("%s: Initializing ZslSnapshotCaptureSession failed: %s (%d).", __FUNCTION__, strerror(-res), res); return nullptr; } return session; } ZslSnapshotCaptureSession::~ZslSnapshotCaptureSession() { auto release_thread = std::thread([this]() { ATRACE_NAME("Release snapshot request processor"); snapshot_request_processor_ = nullptr; }); if (camera_device_session_hwl_ != nullptr) { camera_device_session_hwl_->DestroyPipelines(); } // Need to explicitly release SnapshotProcessBlock by releasing // SnapshotRequestProcessor before the lib handle is released. release_thread.join(); dlclose(snapshot_process_block_lib_handle_); dlclose(denoise_process_block_lib_handle_); } status_t ZslSnapshotCaptureSession::BuildPipelines( ProcessBlock* process_block, ProcessBlock* snapshot_process_block, std::vector* hal_configured_streams) { ATRACE_CALL(); if (process_block == nullptr || hal_configured_streams == nullptr || snapshot_process_block == nullptr) { ALOGE( "%s: process_block (%p) or hal_configured_streams (%p) or " "snapshot_process_block (%p) is nullptr", __FUNCTION__, process_block, hal_configured_streams, snapshot_process_block); return BAD_VALUE; } status_t res; std::vector snapshot_hal_configured_streams; res = snapshot_process_block->GetConfiguredHalStreams( &snapshot_hal_configured_streams); if (res != OK) { ALOGE("%s: Getting snapshot HAL streams failed: %s(%d)", __FUNCTION__, strerror(-res), res); return res; } for (uint32_t i = 0; i < hal_configured_streams->size(); i++) { if (hal_configured_streams->at(i).id == additional_stream_id_) { // Reserve additional buffer(s). hal_configured_streams->at(i).max_buffers += kAdditionalBufferNumber; // Allocate internal YUV stream buffers res = internal_stream_manager_->AllocateBuffers( hal_configured_streams->at(i), /*additional_num_buffers=*/kAdditionalBufferNumber); if (res != OK) { ALOGE("%s: AllocateBuffers failed.", __FUNCTION__); return UNKNOWN_ERROR; } break; } } return OK; } status_t ZslSnapshotCaptureSession::ConfigureStreams( const StreamConfiguration& stream_config, RequestProcessor* request_processor, ProcessBlock* process_block, ProcessCaptureResultFunc process_capture_result, NotifyFunc notify, int32_t& additional_stream_id) { ATRACE_CALL(); if (request_processor == nullptr || process_block == nullptr) { ALOGE("%s: request_processor (%p) or process_block (%p) is nullptr", __FUNCTION__, request_processor, process_block); return BAD_VALUE; } StreamConfiguration process_block_stream_config; // Configure streams for request processor status_t res = request_processor->ConfigureStreams( internal_stream_manager_.get(), stream_config, &process_block_stream_config); if (res != OK) { ALOGE("%s: Configuring stream for request processor failed.", __FUNCTION__); return res; } // Check all streams are configured. if (stream_config.streams.size() > process_block_stream_config.streams.size()) { ALOGE("%s: stream_config has %zu streams but only configured %zu streams", __FUNCTION__, stream_config.streams.size(), process_block_stream_config.streams.size()); return UNKNOWN_ERROR; } for (auto& stream : stream_config.streams) { bool found = false; for (auto& configured_stream : process_block_stream_config.streams) { if (stream.id == configured_stream.id) { found = true; break; } } if (!found) { ALOGE("%s: Cannot find stream %u in configured streams.", __FUNCTION__, stream.id); return UNKNOWN_ERROR; } } for (auto& stream : process_block_stream_config.streams) { bool found = false; for (auto& configured_stream : stream_config.streams) { if (stream.id == configured_stream.id) { found = true; break; } } if (!found) { additional_stream_id = stream.id; break; } } if (additional_stream_id == -1) { ALOGE("%s: Configuring stream fail due to wrong additional_stream_id", __FUNCTION__); return UNKNOWN_ERROR; } // Create preview result processor. Stream ID is not set at this stage. auto realtime_result_processor = RealtimeZslResultProcessor::Create( internal_stream_manager_.get(), additional_stream_id, HAL_PIXEL_FORMAT_YCBCR_420_888, partial_result_count_); if (realtime_result_processor == nullptr) { ALOGE("%s: Creating RealtimeZslResultProcessor failed.", __FUNCTION__); return UNKNOWN_ERROR; } realtime_result_processor_ = realtime_result_processor.get(); realtime_result_processor->SetResultCallback(process_capture_result, notify); res = process_block->SetResultProcessor(std::move(realtime_result_processor)); if (res != OK) { ALOGE("%s: Setting result process in process block failed.", __FUNCTION__); return res; } // Configure streams for process block. res = process_block->ConfigureStreams(process_block_stream_config, stream_config); if (res != OK) { ALOGE("%s: Configuring stream for process block failed.", __FUNCTION__); return res; } for (auto& hal_stream : *hal_config_) { if (hal_stream.id == additional_stream_id) { // Set the producer usage so that the buffer will be 64 byte aligned. hal_stream.producer_usage |= (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_OFTEN); } } return OK; } status_t ZslSnapshotCaptureSession::ConfigureSnapshotStreams( const StreamConfiguration& stream_config) { ATRACE_CALL(); if (snapshot_process_block_ == nullptr || snapshot_request_processor_ == nullptr) { ALOGE( "%s: snapshot_process_block_ or snapshot_request_processor_ is nullptr", __FUNCTION__); return BAD_VALUE; } StreamConfiguration process_block_stream_config; // Configure streams for request processor status_t res = snapshot_request_processor_->ConfigureStreams( internal_stream_manager_.get(), stream_config, &process_block_stream_config); if (res != OK) { ALOGE("%s: Configuring stream for request processor failed.", __FUNCTION__); return res; } // Configure streams for snapshot process block. res = snapshot_process_block_->ConfigureStreams(process_block_stream_config, stream_config); if (res != OK) { ALOGE("%s: Configuring snapshot stream for process block failed.", __FUNCTION__); return res; } return OK; } status_t ZslSnapshotCaptureSession::SetupSnapshotProcessChain( const StreamConfiguration& stream_config, ProcessCaptureResultFunc process_capture_result, NotifyFunc notify) { ATRACE_CALL(); if (snapshot_process_block_ != nullptr || snapshot_result_processor_ != nullptr || snapshot_request_processor_ != nullptr) { ALOGE( "%s: snapshot_process_block_(%p) or snapshot_result_processor_(%p) or " "snapshot_request_processor_(%p) is/are " "already set", __FUNCTION__, snapshot_process_block_, snapshot_result_processor_, snapshot_request_processor_.get()); return BAD_VALUE; } std::unique_ptr snapshot_process_block = CreateSnapshotProcessBlock(); if (snapshot_process_block == nullptr) { ALOGE("%s: Creating SnapshotProcessBlock failed.", __FUNCTION__); return UNKNOWN_ERROR; } snapshot_process_block_ = snapshot_process_block.get(); snapshot_request_processor_ = SnapshotRequestProcessor::Create( camera_device_session_hwl_, hwl_session_callback_, additional_stream_id_); if (snapshot_request_processor_ == nullptr) { ALOGE("%s: Creating SnapshotRequestProcessor failed.", __FUNCTION__); return UNKNOWN_ERROR; } std::unique_ptr snapshot_result_processor = SnapshotResultProcessor::Create(internal_stream_manager_.get(), additional_stream_id_); if (snapshot_result_processor == nullptr) { ALOGE("%s: Creating SnapshotResultProcessor failed.", __FUNCTION__); return UNKNOWN_ERROR; } snapshot_result_processor_ = snapshot_result_processor.get(); status_t res = snapshot_request_processor_->SetProcessBlock( std::move(snapshot_process_block)); if (res != OK) { ALOGE("%s: Setting process block for RequestProcessor failed: %s(%d)", __FUNCTION__, strerror(-res), res); return res; } res = snapshot_process_block_->SetResultProcessor( std::move(snapshot_result_processor)); snapshot_result_processor_->SetResultCallback(process_capture_result, notify); res = ConfigureSnapshotStreams(stream_config); if (res != OK) { ALOGE("%s: Configuring snapshot stream failed: %s(%d)", __FUNCTION__, strerror(-res), res); return res; } return OK; } status_t ZslSnapshotCaptureSession::SetupRealtimeProcessChain( const StreamConfiguration& stream_config, ProcessCaptureResultFunc process_capture_result, NotifyFunc notify) { ATRACE_CALL(); if (realtime_process_block_ != nullptr || realtime_result_processor_ != nullptr || realtime_request_processor_ != nullptr) { ALOGE( "%s: realtime_process_block_(%p) or realtime_result_processor_(%p) or " "realtime_request_processor_(%p) is/are " "already set", __FUNCTION__, realtime_process_block_, realtime_result_processor_, realtime_request_processor_.get()); return BAD_VALUE; } // Create process block auto realtime_process_block = CaptureSessionWrapperProcessBlock::Create( external_capture_session_entries_, capture_session_entries_, hwl_session_callback_, camera_buffer_allocator_hwl_, camera_device_session_hwl_, hal_config_); if (realtime_process_block == nullptr) { ALOGE("%s: Creating RealtimeProcessBlock failed.", __FUNCTION__); return UNKNOWN_ERROR; } realtime_process_block_ = realtime_process_block.get(); // Create realtime request processor. realtime_request_processor_ = RealtimeZslRequestProcessor::Create( camera_device_session_hwl_, HAL_PIXEL_FORMAT_YCBCR_420_888); if (realtime_request_processor_ == nullptr) { ALOGE("%s: Creating RealtimeZslRequestProcessor failed.", __FUNCTION__); return UNKNOWN_ERROR; } // realtime result processor will be created inside ConfigureStreams when the // additional stream id is determined. status_t res = realtime_request_processor_->SetProcessBlock( std::move(realtime_process_block)); if (res != OK) { ALOGE("%s: Setting process block for RequestProcessor failed: %s(%d)", __FUNCTION__, strerror(-res), res); return res; } res = ConfigureStreams(stream_config, realtime_request_processor_.get(), realtime_process_block_, process_capture_result, notify, additional_stream_id_); if (res != OK) { ALOGE("%s: Configuring stream failed: %s(%d)", __FUNCTION__, strerror(-res), res); return res; } return OK; } status_t ZslSnapshotCaptureSession::PurgeHalConfiguredStream( const StreamConfiguration& stream_config, std::vector* hal_configured_streams) { if (hal_configured_streams == nullptr) { ALOGE("%s: HAL configured stream list is null.", __FUNCTION__); return BAD_VALUE; } std::set framework_stream_id_set; for (auto& stream : stream_config.streams) { framework_stream_id_set.insert(stream.id); } std::vector configured_streams; for (auto& hal_stream : *hal_configured_streams) { if (framework_stream_id_set.find(hal_stream.id) != framework_stream_id_set.end()) { configured_streams.push_back(hal_stream); } } *hal_configured_streams = configured_streams; return OK; } ZslSnapshotCaptureSession::ZslSnapshotCaptureSession( const std::vector& external_capture_session_entries, const std::vector& capture_session_entries, HwlSessionCallback hwl_session_callback, CameraBufferAllocatorHwl* camera_buffer_allocator_hwl, CameraDeviceSessionHwl* camera_device_session_hwl) : external_capture_session_entries_(external_capture_session_entries), capture_session_entries_(capture_session_entries), hwl_session_callback_(hwl_session_callback), camera_buffer_allocator_hwl_(camera_buffer_allocator_hwl), camera_device_session_hwl_(camera_device_session_hwl) { } status_t ZslSnapshotCaptureSession::Initialize( CameraDeviceSessionHwl* camera_device_session_hwl, const StreamConfiguration& stream_config, ProcessCaptureResultFunc process_capture_result, NotifyFunc notify, std::vector* hal_configured_streams) { ATRACE_CALL(); if (!IsStreamConfigurationSupported(camera_device_session_hwl, stream_config)) { ALOGE("%s: stream configuration is not supported.", __FUNCTION__); return BAD_VALUE; } std::unique_ptr characteristics; status_t res = camera_device_session_hwl->GetCameraCharacteristics(&characteristics); if (res != OK) { ALOGE("%s: GetCameraCharacteristics failed.", __FUNCTION__); return BAD_VALUE; } for (auto stream : stream_config.streams) { if (utils::IsPreviewStream(stream)) { hal_preview_stream_id_ = stream.id; break; } } camera_device_session_hwl_ = camera_device_session_hwl; hal_config_ = hal_configured_streams; // Create result dispatcher partial_result_count_ = kPartialResult; camera_metadata_ro_entry partial_result_entry; res = characteristics->Get(ANDROID_REQUEST_PARTIAL_RESULT_COUNT, &partial_result_entry); if (res == OK) { partial_result_count_ = partial_result_entry.data.i32[0]; } result_dispatcher_ = ZslResultDispatcher::Create( partial_result_count_, process_capture_result, notify); if (result_dispatcher_ == nullptr) { ALOGE("%s: Cannot create result dispatcher.", __FUNCTION__); return UNKNOWN_ERROR; } internal_stream_manager_ = InternalStreamManager::Create( /*buffer_allocator=*/nullptr, partial_result_count_); if (internal_stream_manager_ == nullptr) { ALOGE("%s: Cannot create internal stream manager.", __FUNCTION__); return UNKNOWN_ERROR; } device_session_notify_ = notify; process_capture_result_ = ProcessCaptureResultFunc([this](std::unique_ptr result) { ProcessCaptureResult(std::move(result)); }); notify_ = NotifyFunc( [this](const NotifyMessage& message) { NotifyHalMessage(message); }); // Setup and connect realtime process chain res = SetupRealtimeProcessChain(stream_config, process_capture_result_, notify_); if (res != OK) { ALOGE("%s: SetupRealtimeProcessChain fail: %s(%d)", __FUNCTION__, strerror(-res), res); return res; } // Setup snapshot process chain res = SetupSnapshotProcessChain(stream_config, process_capture_result_, notify_); if (res != OK) { ALOGE("%s: SetupSnapshotProcessChain fail: %s(%d)", __FUNCTION__, strerror(-res), res); return res; } // Realtime and snapshot streams are configured // Start to build pipleline res = BuildPipelines(realtime_process_block_, snapshot_process_block_, hal_configured_streams); if (res != OK) { ALOGE("%s: Building pipelines failed: %s(%d)", __FUNCTION__, strerror(-res), res); return res; } res = PurgeHalConfiguredStream(stream_config, hal_configured_streams); if (res != OK) { ALOGE("%s: Removing internal streams from configured stream failed: %s(%d)", __FUNCTION__, strerror(-res), res); return res; } if (res != OK) { ALOGE("%s: Connecting process chain failed: %s(%d)", __FUNCTION__, strerror(-res), res); return res; } return OK; } status_t ZslSnapshotCaptureSession::ProcessRequest(const CaptureRequest& request) { ATRACE_CALL(); bool is_zsl_request = false; camera_metadata_ro_entry entry; if (request.settings != nullptr) { if (request.settings->Get(ANDROID_CONTROL_ENABLE_ZSL, &entry) == OK && *entry.data.u8 == ANDROID_CONTROL_ENABLE_ZSL_TRUE) { is_zsl_request = true; } } status_t res = result_dispatcher_->AddPendingRequest(request, is_zsl_request); if (res != OK) { ALOGE("%s: frame(%d) fail to AddPendingRequest", __FUNCTION__, request.frame_number); return BAD_VALUE; } if (IsSwDenoiseSnapshotCompatible(request)) { res = snapshot_request_processor_->ProcessRequest(request); if (res != OK) { ALOGW( "%s: frame (%d) fall back to real time request for snapshot: %s (%d)", __FUNCTION__, request.frame_number, strerror(-res), res); res = realtime_request_processor_->ProcessRequest(request); } } else { res = realtime_request_processor_->ProcessRequest(request); } if (res != OK) { ALOGE("%s: ProcessRequest (%d) fail and remove pending request", __FUNCTION__, request.frame_number); result_dispatcher_->RemovePendingRequest(request.frame_number); } return res; } status_t ZslSnapshotCaptureSession::Flush() { ATRACE_CALL(); return realtime_request_processor_->Flush(); } void ZslSnapshotCaptureSession::ProcessCaptureResult( std::unique_ptr result) { ATRACE_CALL(); std::lock_guard lock(callback_lock_); if (result == nullptr) { return; } if (result->result_metadata) { camera_device_session_hwl_->FilterResultMetadata( result->result_metadata.get()); } status_t res = result_dispatcher_->AddResult(std::move(result)); if (res != OK) { ALOGE("%s: fail to AddResult", __FUNCTION__); return; } } void ZslSnapshotCaptureSession::NotifyHalMessage(const NotifyMessage& message) { ATRACE_CALL(); std::lock_guard lock(callback_lock_); if (device_session_notify_ == nullptr) { ALOGE("%s: device_session_notify_ is nullptr. Dropping a message.", __FUNCTION__); return; } if (message.type == MessageType::kShutter) { status_t res = result_dispatcher_->AddShutter( message.message.shutter.frame_number, message.message.shutter.timestamp_ns, message.message.shutter.readout_timestamp_ns); if (res != OK) { ALOGE("%s: AddShutter for frame %u failed: %s (%d).", __FUNCTION__, message.message.shutter.frame_number, strerror(-res), res); return; } } else if (message.type == MessageType::kError) { status_t res = result_dispatcher_->AddError(message.message.error); if (res != OK) { ALOGE("%s: AddError for frame %u failed: %s (%d).", __FUNCTION__, message.message.error.frame_number, strerror(-res), res); return; } } else { ALOGW("%s: Unsupported message type: %u", __FUNCTION__, message.type); device_session_notify_(message); } } } // namespace google_camera_hal } // namespace android