12355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk/*
22355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk * Copyright (C) 2016 The Android Open Source Project
32355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk *
42355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk * Licensed under the Apache License, Version 2.0 (the "License");
52355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk * you may not use this file except in compliance with the License.
62355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk * You may obtain a copy of the License at
72355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk *
82355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk *      http://www.apache.org/licenses/LICENSE-2.0
92355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk *
102355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk * Unless required by applicable law or agreed to in writing, software
112355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk * distributed under the License is distributed on an "AS IS" BASIS,
122355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk * See the License for the specific language governing permissions and
142355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk * limitations under the License.
152355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk */
162355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk
175ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk#define LOG_TAG "AAudioService"
182355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk//#define LOG_NDEBUG 0
192355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk#include <utils/Log.h>
202355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk
21478d5df3a0e1693669f5809176d5c7f6e8c9aa88Phil Burk#include <sys/mman.h>
22478d5df3a0e1693669f5809176d5c7f6e8c9aa88Phil Burk
23c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include "binding/RingBufferParcelable.h"
24c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include "binding/AudioEndpointParcelable.h"
252355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk
262355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk#include "SharedRingBuffer.h"
272355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk
282355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burkusing namespace android;
295ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkusing namespace aaudio;
302355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk
312355edbcacfcb6e852a8707d893aaca788d42fdcPhil BurkSharedRingBuffer::~SharedRingBuffer()
322355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk{
332355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk    if (mSharedMemory != nullptr) {
342355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk        delete mFifoBuffer;
352355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk        munmap(mSharedMemory, mSharedMemorySizeInBytes);
362355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk        mSharedMemory = nullptr;
372355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk    }
38942bdc0aebc88dc8b12c0e7742ec0003bbb8b80fPhil Burk    if (mFileDescriptor != -1) {
39942bdc0aebc88dc8b12c0e7742ec0003bbb8b80fPhil Burk        ALOGV("SharedRingBuffer: LEAK? close(mFileDescriptor = %d)\n", mFileDescriptor);
40942bdc0aebc88dc8b12c0e7742ec0003bbb8b80fPhil Burk        close(mFileDescriptor);
41942bdc0aebc88dc8b12c0e7742ec0003bbb8b80fPhil Burk        mFileDescriptor = -1;
42942bdc0aebc88dc8b12c0e7742ec0003bbb8b80fPhil Burk    }
432355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk}
442355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk
455ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t SharedRingBuffer::allocate(fifo_frames_t   bytesPerFrame,
462355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk                                         fifo_frames_t   capacityInFrames) {
472355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk    mCapacityInFrames = capacityInFrames;
482355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk
492355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk    // Create shared memory large enough to hold the data and the read and write counters.
502355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk    mDataMemorySizeInBytes = bytesPerFrame * capacityInFrames;
512355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk    mSharedMemorySizeInBytes = mDataMemorySizeInBytes + (2 * (sizeof(fifo_counter_t)));
525ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    mFileDescriptor = ashmem_create_region("AAudioSharedRingBuffer", mSharedMemorySizeInBytes);
53942bdc0aebc88dc8b12c0e7742ec0003bbb8b80fPhil Burk    ALOGV("SharedRingBuffer::allocate() LEAK? mFileDescriptor = %d\n", mFileDescriptor);
542355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk    if (mFileDescriptor < 0) {
552355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk        ALOGE("SharedRingBuffer::allocate() ashmem_create_region() failed %d", errno);
565ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAUDIO_ERROR_INTERNAL;
572355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk    }
58942bdc0aebc88dc8b12c0e7742ec0003bbb8b80fPhil Burk
592355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk    int err = ashmem_set_prot_region(mFileDescriptor, PROT_READ|PROT_WRITE); // TODO error handling?
602355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk    if (err < 0) {
612355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk        ALOGE("SharedRingBuffer::allocate() ashmem_set_prot_region() failed %d", errno);
622355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk        close(mFileDescriptor);
635ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAUDIO_ERROR_INTERNAL; // TODO convert errno to a better AAUDIO_ERROR;
642355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk    }
652355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk
662355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk    // Map the fd to memory addresses.
672355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk    mSharedMemory = (uint8_t *) mmap(0, mSharedMemorySizeInBytes,
682355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk                         PROT_READ|PROT_WRITE,
692355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk                         MAP_SHARED,
702355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk                         mFileDescriptor, 0);
712355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk    if (mSharedMemory == MAP_FAILED) {
722355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk        ALOGE("SharedRingBuffer::allocate() mmap() failed %d", errno);
732355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk        close(mFileDescriptor);
745ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAUDIO_ERROR_INTERNAL; // TODO convert errno to a better AAUDIO_ERROR;
752355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk    }
762355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk
772355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk    // Get addresses for our counters and data from the shared memory.
782355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk    fifo_counter_t *readCounterAddress =
792355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk            (fifo_counter_t *) &mSharedMemory[SHARED_RINGBUFFER_READ_OFFSET];
802355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk    fifo_counter_t *writeCounterAddress =
812355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk            (fifo_counter_t *) &mSharedMemory[SHARED_RINGBUFFER_WRITE_OFFSET];
822355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk    uint8_t *dataAddress = &mSharedMemory[SHARED_RINGBUFFER_DATA_OFFSET];
832355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk
84942bdc0aebc88dc8b12c0e7742ec0003bbb8b80fPhil Burk    mFifoBuffer = new FifoBuffer(bytesPerFrame, capacityInFrames,
852355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk                                 readCounterAddress, writeCounterAddress, dataAddress);
86942bdc0aebc88dc8b12c0e7742ec0003bbb8b80fPhil Burk    return AAUDIO_OK;
872355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk}
882355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk
892355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burkvoid SharedRingBuffer::fillParcelable(AudioEndpointParcelable &endpointParcelable,
902355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk                    RingBufferParcelable &ringBufferParcelable) {
912355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk    int fdIndex = endpointParcelable.addFileDescriptor(mFileDescriptor, mSharedMemorySizeInBytes);
922355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk    ringBufferParcelable.setupMemory(fdIndex,
932355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk                                     SHARED_RINGBUFFER_DATA_OFFSET,
942355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk                                     mDataMemorySizeInBytes,
952355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk                                     SHARED_RINGBUFFER_READ_OFFSET,
962355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk                                     SHARED_RINGBUFFER_WRITE_OFFSET,
972355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk                                     sizeof(fifo_counter_t));
982355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk    ringBufferParcelable.setBytesPerFrame(mFifoBuffer->getBytesPerFrame());
992355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk    ringBufferParcelable.setFramesPerBurst(1);
1002355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk    ringBufferParcelable.setCapacityInFrames(mCapacityInFrames);
1012355edbcacfcb6e852a8707d893aaca788d42fdcPhil Burk}
102