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 17fbf031e8f197c916ae9c399f42926494ebdeb497Phil Burk#define LOG_TAG "SharedMemoryParcelable" 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 46fbf031e8f197c916ae9c399f42926494ebdeb497Phil Burk ALOGV("setup(%d -> %d, %d) this = %p\n", fd.get(), mFd.get(), sizeInBytes, this); 47204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mSizeInBytes = sizeInBytes; 48204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 49204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 50204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkstatus_t SharedMemoryParcelable::writeToParcel(Parcel* parcel) const { 51a5891f427bbd57914090f3260430b82f6879ec8dPhil Burk status_t status = AAudioConvert_aaudioToAndroidStatus(validate()); 52a5891f427bbd57914090f3260430b82f6879ec8dPhil Burk if (status != NO_ERROR) return status; 53a5891f427bbd57914090f3260430b82f6879ec8dPhil Burk 54a5891f427bbd57914090f3260430b82f6879ec8dPhil Burk status = parcel->writeInt32(mSizeInBytes); 55c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk if (status != NO_ERROR) return status; 56204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (mSizeInBytes > 0) { 57fbf031e8f197c916ae9c399f42926494ebdeb497Phil Burk ALOGV("writeToParcel() mFd = %d, this = %p\n", mFd.get(), this); 58e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk status = parcel->writeUniqueFileDescriptor(mFd); 59942bdc0aebc88dc8b12c0e7742ec0003bbb8b80fPhil Burk ALOGE_IF(status != NO_ERROR, "SharedMemoryParcelable writeDupFileDescriptor failed : %d", 60942bdc0aebc88dc8b12c0e7742ec0003bbb8b80fPhil Burk status); 61204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 62c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk return status; 63204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 64204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 65204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkstatus_t SharedMemoryParcelable::readFromParcel(const Parcel* parcel) { 66c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk status_t status = parcel->readInt32(&mSizeInBytes); 67a5891f427bbd57914090f3260430b82f6879ec8dPhil Burk if (status != NO_ERROR) goto error; 68a5891f427bbd57914090f3260430b82f6879ec8dPhil Burk 69204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (mSizeInBytes > 0) { 70e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk // The Parcel owns the file descriptor and will close it later. 71e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk unique_fd mmapFd; 72e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk status = parcel->readUniqueFileDescriptor(&mmapFd); 73e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk if (status != NO_ERROR) { 74fbf031e8f197c916ae9c399f42926494ebdeb497Phil Burk ALOGE("readFromParcel() readUniqueFileDescriptor() failed : %d", status); 75a5891f427bbd57914090f3260430b82f6879ec8dPhil Burk goto error; 76c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk } 77a5891f427bbd57914090f3260430b82f6879ec8dPhil Burk 78a5891f427bbd57914090f3260430b82f6879ec8dPhil Burk // Resolve the memory now while we still have the FD from the Parcel. 79a5891f427bbd57914090f3260430b82f6879ec8dPhil Burk // Closing the FD will not affect the shared memory once mmap() has been called. 80a5891f427bbd57914090f3260430b82f6879ec8dPhil Burk aaudio_result_t result = resolveSharedMemory(mmapFd); 81a5891f427bbd57914090f3260430b82f6879ec8dPhil Burk status = AAudioConvert_aaudioToAndroidStatus(result); 82a5891f427bbd57914090f3260430b82f6879ec8dPhil Burk if (status != NO_ERROR) goto error; 83204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 84a5891f427bbd57914090f3260430b82f6879ec8dPhil Burk 85a5891f427bbd57914090f3260430b82f6879ec8dPhil Burk return AAudioConvert_aaudioToAndroidStatus(validate()); 86a5891f427bbd57914090f3260430b82f6879ec8dPhil Burk 87a5891f427bbd57914090f3260430b82f6879ec8dPhil Burkerror: 88c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk return status; 89204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 90204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 91c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burkaaudio_result_t SharedMemoryParcelable::close() { 92478d5df3a0e1693669f5809176d5c7f6e8c9aa88Phil Burk if (mResolvedAddress != MMAP_UNRESOLVED_ADDRESS) { 93c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk int err = munmap(mResolvedAddress, mSizeInBytes); 94c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk if (err < 0) { 95fbf031e8f197c916ae9c399f42926494ebdeb497Phil Burk ALOGE("close() munmap() failed %d", err); 96c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk return AAudioConvert_androidToAAudioResult(err); 97c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk } 98478d5df3a0e1693669f5809176d5c7f6e8c9aa88Phil Burk mResolvedAddress = MMAP_UNRESOLVED_ADDRESS; 99c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk } 100e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk return AAUDIO_OK; 101e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk} 102e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk 103e72481c5c16d401c776e0ba49b84b80223769b91Phil Burkaaudio_result_t SharedMemoryParcelable::resolveSharedMemory(const unique_fd& fd) { 104e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk mResolvedAddress = (uint8_t *) mmap(0, mSizeInBytes, PROT_READ | PROT_WRITE, 105e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk MAP_SHARED, fd.get(), 0); 106e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk if (mResolvedAddress == MMAP_UNRESOLVED_ADDRESS) { 107fbf031e8f197c916ae9c399f42926494ebdeb497Phil Burk ALOGE("mmap() failed for fd = %d, errno = %s", fd.get(), strerror(errno)); 108e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk return AAUDIO_ERROR_INTERNAL; 109c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk } 110c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk return AAUDIO_OK; 111c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk} 112204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 1135ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t SharedMemoryParcelable::resolve(int32_t offsetInBytes, int32_t sizeInBytes, 114204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk void **regionAddressPtr) { 115204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (offsetInBytes < 0) { 116fbf031e8f197c916ae9c399f42926494ebdeb497Phil Burk ALOGE("illegal offsetInBytes = %d", offsetInBytes); 1175ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_OUT_OF_RANGE; 118204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } else if ((offsetInBytes + sizeInBytes) > mSizeInBytes) { 119fbf031e8f197c916ae9c399f42926494ebdeb497Phil Burk ALOGE("out of range, offsetInBytes = %d, " 120e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk "sizeInBytes = %d, mSizeInBytes = %d", 121204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk offsetInBytes, sizeInBytes, mSizeInBytes); 1225ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_OUT_OF_RANGE; 123204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 124e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk 125e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk aaudio_result_t result = AAUDIO_OK; 126e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk 127478d5df3a0e1693669f5809176d5c7f6e8c9aa88Phil Burk if (mResolvedAddress == MMAP_UNRESOLVED_ADDRESS) { 128e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk if (mFd.get() != -1) { 129e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk result = resolveSharedMemory(mFd); 130e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk } else { 131fbf031e8f197c916ae9c399f42926494ebdeb497Phil Burk ALOGE("has no file descriptor for shared memory."); 132e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk result = AAUDIO_ERROR_INTERNAL; 133204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 134204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 135e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk 136e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk if (result == AAUDIO_OK && mResolvedAddress != MMAP_UNRESOLVED_ADDRESS) { 137e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk *regionAddressPtr = mResolvedAddress + offsetInBytes; 138fbf031e8f197c916ae9c399f42926494ebdeb497Phil Burk ALOGV("mResolvedAddress = %p", mResolvedAddress); 139fbf031e8f197c916ae9c399f42926494ebdeb497Phil Burk ALOGV("offset by %d, *regionAddressPtr = %p", offsetInBytes, *regionAddressPtr); 140e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk } 141e72481c5c16d401c776e0ba49b84b80223769b91Phil Burk return result; 142204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 143204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 144204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkint32_t SharedMemoryParcelable::getSizeInBytes() { 145204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return mSizeInBytes; 146204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 147204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 148a5891f427bbd57914090f3260430b82f6879ec8dPhil Burkaaudio_result_t SharedMemoryParcelable::validate() const { 1493df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk if (mSizeInBytes < 0 || mSizeInBytes >= MAX_MMAP_SIZE_BYTES) { 150fbf031e8f197c916ae9c399f42926494ebdeb497Phil Burk ALOGE("invalid mSizeInBytes = %d", mSizeInBytes); 1513df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk return AAUDIO_ERROR_OUT_OF_RANGE; 152204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 1535ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_OK; 154204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 155204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 156204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkvoid SharedMemoryParcelable::dump() { 157fbf031e8f197c916ae9c399f42926494ebdeb497Phil Burk ALOGD("mFd = %d", mFd.get()); 158fbf031e8f197c916ae9c399f42926494ebdeb497Phil Burk ALOGD("mSizeInBytes = %d", mSizeInBytes); 159fbf031e8f197c916ae9c399f42926494ebdeb497Phil Burk ALOGD("mResolvedAddress = %p", mResolvedAddress); 160204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 161