/* * 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. */ #define LOG_TAG "SharedMemoryWrapper" //#define LOG_NDEBUG 0 #include #include #include #include #include "SharedMemoryWrapper.h" namespace aaudio { constexpr int COUNTER_SIZE_IN_BYTES = sizeof(android::fifo_counter_t); constexpr int WRAPPER_SIZE_IN_BYTES = 2 * COUNTER_SIZE_IN_BYTES; SharedMemoryWrapper::SharedMemoryWrapper() { mCounterFd.reset(ashmem_create_region("AAudioSharedMemoryWrapper", WRAPPER_SIZE_IN_BYTES)); if (mCounterFd.get() == -1) { ALOGE("allocate() ashmem_create_region() failed %d", errno); return; } int err = ashmem_set_prot_region(mCounterFd.get(), PROT_READ|PROT_WRITE); if (err < 0) { ALOGE("allocate() ashmem_set_prot_region() failed %d", errno); mCounterFd.reset(); return; } auto tmpPtr = (uint8_t *) mmap(nullptr, WRAPPER_SIZE_IN_BYTES, PROT_READ|PROT_WRITE, MAP_SHARED, mCounterFd.get(), 0); if (tmpPtr == MAP_FAILED) { ALOGE("allocate() mmap() failed %d", errno); mCounterFd.reset(); return; } mCounterMemoryAddress = tmpPtr; mReadCounterAddress = (android::fifo_counter_t*) mCounterMemoryAddress; mWriteCounterAddress = (android::fifo_counter_t*) &mCounterMemoryAddress[COUNTER_SIZE_IN_BYTES]; } SharedMemoryWrapper::~SharedMemoryWrapper() { reset(); if (mCounterMemoryAddress != nullptr) { munmap(mCounterMemoryAddress, COUNTER_SIZE_IN_BYTES); mCounterMemoryAddress = nullptr; } } aaudio_result_t SharedMemoryWrapper::setupFifoBuffer(android::fifo_frames_t bytesPerFrame, android::fifo_frames_t capacityInFrames) { if (mDataFd.get() == -1) { ALOGE("%s data file descriptor is not initialized", __func__); return AAUDIO_ERROR_INTERNAL; } if (mCounterMemoryAddress == nullptr) { ALOGE("%s the counter memory is not allocated correctly", __func__); return AAUDIO_ERROR_INTERNAL; } mSharedMemorySizeInBytes = bytesPerFrame * capacityInFrames; auto tmpPtr = (uint8_t *) mmap(nullptr, mSharedMemorySizeInBytes, PROT_READ|PROT_WRITE, MAP_SHARED, mDataFd.get(), 0); if (tmpPtr == MAP_FAILED) { ALOGE("allocate() mmap() failed %d", errno); return AAUDIO_ERROR_INTERNAL; } mSharedMemory = tmpPtr; mFifoBuffer = std::make_shared( bytesPerFrame, capacityInFrames, mReadCounterAddress, mWriteCounterAddress, mSharedMemory); return AAUDIO_OK; } void SharedMemoryWrapper::reset() { mFifoBuffer.reset(); if (mSharedMemory != nullptr) { munmap(mSharedMemory, mSharedMemorySizeInBytes); mSharedMemory = nullptr; } mDataFd.reset(); } void SharedMemoryWrapper::fillParcelable( AudioEndpointParcelable* endpointParcelable, RingBufferParcelable &ringBufferParcelable, int32_t bytesPerFrame, int32_t framesPerBurst, int32_t capacityInFrames, CounterFilling counterFilling) { const int capacityInBytes = bytesPerFrame * capacityInFrames; const int dataFdIndex = endpointParcelable->addFileDescriptor(mDataFd, mSharedMemorySizeInBytes); ringBufferParcelable.setBytesPerFrame(bytesPerFrame); ringBufferParcelable.setFramesPerBurst(framesPerBurst); ringBufferParcelable.setCapacityInFrames(capacityInFrames); if (mCounterFd.get() == -1 || counterFilling == NONE) { // Failed to create shared memory for read/write counter or requesting no filling counters. ALOGD("%s no counter is filled, counterFd=%d", __func__, mCounterFd.get()); ringBufferParcelable.setupMemory(dataFdIndex, 0, capacityInBytes); } else { int counterFdIndex = endpointParcelable->addFileDescriptor(mCounterFd, WRAPPER_SIZE_IN_BYTES); const int readCounterSize = (counterFilling & READ) == NONE ? 0 : COUNTER_SIZE_IN_BYTES; const int writeCounterSize = (counterFilling & WRITE) == NONE ? 0 : COUNTER_SIZE_IN_BYTES; ALOGD("%s counterFdIndex=%d readCounterSize=%d, writeCounterSize=%d", __func__, counterFdIndex, readCounterSize, writeCounterSize); ringBufferParcelable.setupMemory( {dataFdIndex, 0 /*offset*/, capacityInBytes}, {counterFdIndex, 0 /*offset*/, readCounterSize}, {counterFdIndex, COUNTER_SIZE_IN_BYTES, writeCounterSize}); } } } // namespace aaudio