• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <binder/Parcelable.h>
28 #include <utility/AAudioUtilities.h>
29 
30 #include "binding/SharedMemoryParcelable.h"
31 
32 using android::NO_ERROR;
33 using android::status_t;
34 using android::Parcel;
35 using android::Parcelable;
36 
37 using namespace aaudio;
38 
SharedMemoryParcelable()39 SharedMemoryParcelable::SharedMemoryParcelable() {}
~SharedMemoryParcelable()40 SharedMemoryParcelable::~SharedMemoryParcelable() {};
41 
setup(int fd,int32_t sizeInBytes)42 void SharedMemoryParcelable::setup(int fd, int32_t sizeInBytes) {
43     mFd = fd;
44     mSizeInBytes = sizeInBytes;
45 
46 }
47 
writeToParcel(Parcel * parcel) const48 status_t SharedMemoryParcelable::writeToParcel(Parcel* parcel) const {
49     status_t status = parcel->writeInt32(mSizeInBytes);
50     if (status != NO_ERROR) return status;
51     if (mSizeInBytes > 0) {
52         status = parcel->writeDupFileDescriptor(mFd);
53         ALOGE_IF(status != NO_ERROR, "SharedMemoryParcelable writeDupFileDescriptor failed : %d",
54                  status);
55     }
56     return status;
57 }
58 
readFromParcel(const Parcel * parcel)59 status_t SharedMemoryParcelable::readFromParcel(const Parcel* parcel) {
60     status_t status = parcel->readInt32(&mSizeInBytes);
61     if (status != NO_ERROR) {
62         return status;
63     }
64     if (mSizeInBytes > 0) {
65         // Keep the original FD until you are done with the mFd.
66         // If you close it in here then it will prevent mFd from working.
67         mOriginalFd = parcel->readFileDescriptor();
68         ALOGV("SharedMemoryParcelable::readFromParcel() LEAK? mOriginalFd = %d\n", mOriginalFd);
69         mFd = fcntl(mOriginalFd, F_DUPFD_CLOEXEC, 0);
70         ALOGV("SharedMemoryParcelable::readFromParcel() LEAK? mFd = %d\n", mFd);
71         if (mFd == -1) {
72             status = -errno;
73             ALOGE("SharedMemoryParcelable readFromParcel fcntl() failed : %d", status);
74         }
75     }
76     return status;
77 }
78 
close()79 aaudio_result_t SharedMemoryParcelable::close() {
80     if (mResolvedAddress != MMAP_UNRESOLVED_ADDRESS) {
81         int err = munmap(mResolvedAddress, mSizeInBytes);
82         if (err < 0) {
83             ALOGE("SharedMemoryParcelable::close() munmap() failed %d", err);
84             return AAudioConvert_androidToAAudioResult(err);
85         }
86         mResolvedAddress = MMAP_UNRESOLVED_ADDRESS;
87     }
88     if (mFd != -1) {
89         ALOGV("SharedMemoryParcelable::close() LEAK? mFd = %d\n", mFd);
90         ::close(mFd);
91         mFd = -1;
92     }
93     if (mOriginalFd != -1) {
94         ALOGV("SharedMemoryParcelable::close() LEAK? mOriginalFd = %d\n", mOriginalFd);
95         ::close(mOriginalFd);
96         mOriginalFd = -1;
97     }
98     return AAUDIO_OK;
99 }
100 
resolve(int32_t offsetInBytes,int32_t sizeInBytes,void ** regionAddressPtr)101 aaudio_result_t SharedMemoryParcelable::resolve(int32_t offsetInBytes, int32_t sizeInBytes,
102                                               void **regionAddressPtr) {
103 
104     if (offsetInBytes < 0) {
105         ALOGE("SharedMemoryParcelable illegal offsetInBytes = %d", offsetInBytes);
106         return AAUDIO_ERROR_OUT_OF_RANGE;
107     } else if ((offsetInBytes + sizeInBytes) > mSizeInBytes) {
108         ALOGE("SharedMemoryParcelable out of range, offsetInBytes = %d, "
109               "sizeInBytes = %d, mSizeInBytes = %d",
110               offsetInBytes, sizeInBytes, mSizeInBytes);
111         return AAUDIO_ERROR_OUT_OF_RANGE;
112     }
113     if (mResolvedAddress == MMAP_UNRESOLVED_ADDRESS) {
114         mResolvedAddress = (uint8_t *) mmap(0, mSizeInBytes, PROT_READ|PROT_WRITE,
115                                           MAP_SHARED, mFd, 0);
116         if (mResolvedAddress == MMAP_UNRESOLVED_ADDRESS) {
117             ALOGE("SharedMemoryParcelable mmap failed for fd = %d, errno = %s",
118                   mFd, strerror(errno));
119             return AAUDIO_ERROR_INTERNAL;
120         }
121     }
122     *regionAddressPtr = mResolvedAddress + offsetInBytes;
123     ALOGV("SharedMemoryParcelable mResolvedAddress = %p", mResolvedAddress);
124     ALOGV("SharedMemoryParcelable offset by %d, *regionAddressPtr = %p",
125           offsetInBytes, *regionAddressPtr);
126     return AAUDIO_OK;
127 }
128 
getSizeInBytes()129 int32_t SharedMemoryParcelable::getSizeInBytes() {
130     return mSizeInBytes;
131 }
132 
validate()133 aaudio_result_t SharedMemoryParcelable::validate() {
134     if (mSizeInBytes < 0 || mSizeInBytes >= MAX_MMAP_SIZE_BYTES) {
135         ALOGE("SharedMemoryParcelable invalid mSizeInBytes = %d", mSizeInBytes);
136         return AAUDIO_ERROR_OUT_OF_RANGE;
137     }
138     if (mSizeInBytes > 0) {
139         if (mFd == -1) {
140             ALOGE("SharedMemoryParcelable uninitialized mFd = %d", mFd);
141             return AAUDIO_ERROR_INTERNAL;
142         }
143     }
144     return AAUDIO_OK;
145 }
146 
dump()147 void SharedMemoryParcelable::dump() {
148     ALOGD("SharedMemoryParcelable mFd = %d", mFd);
149     ALOGD("SharedMemoryParcelable mSizeInBytes = %d", mSizeInBytes);
150     ALOGD("SharedMemoryParcelable mResolvedAddress = %p", mResolvedAddress);
151 }
152