|  | /* | 
|  | * Copyright 2016 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 "RingBufferParcelable" | 
|  | //#define LOG_NDEBUG 0 | 
|  | #include <utils/Log.h> | 
|  |  | 
|  | #include <stdint.h> | 
|  |  | 
|  | #include <binder/Parcelable.h> | 
|  | #include <utility/AAudioUtilities.h> | 
|  |  | 
|  | #include "binding/AAudioServiceDefinitions.h" | 
|  | #include "binding/SharedRegionParcelable.h" | 
|  | #include "binding/RingBufferParcelable.h" | 
|  |  | 
|  | using namespace aaudio; | 
|  |  | 
|  | RingBufferParcelable::RingBufferParcelable(const RingBuffer& parcelable) | 
|  | : mReadCounterParcelable(parcelable.readCounterParcelable), | 
|  | mWriteCounterParcelable(parcelable.writeCounterParcelable), | 
|  | mDataParcelable(parcelable.dataParcelable), | 
|  | mBytesPerFrame(parcelable.bytesPerFrame), | 
|  | mFramesPerBurst(parcelable.framesPerBurst), | 
|  | mCapacityInFrames(parcelable.capacityInFrames), | 
|  | mFlags(static_cast<RingbufferFlags>(parcelable.flags)) { | 
|  | static_assert(sizeof(mFlags) == sizeof(parcelable.flags)); | 
|  | } | 
|  |  | 
|  | RingBuffer RingBufferParcelable::parcelable() const { | 
|  | RingBuffer result; | 
|  | result.readCounterParcelable = mReadCounterParcelable.parcelable(); | 
|  | result.writeCounterParcelable = mWriteCounterParcelable.parcelable(); | 
|  | result.dataParcelable = mDataParcelable.parcelable(); | 
|  | result.bytesPerFrame = mBytesPerFrame; | 
|  | result.framesPerBurst = mFramesPerBurst; | 
|  | result.capacityInFrames = mCapacityInFrames; | 
|  | static_assert(sizeof(mFlags) == sizeof(result.flags)); | 
|  | result.flags = static_cast<int32_t>(mFlags); | 
|  | return result; | 
|  | } | 
|  |  | 
|  | // TODO This assumes that all three use the same SharedMemoryParcelable | 
|  | void RingBufferParcelable::setupMemory(int32_t sharedMemoryIndex, | 
|  | int32_t dataMemoryOffset, | 
|  | int32_t dataSizeInBytes, | 
|  | int32_t readCounterOffset, | 
|  | int32_t writeCounterOffset, | 
|  | int32_t counterSizeBytes) { | 
|  | mReadCounterParcelable.setup({sharedMemoryIndex, readCounterOffset, counterSizeBytes}); | 
|  | mWriteCounterParcelable.setup({sharedMemoryIndex, writeCounterOffset, counterSizeBytes}); | 
|  | mDataParcelable.setup({sharedMemoryIndex, dataMemoryOffset, dataSizeInBytes}); | 
|  | } | 
|  |  | 
|  | void RingBufferParcelable::setupMemory(int32_t sharedMemoryIndex, | 
|  | int32_t dataMemoryOffset, | 
|  | int32_t dataSizeInBytes) { | 
|  | mReadCounterParcelable.setup({sharedMemoryIndex, 0, 0}); | 
|  | mWriteCounterParcelable.setup({sharedMemoryIndex, 0, 0}); | 
|  | mDataParcelable.setup({sharedMemoryIndex, dataMemoryOffset, dataSizeInBytes}); | 
|  | } | 
|  |  | 
|  | void RingBufferParcelable::setupMemory( | 
|  | const SharedRegionParcelable::MemoryInfoTuple& dataMemoryInfo, | 
|  | const SharedRegionParcelable::MemoryInfoTuple& readCounterInfo, | 
|  | const SharedRegionParcelable::MemoryInfoTuple& writeCounterInfo) { | 
|  | mReadCounterParcelable.setup(readCounterInfo); | 
|  | mWriteCounterParcelable.setup(writeCounterInfo); | 
|  | mDataParcelable.setup(dataMemoryInfo); | 
|  | } | 
|  |  | 
|  | int32_t RingBufferParcelable::getBytesPerFrame() const { | 
|  | return mBytesPerFrame; | 
|  | } | 
|  |  | 
|  | void RingBufferParcelable::setBytesPerFrame(int32_t bytesPerFrame) { | 
|  | mBytesPerFrame = bytesPerFrame; | 
|  | } | 
|  |  | 
|  | int32_t RingBufferParcelable::getFramesPerBurst() const { | 
|  | return mFramesPerBurst; | 
|  | } | 
|  |  | 
|  | void RingBufferParcelable::setFramesPerBurst(int32_t framesPerBurst) { | 
|  | mFramesPerBurst = framesPerBurst; | 
|  | } | 
|  |  | 
|  | int32_t RingBufferParcelable::getCapacityInFrames() const { | 
|  | return mCapacityInFrames; | 
|  | } | 
|  |  | 
|  | void RingBufferParcelable::setCapacityInFrames(int32_t capacityInFrames) { | 
|  | mCapacityInFrames = capacityInFrames; | 
|  | } | 
|  |  | 
|  | aaudio_result_t RingBufferParcelable::resolve(SharedMemoryParcelable *memoryParcels, RingBufferDescriptor *descriptor) { | 
|  | aaudio_result_t result; | 
|  |  | 
|  | result = mReadCounterParcelable.resolve(memoryParcels, | 
|  | (void **) &descriptor->readCounterAddress); | 
|  | if (result != AAUDIO_OK) { | 
|  | return result; | 
|  | } | 
|  |  | 
|  | result = mWriteCounterParcelable.resolve(memoryParcels, | 
|  | (void **) &descriptor->writeCounterAddress); | 
|  | if (result != AAUDIO_OK) { | 
|  | return result; | 
|  | } | 
|  |  | 
|  | result = mDataParcelable.resolve(memoryParcels, (void **) &descriptor->dataAddress); | 
|  | if (result != AAUDIO_OK) { | 
|  | return result; | 
|  | } | 
|  |  | 
|  | descriptor->bytesPerFrame = mBytesPerFrame; | 
|  | descriptor->framesPerBurst = mFramesPerBurst; | 
|  | descriptor->capacityInFrames = mCapacityInFrames; | 
|  | descriptor->flags = mFlags; | 
|  | return AAUDIO_OK; | 
|  | } | 
|  |  | 
|  | void RingBufferParcelable::updateMemory(const RingBufferParcelable& parcelable, | 
|  | const std::map<int32_t, int32_t>& memoryIndexMap) { | 
|  | setupMemory(parcelable.mDataParcelable.getMemoryInfo(&memoryIndexMap), | 
|  | parcelable.mReadCounterParcelable.getMemoryInfo(&memoryIndexMap), | 
|  | parcelable.mWriteCounterParcelable.getMemoryInfo(&memoryIndexMap)); | 
|  | setBytesPerFrame(parcelable.getBytesPerFrame()); | 
|  | setFramesPerBurst(parcelable.getFramesPerBurst()); | 
|  | setCapacityInFrames(parcelable.getCapacityInFrames()); | 
|  | } | 
|  |  | 
|  | aaudio_result_t RingBufferParcelable::validate() const { | 
|  | if (mCapacityInFrames < 0 || mCapacityInFrames >= 32 * 1024) { | 
|  | ALOGE("invalid mCapacityInFrames = %d", mCapacityInFrames); | 
|  | return AAUDIO_ERROR_INTERNAL; | 
|  | } | 
|  | if (mBytesPerFrame < 0 || mBytesPerFrame >= 256) { | 
|  | ALOGE("invalid mBytesPerFrame = %d", mBytesPerFrame); | 
|  | return AAUDIO_ERROR_INTERNAL; | 
|  | } | 
|  | if (mFramesPerBurst < 0 || mFramesPerBurst >= 16 * 1024) { | 
|  | ALOGE("invalid mFramesPerBurst = %d", mFramesPerBurst); | 
|  | return AAUDIO_ERROR_INTERNAL; | 
|  | } | 
|  | return AAUDIO_OK; | 
|  | } | 
|  |  | 
|  | void RingBufferParcelable::dump() { | 
|  | ALOGD("mCapacityInFrames = %d ---------", mCapacityInFrames); | 
|  | if (mCapacityInFrames > 0) { | 
|  | ALOGD("mBytesPerFrame = %d", mBytesPerFrame); | 
|  | ALOGD("mFramesPerBurst = %d", mFramesPerBurst); | 
|  | ALOGD("mFlags = %u", mFlags); | 
|  | mReadCounterParcelable.dump(); | 
|  | mWriteCounterParcelable.dump(); | 
|  | mDataParcelable.dump(); | 
|  | } | 
|  | } |