1 /* 2 * Copyright 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define LOG_TAG "AAudio" 18 //#define LOG_NDEBUG 0 19 #include <utils/Log.h> 20 21 #include <stdint.h> 22 #include <stdio.h> 23 24 #include <sys/mman.h> 25 #include <aaudio/AAudio.h> 26 27 #include <android-base/unique_fd.h> 28 #include <binder/Parcelable.h> 29 #include <utility/AAudioUtilities.h> 30 31 #include "binding/SharedMemoryParcelable.h" 32 33 using android::base::unique_fd; 34 using android::NO_ERROR; 35 using android::status_t; 36 using android::Parcel; 37 using android::Parcelable; 38 39 using namespace aaudio; 40 41 SharedMemoryParcelable::SharedMemoryParcelable() {} 42 SharedMemoryParcelable::~SharedMemoryParcelable() {}; 43 44 void SharedMemoryParcelable::setup(const unique_fd& fd, int32_t sizeInBytes) { 45 mFd.reset(dup(fd.get())); // store a duplicate fd 46 ALOGV("SharedMemoryParcelable::setup(%d -> %d, %d) this = %p\n", 47 fd.get(), mFd.get(), sizeInBytes, this); 48 mSizeInBytes = sizeInBytes; 49 } 50 51 status_t SharedMemoryParcelable::writeToParcel(Parcel* parcel) const { 52 status_t status = parcel->writeInt32(mSizeInBytes); 53 if (status != NO_ERROR) return status; 54 if (mSizeInBytes > 0) { 55 ALOGV("SharedMemoryParcelable::writeToParcel() mFd = %d, this = %p\n", mFd.get(), this); 56 status = parcel->writeUniqueFileDescriptor(mFd); 57 ALOGE_IF(status != NO_ERROR, "SharedMemoryParcelable writeDupFileDescriptor failed : %d", 58 status); 59 } 60 return status; 61 } 62 63 status_t SharedMemoryParcelable::readFromParcel(const Parcel* parcel) { 64 status_t status = parcel->readInt32(&mSizeInBytes); 65 if (status != NO_ERROR) { 66 return status; 67 } 68 if (mSizeInBytes > 0) { 69 // The Parcel owns the file descriptor and will close it later. 70 unique_fd mmapFd; 71 status = parcel->readUniqueFileDescriptor(&mmapFd); 72 if (status != NO_ERROR) { 73 ALOGE("SharedMemoryParcelable::readFromParcel() readUniqueFileDescriptor() failed : %d", 74 status); 75 } else { 76 // Resolve the memory now while we still have the FD from the Parcel. 77 // Closing the FD will not affect the shared memory once mmap() has been called. 78 status = AAudioConvert_androidToAAudioResult(resolveSharedMemory(mmapFd)); 79 } 80 } 81 return status; 82 } 83 84 aaudio_result_t SharedMemoryParcelable::close() { 85 if (mResolvedAddress != MMAP_UNRESOLVED_ADDRESS) { 86 int err = munmap(mResolvedAddress, mSizeInBytes); 87 if (err < 0) { 88 ALOGE("SharedMemoryParcelable::close() munmap() failed %d", err); 89 return AAudioConvert_androidToAAudioResult(err); 90 } 91 mResolvedAddress = MMAP_UNRESOLVED_ADDRESS; 92 } 93 return AAUDIO_OK; 94 } 95 96 aaudio_result_t SharedMemoryParcelable::resolveSharedMemory(const unique_fd& fd) { 97 mResolvedAddress = (uint8_t *) mmap(0, mSizeInBytes, PROT_READ | PROT_WRITE, 98 MAP_SHARED, fd.get(), 0); 99 if (mResolvedAddress == MMAP_UNRESOLVED_ADDRESS) { 100 ALOGE("SharedMemoryParcelable mmap() failed for fd = %d, errno = %s", 101 fd.get(), strerror(errno)); 102 return AAUDIO_ERROR_INTERNAL; 103 } 104 return AAUDIO_OK; 105 } 106 107 aaudio_result_t SharedMemoryParcelable::resolve(int32_t offsetInBytes, int32_t sizeInBytes, 108 void **regionAddressPtr) { 109 if (offsetInBytes < 0) { 110 ALOGE("SharedMemoryParcelable illegal offsetInBytes = %d", offsetInBytes); 111 return AAUDIO_ERROR_OUT_OF_RANGE; 112 } else if ((offsetInBytes + sizeInBytes) > mSizeInBytes) { 113 ALOGE("SharedMemoryParcelable out of range, offsetInBytes = %d, " 114 "sizeInBytes = %d, mSizeInBytes = %d", 115 offsetInBytes, sizeInBytes, mSizeInBytes); 116 return AAUDIO_ERROR_OUT_OF_RANGE; 117 } 118 119 aaudio_result_t result = AAUDIO_OK; 120 121 if (mResolvedAddress == MMAP_UNRESOLVED_ADDRESS) { 122 if (mFd.get() != -1) { 123 result = resolveSharedMemory(mFd); 124 } else { 125 ALOGE("SharedMemoryParcelable has no file descriptor for shared memory."); 126 result = AAUDIO_ERROR_INTERNAL; 127 } 128 } 129 130 if (result == AAUDIO_OK && mResolvedAddress != MMAP_UNRESOLVED_ADDRESS) { 131 *regionAddressPtr = mResolvedAddress + offsetInBytes; 132 ALOGV("SharedMemoryParcelable mResolvedAddress = %p", mResolvedAddress); 133 ALOGV("SharedMemoryParcelable offset by %d, *regionAddressPtr = %p", 134 offsetInBytes, *regionAddressPtr); 135 } 136 return result; 137 } 138 139 int32_t SharedMemoryParcelable::getSizeInBytes() { 140 return mSizeInBytes; 141 } 142 143 aaudio_result_t SharedMemoryParcelable::validate() { 144 if (mSizeInBytes < 0 || mSizeInBytes >= MAX_MMAP_SIZE_BYTES) { 145 ALOGE("SharedMemoryParcelable invalid mSizeInBytes = %d", mSizeInBytes); 146 return AAUDIO_ERROR_OUT_OF_RANGE; 147 } 148 return AAUDIO_OK; 149 } 150 151 void SharedMemoryParcelable::dump() { 152 ALOGD("SharedMemoryParcelable mFd = %d", mFd.get()); 153 ALOGD("SharedMemoryParcelable mSizeInBytes = %d", mSizeInBytes); 154 ALOGD("SharedMemoryParcelable mResolvedAddress = %p", mResolvedAddress); 155 } 156