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