/* * Copyright (C) 2019 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 #include #define LOG_TAG "GCH_InternalStreamManager" #define ATRACE_TAG ATRACE_TAG_CAMERA #include #include #include "hal_utils.h" #include "internal_stream_manager.h" namespace android { namespace google_camera_hal { namespace { int32_t GetNextAvailableStreamId() { static int32_t next_available_stream_id = kHalInternalStreamStart; static std::mutex next_available_stream_id_mutex; int32_t result; { std::lock_guard lock(next_available_stream_id_mutex); result = next_available_stream_id++; } return result; } } // namespace std::unique_ptr InternalStreamManager::Create( IHalBufferAllocator* buffer_allocator, int partial_result_count) { ATRACE_CALL(); auto stream_manager = std::unique_ptr(new InternalStreamManager()); if (stream_manager == nullptr) { ALOGE("%s: Creating InternalStreamManager failed.", __FUNCTION__); return nullptr; } stream_manager->Initialize(buffer_allocator, partial_result_count); return stream_manager; } void InternalStreamManager::Initialize(IHalBufferAllocator* buffer_allocator, int partial_result_count) { hwl_buffer_allocator_ = buffer_allocator; partial_result_count_ = partial_result_count; } status_t InternalStreamManager::IsStreamRegisteredLocked(int32_t stream_id) const { return registered_streams_.find(stream_id) != registered_streams_.end(); } status_t InternalStreamManager::IsStreamAllocatedLocked(int32_t stream_id) const { // Check if this stream is sharing buffers with another stream or owns a // a buffer manager. return shared_stream_owner_ids_.find(stream_id) != shared_stream_owner_ids_.end() || buffer_managers_.find(stream_id) != buffer_managers_.end(); } int32_t InternalStreamManager::GetBufferManagerOwnerIdLocked(int32_t stream_id) { int32_t owner_stream_id = stream_id; auto owner_id_it = shared_stream_owner_ids_.find(stream_id); if (owner_id_it != shared_stream_owner_ids_.end()) { owner_stream_id = owner_id_it->second; } if (buffer_managers_.find(owner_stream_id) == buffer_managers_.end()) { return kInvalidStreamId; } return owner_stream_id; } status_t InternalStreamManager::RegisterNewInternalStream(const Stream& stream, int32_t* stream_id) { ATRACE_CALL(); std::lock_guard lock(stream_mutex_); if (stream_id == nullptr) { ALOGE("%s: stream_id is nullptr.", __FUNCTION__); return BAD_VALUE; } Stream internal_stream = stream; int32_t id = stream.id; // if stream.id is one of reserved ids in camera_buffer_allocator_hwl.h, we // will use the given id so that HWL can use its predefined id to setup // implementation defined internal stream format. other wise will use the next // available unique id. if (stream.id < kStreamIdReserve) { id = GetNextAvailableStreamId(); internal_stream.id = id; } registered_streams_[id] = std::move(internal_stream); *stream_id = id; return OK; } status_t InternalStreamManager::GetBufferDescriptor( const Stream& stream, const HalStream& hal_stream, uint32_t additional_num_buffers, HalBufferDescriptor* buffer_descriptor) { ATRACE_CALL(); if (buffer_descriptor == nullptr) { ALOGE("%s: buffer_descriptor is nullptr", __FUNCTION__); return BAD_VALUE; } if (stream.id != hal_stream.id) { ALOGE("%s: IDs don't match: stream %d hal stream %d", __FUNCTION__, stream.id, hal_stream.id); return BAD_VALUE; } buffer_descriptor->stream_id = stream.id; buffer_descriptor->width = stream.width; buffer_descriptor->height = stream.height; buffer_descriptor->format = hal_stream.override_format; buffer_descriptor->producer_flags = hal_stream.producer_usage; buffer_descriptor->consumer_flags = hal_stream.consumer_usage; buffer_descriptor->immediate_num_buffers = hal_stream.max_buffers; buffer_descriptor->max_num_buffers = hal_stream.max_buffers + additional_num_buffers; return OK; } status_t InternalStreamManager::AllocateBuffers(const HalStream& hal_stream, uint32_t additional_num_buffers, bool need_vendor_buffer) { ATRACE_CALL(); std::lock_guard lock(stream_mutex_); return AllocateBuffersLocked(hal_stream, additional_num_buffers, need_vendor_buffer); } status_t InternalStreamManager::AllocateBuffersLocked( const HalStream& hal_stream, uint32_t additional_num_buffers, bool need_vendor_buffer) { ATRACE_CALL(); int32_t stream_id = hal_stream.id; if (!IsStreamRegisteredLocked(stream_id)) { ALOGE("%s: Stream %d was not registered.", __FUNCTION__, stream_id); return NAME_NOT_FOUND; } if (IsStreamAllocatedLocked(stream_id)) { ALOGE("%s: Stream %d is already allocated.", __FUNCTION__, stream_id); return ALREADY_EXISTS; } HalBufferDescriptor buffer_descriptor; status_t res = GetBufferDescriptor(registered_streams_[stream_id], hal_stream, additional_num_buffers, &buffer_descriptor); if (res != OK) { ALOGE("%s: Getting buffer descriptor failed: %s(%d)", __FUNCTION__, strerror(-res), res); return res; } auto buffer_manager = std::make_unique( need_vendor_buffer ? hwl_buffer_allocator_ : nullptr, partial_result_count_); if (buffer_manager == nullptr) { ALOGE("%s: Failed to create a buffer manager for stream %d", __FUNCTION__, stream_id); return UNKNOWN_ERROR; } res = buffer_manager->AllocateBuffers(buffer_descriptor); if (res != OK) { ALOGE( "%s: Failed to allocate %u immediate buffers (max: %u) for stream %d: " "%s(%d)", __FUNCTION__, buffer_descriptor.immediate_num_buffers, buffer_descriptor.max_num_buffers, stream_id, strerror(-res), res); return res; } buffer_managers_[stream_id] = std::move(buffer_manager); return OK; } bool InternalStreamManager::AreStreamsCompatible( const Stream& stream_0, const HalStream& hal_stream_0, const Stream& stream_1, const HalStream& hal_stream_1) const { return stream_0.width == stream_1.width && stream_0.height == stream_1.height && stream_0.rotation == stream_1.rotation && hal_stream_0.override_format == hal_stream_1.override_format && hal_stream_0.producer_usage == hal_stream_1.producer_usage && hal_stream_0.consumer_usage == hal_stream_1.consumer_usage && hal_stream_0.override_data_space == hal_stream_1.override_data_space; } bool InternalStreamManager::CanHalStreamsShareBuffersLocked( const std::vector& hal_streams) const { if (hal_streams.size() < 2) { ALOGV("%s: Cannot sharing buffers for %zu stream.", __FUNCTION__, hal_streams.size()); return BAD_VALUE; } int32_t first_stream_id = hal_streams[0].id; for (uint32_t i = 0; i < hal_streams.size(); i++) { int32_t stream_id = hal_streams[i].id; if (!IsStreamRegisteredLocked(stream_id)) { ALOGE("%s: stream id %d was not registered.", __FUNCTION__, stream_id); return false; } if (i == 0) { // Skip the first one. continue; } if (!AreStreamsCompatible(registered_streams_.at(first_stream_id), hal_streams[0], registered_streams_.at(stream_id), hal_streams[i])) { ALOGV("%s: Stream %d and %d are not compatible", __FUNCTION__, first_stream_id, stream_id); IF_ALOGV() { hal_utils::DumpStream(registered_streams_.at(first_stream_id), "stream_0"); hal_utils::DumpStream(registered_streams_.at(stream_id), "stream_1"); hal_utils::DumpHalStream(hal_streams[0], "hal_stream_0"); hal_utils::DumpHalStream(hal_streams[i], "hal_stream_1"); } return false; } } return true; } status_t InternalStreamManager::AllocateSharedBuffers( const std::vector& hal_streams, uint32_t additional_num_buffers, bool need_vendor_buffer) { std::lock_guard lock(stream_mutex_); if (hal_streams.size() < 2) { ALOGE("%s: Cannot sharing buffers for %zu stream.", __FUNCTION__, hal_streams.size()); return BAD_VALUE; } uint32_t max_buffers = 0; uint32_t total_max_buffers = 0; // Find the maximum and total of all hal_streams' max_buffers. for (auto& hal_stream : hal_streams) { if (!IsStreamRegisteredLocked(hal_stream.id)) { ALOGE("%s: Stream %d was not registered.", __FUNCTION__, hal_stream.id); return BAD_VALUE; } if (IsStreamAllocatedLocked(hal_stream.id)) { ALOGE("%s: Stream %d has been allocated.", __FUNCTION__, hal_stream.id); return BAD_VALUE; } total_max_buffers += hal_stream.max_buffers; max_buffers = std::max(max_buffers, hal_stream.max_buffers); } if (!CanHalStreamsShareBuffersLocked(hal_streams)) { ALOGE("%s: Streams cannot share buffers.", __FUNCTION__); return BAD_VALUE; } // Allocate the maximum of all hal_streams' max_buffers immediately and // additional (total_max_buffers + additional_num_buffers - max_buffers) // buffers. HalStream hal_stream = hal_streams[0]; hal_stream.max_buffers = max_buffers; uint32_t total_additional_num_buffers = total_max_buffers + additional_num_buffers - max_buffers; status_t res = AllocateBuffersLocked(hal_stream, total_additional_num_buffers, need_vendor_buffer); if (res != OK) { ALOGE("%s: Allocating buffers for stream %d failed: %s(%d)", __FUNCTION__, hal_stream.id, strerror(-res), res); return res; } for (uint32_t i = 1; i < hal_streams.size(); i++) { shared_stream_owner_ids_[hal_streams[i].id] = hal_streams[0].id; } return OK; } status_t InternalStreamManager::RemoveOwnerStreamIdLocked( int32_t old_owner_stream_id) { int32_t new_owner_stream_id = kInvalidStreamId; if (buffer_managers_.find(old_owner_stream_id) == buffer_managers_.end()) { ALOGE("%s: Stream %d does not own any buffer manager.", __FUNCTION__, old_owner_stream_id); return BAD_VALUE; } // Find the first stream that shares the buffer manager that // old_owner_stream_id owns, and update the rest of the streams to point to // the new owner. auto owner_stream_id_it = shared_stream_owner_ids_.begin(); while (owner_stream_id_it != shared_stream_owner_ids_.end()) { if (owner_stream_id_it->second == old_owner_stream_id) { if (new_owner_stream_id == kInvalidStreamId) { // Found the first stream sharing the old owner's buffer manager. // Make this the new buffer manager owner. new_owner_stream_id = owner_stream_id_it->first; owner_stream_id_it = shared_stream_owner_ids_.erase(owner_stream_id_it); continue; } else { // Update the rest of the stream to point to the new owner. owner_stream_id_it->second = new_owner_stream_id; } } owner_stream_id_it++; } if (new_owner_stream_id != kInvalidStreamId) { // Update buffer manager owner. buffer_managers_[new_owner_stream_id] = std::move(buffer_managers_[old_owner_stream_id]); } buffer_managers_.erase(old_owner_stream_id); return OK; } void InternalStreamManager::FreeStream(int32_t stream_id) { ATRACE_CALL(); std::lock_guard lock(stream_mutex_); registered_streams_.erase(stream_id); int32_t owner_stream_id = GetBufferManagerOwnerIdLocked(stream_id); if (owner_stream_id == kInvalidStreamId) { ALOGE("%s: Cannot find a owner stream ID for stream %d", __FUNCTION__, stream_id); return; } if (stream_id == owner_stream_id) { // Find a new owner if the owner is being freed. status_t res = RemoveOwnerStreamIdLocked(owner_stream_id); if (res != OK) { ALOGE("%s: Removing owner stream failed: %s(%d)", __FUNCTION__, strerror(-res), res); return; } } else { // If this stream is not the owner, just remove it from // shared_stream_owner_ids_. shared_stream_owner_ids_.erase(stream_id); } } status_t InternalStreamManager::GetStreamBuffer(int32_t stream_id, StreamBuffer* buffer) { ATRACE_CALL(); std::lock_guard lock(stream_mutex_); if (!IsStreamAllocatedLocked(stream_id)) { ALOGE("%s: Stream %d was not allocated.", __FUNCTION__, stream_id); return ALREADY_EXISTS; } if (buffer == nullptr) { ALOGE("%s: buffer is nullptr", __FUNCTION__); return BAD_VALUE; } int32_t owner_stream_id = GetBufferManagerOwnerIdLocked(stream_id); if (owner_stream_id == kInvalidStreamId) { ALOGE("%s: Cannot find a owner stream ID for stream %d", __FUNCTION__, stream_id); return BAD_VALUE; } buffer->buffer = buffer_managers_[owner_stream_id]->GetEmptyBuffer(); if (buffer->buffer == kInvalidBufferHandle) { ALOGE("%s: Failed to get an empty buffer for stream %d (owner %d)", __FUNCTION__, stream_id, owner_stream_id); return UNKNOWN_ERROR; } buffer->stream_id = stream_id; buffer->buffer_id = 0; // Buffer ID should be irrelevant internally in HAL. buffer->status = BufferStatus::kOk; buffer->acquire_fence = nullptr; buffer->release_fence = nullptr; return OK; } bool InternalStreamManager::IsPendingBufferEmpty(int32_t stream_id) { ATRACE_CALL(); std::lock_guard lock(stream_mutex_); if (!IsStreamAllocatedLocked(stream_id)) { ALOGE("%s: Stream %d was not allocated.", __FUNCTION__, stream_id); return false; } int32_t owner_stream_id = GetBufferManagerOwnerIdLocked(stream_id); if (owner_stream_id == kInvalidStreamId) { ALOGE("%s: Cannot find a owner stream ID for stream %d", __FUNCTION__, stream_id); return false; } return buffer_managers_[owner_stream_id]->IsPendingBufferEmpty(); } status_t InternalStreamManager::GetMostRecentStreamBuffer( int32_t stream_id, std::vector* input_buffers, std::vector>* input_buffer_metadata, uint32_t payload_frames, int32_t min_filled_buffers) { ATRACE_CALL(); std::lock_guard lock(stream_mutex_); if (static_cast(payload_frames) < min_filled_buffers) { ALOGW("%s: payload frames %d is smaller than min filled buffers %d", __FUNCTION__, payload_frames, min_filled_buffers); } if (!IsStreamAllocatedLocked(stream_id)) { ALOGE("%s: Stream %d was not allocated.", __FUNCTION__, stream_id); return BAD_VALUE; } int32_t owner_stream_id = GetBufferManagerOwnerIdLocked(stream_id); if (owner_stream_id == kInvalidStreamId) { ALOGE("%s: Cannot find a owner stream ID for stream %d", __FUNCTION__, stream_id); return BAD_VALUE; } if (input_buffers == nullptr || input_buffer_metadata == nullptr) { ALOGE("%s: input_buffers (%p) or input_buffer_metadata (%p) is nullptr", __FUNCTION__, input_buffers, input_buffer_metadata); return BAD_VALUE; } std::vector filled_buffers; buffer_managers_[owner_stream_id]->GetMostRecentZslBuffers( &filled_buffers, payload_frames, min_filled_buffers); if (filled_buffers.size() == 0) { ALOGE("%s: There is no input buffers.", __FUNCTION__); return INVALID_OPERATION; } // TODO(b/138592133): Remove AddPendingBuffers because internal stream manager // should not be responsible for saving the pending buffers' metadata. buffer_managers_[owner_stream_id]->AddPendingBuffers(filled_buffers); for (uint32_t i = 0; i < filled_buffers.size(); i++) { StreamBuffer buffer = {}; buffer.stream_id = stream_id; buffer.buffer_id = 0; // Buffer ID should be irrelevant internally in HAL. buffer.status = BufferStatus::kOk; buffer.acquire_fence = nullptr; buffer.release_fence = nullptr; buffer.buffer = filled_buffers[i].buffer.buffer; input_buffers->push_back(buffer); if (filled_buffers[i].metadata == nullptr) { std::vector buffers; buffer_managers_[owner_stream_id]->CleanPendingBuffers(&buffers); buffer_managers_[owner_stream_id]->ReturnZslBuffers(std::move(buffers)); return INVALID_OPERATION; } input_buffer_metadata->push_back(std::move(filled_buffers[i].metadata)); } return OK; } status_t InternalStreamManager::ReturnZslStreamBuffers(uint32_t frame_number, int32_t stream_id) { ATRACE_CALL(); std::lock_guard lock(stream_mutex_); if (!IsStreamAllocatedLocked(stream_id)) { ALOGE("%s: Unknown stream ID %d.", __FUNCTION__, stream_id); return BAD_VALUE; } int32_t owner_stream_id = GetBufferManagerOwnerIdLocked(stream_id); if (owner_stream_id == kInvalidStreamId) { ALOGE("%s: Cannot find a owner stream ID for stream %d", __FUNCTION__, stream_id); return BAD_VALUE; } std::vector zsl_buffers; status_t res = buffer_managers_[owner_stream_id]->CleanPendingBuffers(&zsl_buffers); if (res != OK) { ALOGE("%s: frame (%d)fail to return zsl stream buffers", __FUNCTION__, frame_number); return res; } buffer_managers_[owner_stream_id]->ReturnZslBuffers(std::move(zsl_buffers)); return OK; } status_t InternalStreamManager::ReturnStreamBuffer(const StreamBuffer& buffer) { ATRACE_CALL(); std::lock_guard lock(stream_mutex_); int32_t stream_id = buffer.stream_id; if (!IsStreamAllocatedLocked(stream_id)) { ALOGE("%s: Unknown stream ID %d.", __FUNCTION__, stream_id); return BAD_VALUE; } int32_t owner_stream_id = GetBufferManagerOwnerIdLocked(stream_id); if (owner_stream_id == kInvalidStreamId) { ALOGE("%s: Cannot find a owner stream ID for stream %d", __FUNCTION__, stream_id); return BAD_VALUE; } return buffer_managers_[owner_stream_id]->ReturnEmptyBuffer(buffer.buffer); } status_t InternalStreamManager::ReturnFilledBuffer(uint32_t frame_number, const StreamBuffer& buffer) { ATRACE_CALL(); std::lock_guard lock(stream_mutex_); int32_t stream_id = buffer.stream_id; if (!IsStreamAllocatedLocked(stream_id)) { ALOGE("%s: Unknown stream ID %d.", __FUNCTION__, stream_id); return BAD_VALUE; } int32_t owner_stream_id = GetBufferManagerOwnerIdLocked(stream_id); if (owner_stream_id == kInvalidStreamId) { ALOGE("%s: Cannot find a owner stream ID for stream %d", __FUNCTION__, stream_id); return BAD_VALUE; } return buffer_managers_[owner_stream_id]->ReturnFilledBuffer(frame_number, buffer); } status_t InternalStreamManager::ReturnMetadata(int32_t stream_id, uint32_t frame_number, const HalCameraMetadata* metadata, int partial_result) { ATRACE_CALL(); std::lock_guard lock(stream_mutex_); if (!IsStreamAllocatedLocked(stream_id)) { ALOGE("%s: Unknown stream ID %d.", __FUNCTION__, stream_id); return BAD_VALUE; } int32_t owner_stream_id = GetBufferManagerOwnerIdLocked(stream_id); if (owner_stream_id == kInvalidStreamId) { ALOGE("%s: Cannot find a owner stream ID for stream %d", __FUNCTION__, stream_id); return BAD_VALUE; } return buffer_managers_[owner_stream_id]->ReturnMetadata( frame_number, metadata, partial_result); } } // namespace google_camera_hal } // namespace android