1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define LOG_TAG "SharedRingBuffer" 18 //#define LOG_NDEBUG 0 19 #include <utils/Log.h> 20 21 #include <sys/mman.h> 22 23 #include "binding/RingBufferParcelable.h" 24 #include "binding/AudioEndpointParcelable.h" 25 26 #include "SharedRingBuffer.h" 27 28 using namespace android; 29 using namespace aaudio; 30 31 SharedRingBuffer::~SharedRingBuffer() 32 { 33 if (mSharedMemory != nullptr) { 34 delete mFifoBuffer; 35 munmap(mSharedMemory, mSharedMemorySizeInBytes); 36 mSharedMemory = nullptr; 37 } 38 } 39 40 aaudio_result_t SharedRingBuffer::allocate(fifo_frames_t bytesPerFrame, 41 fifo_frames_t capacityInFrames) { 42 mCapacityInFrames = capacityInFrames; 43 44 // Create shared memory large enough to hold the data and the read and write counters. 45 mDataMemorySizeInBytes = bytesPerFrame * capacityInFrames; 46 mSharedMemorySizeInBytes = mDataMemorySizeInBytes + (2 * (sizeof(fifo_counter_t))); 47 mFileDescriptor.reset(ashmem_create_region("AAudioSharedRingBuffer", mSharedMemorySizeInBytes)); 48 if (mFileDescriptor.get() == -1) { 49 ALOGE("allocate() ashmem_create_region() failed %d", errno); 50 return AAUDIO_ERROR_INTERNAL; 51 } 52 ALOGV("allocate() mFileDescriptor = %d\n", mFileDescriptor.get()); 53 54 int err = ashmem_set_prot_region(mFileDescriptor.get(), PROT_READ|PROT_WRITE); // TODO error handling? 55 if (err < 0) { 56 ALOGE("allocate() ashmem_set_prot_region() failed %d", errno); 57 mFileDescriptor.reset(); 58 return AAUDIO_ERROR_INTERNAL; // TODO convert errno to a better AAUDIO_ERROR; 59 } 60 61 // Map the fd to memory addresses. 62 mSharedMemory = (uint8_t *) mmap(0, mSharedMemorySizeInBytes, 63 PROT_READ|PROT_WRITE, 64 MAP_SHARED, 65 mFileDescriptor.get(), 0); 66 if (mSharedMemory == MAP_FAILED) { 67 ALOGE("allocate() mmap() failed %d", errno); 68 mFileDescriptor.reset(); 69 return AAUDIO_ERROR_INTERNAL; // TODO convert errno to a better AAUDIO_ERROR; 70 } 71 72 // Get addresses for our counters and data from the shared memory. 73 fifo_counter_t *readCounterAddress = 74 (fifo_counter_t *) &mSharedMemory[SHARED_RINGBUFFER_READ_OFFSET]; 75 fifo_counter_t *writeCounterAddress = 76 (fifo_counter_t *) &mSharedMemory[SHARED_RINGBUFFER_WRITE_OFFSET]; 77 uint8_t *dataAddress = &mSharedMemory[SHARED_RINGBUFFER_DATA_OFFSET]; 78 79 mFifoBuffer = new FifoBuffer(bytesPerFrame, capacityInFrames, 80 readCounterAddress, writeCounterAddress, dataAddress); 81 return AAUDIO_OK; 82 } 83 84 void SharedRingBuffer::fillParcelable(AudioEndpointParcelable &endpointParcelable, 85 RingBufferParcelable &ringBufferParcelable) { 86 int fdIndex = endpointParcelable.addFileDescriptor(mFileDescriptor, mSharedMemorySizeInBytes); 87 ringBufferParcelable.setupMemory(fdIndex, 88 SHARED_RINGBUFFER_DATA_OFFSET, 89 mDataMemorySizeInBytes, 90 SHARED_RINGBUFFER_READ_OFFSET, 91 SHARED_RINGBUFFER_WRITE_OFFSET, 92 sizeof(fifo_counter_t)); 93 ringBufferParcelable.setBytesPerFrame(mFifoBuffer->getBytesPerFrame()); 94 ringBufferParcelable.setFramesPerBurst(1); 95 ringBufferParcelable.setCapacityInFrames(mCapacityInFrames); 96 } 97