SharedMemoryParcelable.cpp revision e72481c5c16d401c776e0ba49b84b80223769b91
1204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk/* 2204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk * Copyright 2016 The Android Open Source Project 3204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk * 4204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk * Licensed under the Apache License, Version 2.0 (the "License"); 5204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk * you may not use this file except in compliance with the License. 6204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk * You may obtain a copy of the License at 7204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk * 8204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk * http://www.apache.org/licenses/LICENSE-2.0 9204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk * 10204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk * Unless required by applicable law or agreed to in writing, software 11204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk * distributed under the License is distributed on an "AS IS" BASIS, 12204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk * See the License for the specific language governing permissions and 14204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk * limitations under the License. 15204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk */ 16204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 17c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#define LOG_TAG "AAudio" 18c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk//#define LOG_NDEBUG 0 19c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include <utils/Log.h> 20c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 21204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#include <stdint.h> 22c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include <stdio.h> 23204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 24204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#include <sys/mman.h> 25a4eb0d86a29be2763be5fac51727858d5095794bPhil Burk#include <aaudio/AAudio.h> 26204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 27e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk#include <android-base/unique_fd.h> 28204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#include <binder/Parcelable.h> 29c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include <utility/AAudioUtilities.h> 30204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 31204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#include "binding/SharedMemoryParcelable.h" 32204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 33e72481c5c16d401c776e0ba49b84b80223769b91Phil Burkusing android::base::unique_fd; 34204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkusing android::NO_ERROR; 35204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkusing android::status_t; 36204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkusing android::Parcel; 37204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkusing android::Parcelable; 38204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 395ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkusing namespace aaudio; 40204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 41204a163c86f357a878873fe7d4c4164f3d55c9b6Phil BurkSharedMemoryParcelable::SharedMemoryParcelable() {} 42204a163c86f357a878873fe7d4c4164f3d55c9b6Phil BurkSharedMemoryParcelable::~SharedMemoryParcelable() {}; 43204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 44e72481c5c16d401c776e0ba49b84b80223769b91Phil Burkvoid SharedMemoryParcelable::setup(const unique_fd& fd, int32_t sizeInBytes) { 45e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk mFd.reset(dup(fd.get())); // store a duplicate fd 46e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk ALOGV("SharedMemoryParcelable::setup(%d -> %d, %d) this = %p\n", 47e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk fd.get(), mFd.get(), sizeInBytes, this); 48204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mSizeInBytes = sizeInBytes; 49204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 50204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 51204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkstatus_t SharedMemoryParcelable::writeToParcel(Parcel* parcel) const { 52c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk status_t status = parcel->writeInt32(mSizeInBytes); 53c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk if (status != NO_ERROR) return status; 54204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (mSizeInBytes > 0) { 55e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk ALOGV("SharedMemoryParcelable::writeToParcel() mFd = %d, this = %p\n", mFd.get(), this); 56e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk status = parcel->writeUniqueFileDescriptor(mFd); 57942bdc0aebc88dc8b12c0e7742ec0003bbb8b80fPhil Burk ALOGE_IF(status != NO_ERROR, "SharedMemoryParcelable writeDupFileDescriptor failed : %d", 58942bdc0aebc88dc8b12c0e7742ec0003bbb8b80fPhil Burk status); 59204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 60c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk return status; 61204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 62204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 63204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkstatus_t SharedMemoryParcelable::readFromParcel(const Parcel* parcel) { 64c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk status_t status = parcel->readInt32(&mSizeInBytes); 65c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk if (status != NO_ERROR) { 66c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk return status; 67c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk } 68204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (mSizeInBytes > 0) { 69e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk // The Parcel owns the file descriptor and will close it later. 70e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk unique_fd mmapFd; 71e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk status = parcel->readUniqueFileDescriptor(&mmapFd); 72e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk if (status != NO_ERROR) { 73e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk ALOGE("SharedMemoryParcelable::readFromParcel() readUniqueFileDescriptor() failed : %d", 74e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk status); 75e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk } else { 76e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk // Resolve the memory now while we still have the FD from the Parcel. 77e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk // Closing the FD will not affect the shared memory once mmap() has been called. 78e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk status = AAudioConvert_androidToAAudioResult(resolveSharedMemory(mmapFd)); 79c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk } 80204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 81c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk return status; 82204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 83204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 84c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burkaaudio_result_t SharedMemoryParcelable::close() { 85478d5df3a0e1693669f5809176d5c7f6e8c9aa88Phil Burk if (mResolvedAddress != MMAP_UNRESOLVED_ADDRESS) { 86c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk int err = munmap(mResolvedAddress, mSizeInBytes); 87c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk if (err < 0) { 88c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk ALOGE("SharedMemoryParcelable::close() munmap() failed %d", err); 89c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk return AAudioConvert_androidToAAudioResult(err); 90c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk } 91478d5df3a0e1693669f5809176d5c7f6e8c9aa88Phil Burk mResolvedAddress = MMAP_UNRESOLVED_ADDRESS; 92c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk } 93e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk return AAUDIO_OK; 94e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk} 95e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk 96e72481c5c16d401c776e0ba49b84b80223769b91Phil Burkaaudio_result_t SharedMemoryParcelable::resolveSharedMemory(const unique_fd& fd) { 97e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk mResolvedAddress = (uint8_t *) mmap(0, mSizeInBytes, PROT_READ | PROT_WRITE, 98e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk MAP_SHARED, fd.get(), 0); 99e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk if (mResolvedAddress == MMAP_UNRESOLVED_ADDRESS) { 100e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk ALOGE("SharedMemoryParcelable mmap() failed for fd = %d, errno = %s", 101e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk fd.get(), strerror(errno)); 102e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk return AAUDIO_ERROR_INTERNAL; 103c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk } 104c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk return AAUDIO_OK; 105c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk} 106204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 1075ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t SharedMemoryParcelable::resolve(int32_t offsetInBytes, int32_t sizeInBytes, 108204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk void **regionAddressPtr) { 109204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (offsetInBytes < 0) { 110204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGE("SharedMemoryParcelable illegal offsetInBytes = %d", offsetInBytes); 1115ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_OUT_OF_RANGE; 112204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } else if ((offsetInBytes + sizeInBytes) > mSizeInBytes) { 113204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGE("SharedMemoryParcelable out of range, offsetInBytes = %d, " 114e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk "sizeInBytes = %d, mSizeInBytes = %d", 115204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk offsetInBytes, sizeInBytes, mSizeInBytes); 1165ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_OUT_OF_RANGE; 117204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 118e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk 119e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk aaudio_result_t result = AAUDIO_OK; 120e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk 121478d5df3a0e1693669f5809176d5c7f6e8c9aa88Phil Burk if (mResolvedAddress == MMAP_UNRESOLVED_ADDRESS) { 122e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk if (mFd.get() != -1) { 123e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk result = resolveSharedMemory(mFd); 124e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk } else { 125e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk ALOGE("SharedMemoryParcelable has no file descriptor for shared memory."); 126e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk result = AAUDIO_ERROR_INTERNAL; 127204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 128204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 129e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk 130e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk if (result == AAUDIO_OK && mResolvedAddress != MMAP_UNRESOLVED_ADDRESS) { 131e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk *regionAddressPtr = mResolvedAddress + offsetInBytes; 132e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk ALOGV("SharedMemoryParcelable mResolvedAddress = %p", mResolvedAddress); 133e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk ALOGV("SharedMemoryParcelable offset by %d, *regionAddressPtr = %p", 134e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk offsetInBytes, *regionAddressPtr); 135e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk } 136e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk return result; 137204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 138204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 139204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkint32_t SharedMemoryParcelable::getSizeInBytes() { 140204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return mSizeInBytes; 141204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 142204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 1435ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t SharedMemoryParcelable::validate() { 1443df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk if (mSizeInBytes < 0 || mSizeInBytes >= MAX_MMAP_SIZE_BYTES) { 145204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGE("SharedMemoryParcelable invalid mSizeInBytes = %d", mSizeInBytes); 1463df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk return AAUDIO_ERROR_OUT_OF_RANGE; 147204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 1485ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_OK; 149204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 150204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 151204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkvoid SharedMemoryParcelable::dump() { 152e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk ALOGD("SharedMemoryParcelable mFd = %d", mFd.get()); 153204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("SharedMemoryParcelable mSizeInBytes = %d", mSizeInBytes); 154204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("SharedMemoryParcelable mResolvedAddress = %p", mResolvedAddress); 155204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 156