/* * Copyright (C) 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. */ #include #include #include #include #include #include "CachedStreamBuffer.h" #include "debug.h" namespace android { namespace hardware { namespace camera { namespace provider { namespace implementation { using base::unique_fd; namespace { const native_handle_t* importAidlNativeHandle(const NativeHandle& anh) { typedef decltype(native_handle_t::version) T; std::vector data(sizeof(native_handle_t) / sizeof(T) + anh.fds.size() + anh.ints.size()); native_handle_t* h = native_handle_init( reinterpret_cast(&data[0]), anh.fds.size(), anh.ints.size()); std::transform(anh.fds.begin(), anh.fds.end(), &h->data[0], [](const ndk::ScopedFileDescriptor& sfd){ return sfd.get(); }); std::copy(anh.ints.begin(), anh.ints.end(), &h->data[anh.fds.size()]); const native_handle_t* importedH = nullptr; if (GraphicBufferMapper::get().importBufferNoValidate(h, &importedH) != NO_ERROR) { return FAILURE(nullptr); } return importedH; } unique_fd importAidlNativeHandleFence(const NativeHandle& nh) { const size_t nfds = nh.fds.size(); const size_t nints = nh.ints.size(); if (nints == 0) { switch (nfds) { case 0: return unique_fd(); case 1: { const int fd = fcntl(nh.fds.front().get(), F_DUPFD_CLOEXEC, 0); if (fd < 0) { return FAILURE_V(unique_fd(), "fcntl failed with %s (%d)", strerror(errno), errno); } return unique_fd(fd); } default: return FAILURE_V(unique_fd(), "unexpected fence shape, nfds=%zu, must " "be one", nfds); } } else { return unique_fd(); } } NativeHandle moveFenceToAidlNativeHandle(unique_fd fence) { if (!fence.ok()) { return {}; } typedef decltype(native_handle_t::version) T; T on_stack[sizeof(native_handle_t) / sizeof(T) + 1]; native_handle_t* nh = native_handle_init( reinterpret_cast(&on_stack[0]), 1, 0); nh->data[0] = fence.release(); return makeToAidl(nh); } } //namespace CachedStreamBuffer::CachedStreamBuffer(const StreamBuffer& sb) : mBuffer(importAidlNativeHandle(sb.buffer)) , mBufferId(sb.bufferId) , mAcquireFence(importAidlNativeHandleFence(sb.acquireFence)) , mStreamId(sb.streamId) { LOG_ALWAYS_FATAL_IF(!mBuffer); LOG_ALWAYS_FATAL_IF(!mBufferId); LOG_ALWAYS_FATAL_IF(mStreamId < 0); } CachedStreamBuffer::CachedStreamBuffer(CachedStreamBuffer&& rhs) noexcept : mBuffer(std::exchange(rhs.mBuffer, nullptr)) , mBufferId(std::exchange(rhs.mBufferId, 0)) , mAcquireFence(std::exchange(rhs.mAcquireFence, {})) , mStreamId(std::exchange(rhs.mStreamId, -1)) , mProcessed(std::exchange(rhs.mProcessed, true)) { LOG_ALWAYS_FATAL_IF(!mBuffer); LOG_ALWAYS_FATAL_IF(!mBufferId); LOG_ALWAYS_FATAL_IF(mStreamId < 0); } CachedStreamBuffer::~CachedStreamBuffer() { LOG_ALWAYS_FATAL_IF(!mProcessed); if (mStreamId >= 0) { LOG_ALWAYS_FATAL_IF(!mBuffer); LOG_ALWAYS_FATAL_IF(GraphicBufferMapper::get().freeBuffer(mBuffer) != NO_ERROR); } } void CachedStreamBuffer::importAcquireFence(const NativeHandle& fence) { LOG_ALWAYS_FATAL_IF(!mProcessed); mAcquireFence = importAidlNativeHandleFence(fence); mProcessed = false; } bool CachedStreamBuffer::waitAcquireFence(const unsigned timeoutMs) { if (mAcquireFence.ok()) { if (sync_wait(mAcquireFence.get(), timeoutMs)) { return FAILURE(false); } else { mAcquireFence.reset(); return true; } } else { return true; } } StreamBuffer CachedStreamBuffer::finish(const bool success) { using aidl::android::hardware::camera::device::BufferStatus; LOG_ALWAYS_FATAL_IF(mProcessed); LOG_ALWAYS_FATAL_IF(!mBufferId); LOG_ALWAYS_FATAL_IF(mStreamId < 0); StreamBuffer sb; sb.streamId = mStreamId; sb.bufferId = mBufferId; sb.status = success ? BufferStatus::OK : BufferStatus::ERROR; sb.releaseFence = moveFenceToAidlNativeHandle(std::move(mAcquireFence)); mProcessed = true; return sb; } } // namespace implementation } // namespace provider } // namespace camera } // namespace hardware } // namespace android