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
27204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#include <binder/Parcelable.h>
28c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include <utility/AAudioUtilities.h>
29204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk
30204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#include "binding/SharedMemoryParcelable.h"
31204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk
32204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkusing android::NO_ERROR;
33204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkusing android::status_t;
34204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkusing android::Parcel;
35204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkusing android::Parcelable;
36204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk
375ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkusing namespace aaudio;
38204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk
39204a163c86f357a878873fe7d4c4164f3d55c9b6Phil BurkSharedMemoryParcelable::SharedMemoryParcelable() {}
40204a163c86f357a878873fe7d4c4164f3d55c9b6Phil BurkSharedMemoryParcelable::~SharedMemoryParcelable() {};
41204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk
42204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkvoid SharedMemoryParcelable::setup(int fd, int32_t sizeInBytes) {
43204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk    mFd = fd;
44204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk    mSizeInBytes = sizeInBytes;
45c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk
46204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk}
47204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk
48204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkstatus_t SharedMemoryParcelable::writeToParcel(Parcel* parcel) const {
49c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk    status_t status = parcel->writeInt32(mSizeInBytes);
50c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk    if (status != NO_ERROR) return status;
51204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk    if (mSizeInBytes > 0) {
52c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk        status = parcel->writeDupFileDescriptor(mFd);
53942bdc0aebc88dc8b12c0e7742ec0003bbb8b80fPhil Burk        ALOGE_IF(status != NO_ERROR, "SharedMemoryParcelable writeDupFileDescriptor failed : %d",
54942bdc0aebc88dc8b12c0e7742ec0003bbb8b80fPhil Burk                 status);
55204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk    }
56c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk    return status;
57204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk}
58204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk
59204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkstatus_t SharedMemoryParcelable::readFromParcel(const Parcel* parcel) {
60c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk    status_t status = parcel->readInt32(&mSizeInBytes);
61c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk    if (status != NO_ERROR) {
62c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk        return status;
63c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk    }
64204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk    if (mSizeInBytes > 0) {
6587c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        // Keep the original FD until you are done with the mFd.
6687c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        // If you close it in here then it will prevent mFd from working.
67942bdc0aebc88dc8b12c0e7742ec0003bbb8b80fPhil Burk        mOriginalFd = parcel->readFileDescriptor();
68942bdc0aebc88dc8b12c0e7742ec0003bbb8b80fPhil Burk        ALOGV("SharedMemoryParcelable::readFromParcel() LEAK? mOriginalFd = %d\n", mOriginalFd);
69942bdc0aebc88dc8b12c0e7742ec0003bbb8b80fPhil Burk        mFd = fcntl(mOriginalFd, F_DUPFD_CLOEXEC, 0);
70942bdc0aebc88dc8b12c0e7742ec0003bbb8b80fPhil Burk        ALOGV("SharedMemoryParcelable::readFromParcel() LEAK? mFd = %d\n", mFd);
71c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk        if (mFd == -1) {
72c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk            status = -errno;
73942bdc0aebc88dc8b12c0e7742ec0003bbb8b80fPhil Burk            ALOGE("SharedMemoryParcelable readFromParcel fcntl() failed : %d", status);
74c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk        }
75204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk    }
76c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk    return status;
77204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk}
78204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk
79c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burkaaudio_result_t SharedMemoryParcelable::close() {
80478d5df3a0e1693669f5809176d5c7f6e8c9aa88Phil Burk    if (mResolvedAddress != MMAP_UNRESOLVED_ADDRESS) {
81c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk        int err = munmap(mResolvedAddress, mSizeInBytes);
82c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk        if (err < 0) {
83c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk            ALOGE("SharedMemoryParcelable::close() munmap() failed %d", err);
84c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk            return AAudioConvert_androidToAAudioResult(err);
85c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk        }
86478d5df3a0e1693669f5809176d5c7f6e8c9aa88Phil Burk        mResolvedAddress = MMAP_UNRESOLVED_ADDRESS;
87c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk    }
88c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk    if (mFd != -1) {
89942bdc0aebc88dc8b12c0e7742ec0003bbb8b80fPhil Burk        ALOGV("SharedMemoryParcelable::close() LEAK? mFd = %d\n", mFd);
90c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk        ::close(mFd);
91c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk        mFd = -1;
92c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk    }
93942bdc0aebc88dc8b12c0e7742ec0003bbb8b80fPhil Burk    if (mOriginalFd != -1) {
94942bdc0aebc88dc8b12c0e7742ec0003bbb8b80fPhil Burk        ALOGV("SharedMemoryParcelable::close() LEAK? mOriginalFd = %d\n", mOriginalFd);
95942bdc0aebc88dc8b12c0e7742ec0003bbb8b80fPhil Burk        ::close(mOriginalFd);
96942bdc0aebc88dc8b12c0e7742ec0003bbb8b80fPhil Burk        mOriginalFd = -1;
97942bdc0aebc88dc8b12c0e7742ec0003bbb8b80fPhil Burk    }
98c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk    return AAUDIO_OK;
99c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk}
100204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk
1015ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t SharedMemoryParcelable::resolve(int32_t offsetInBytes, int32_t sizeInBytes,
102204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk                                              void **regionAddressPtr) {
103c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk
104204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk    if (offsetInBytes < 0) {
105204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk        ALOGE("SharedMemoryParcelable illegal offsetInBytes = %d", offsetInBytes);
1065ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAUDIO_ERROR_OUT_OF_RANGE;
107204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk    } else if ((offsetInBytes + sizeInBytes) > mSizeInBytes) {
108204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk        ALOGE("SharedMemoryParcelable out of range, offsetInBytes = %d, "
109204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk              "sizeInBytes = %d, mSizeInBytes = %d",
110204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk              offsetInBytes, sizeInBytes, mSizeInBytes);
1115ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAUDIO_ERROR_OUT_OF_RANGE;
112204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk    }
113478d5df3a0e1693669f5809176d5c7f6e8c9aa88Phil Burk    if (mResolvedAddress == MMAP_UNRESOLVED_ADDRESS) {
114204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk        mResolvedAddress = (uint8_t *) mmap(0, mSizeInBytes, PROT_READ|PROT_WRITE,
115204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk                                          MAP_SHARED, mFd, 0);
116478d5df3a0e1693669f5809176d5c7f6e8c9aa88Phil Burk        if (mResolvedAddress == MMAP_UNRESOLVED_ADDRESS) {
117478d5df3a0e1693669f5809176d5c7f6e8c9aa88Phil Burk            ALOGE("SharedMemoryParcelable mmap failed for fd = %d, errno = %s",
118478d5df3a0e1693669f5809176d5c7f6e8c9aa88Phil Burk                  mFd, strerror(errno));
1195ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk            return AAUDIO_ERROR_INTERNAL;
120204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk        }
121204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk    }
122204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk    *regionAddressPtr = mResolvedAddress + offsetInBytes;
123c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk    ALOGV("SharedMemoryParcelable mResolvedAddress = %p", mResolvedAddress);
124c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk    ALOGV("SharedMemoryParcelable offset by %d, *regionAddressPtr = %p",
125204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk          offsetInBytes, *regionAddressPtr);
1265ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    return AAUDIO_OK;
127204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk}
128204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk
129204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkint32_t SharedMemoryParcelable::getSizeInBytes() {
130204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk    return mSizeInBytes;
131204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk}
132204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk
1335ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t SharedMemoryParcelable::validate() {
1343df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk    if (mSizeInBytes < 0 || mSizeInBytes >= MAX_MMAP_SIZE_BYTES) {
135204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk        ALOGE("SharedMemoryParcelable invalid mSizeInBytes = %d", mSizeInBytes);
1363df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk        return AAUDIO_ERROR_OUT_OF_RANGE;
137204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk    }
138204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk    if (mSizeInBytes > 0) {
139204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk        if (mFd == -1) {
140204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk            ALOGE("SharedMemoryParcelable uninitialized mFd = %d", mFd);
1415ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk            return AAUDIO_ERROR_INTERNAL;
142204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk        }
143204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk    }
1445ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    return AAUDIO_OK;
145204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk}
146204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk
147204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkvoid SharedMemoryParcelable::dump() {
148204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk    ALOGD("SharedMemoryParcelable mFd = %d", mFd);
149204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk    ALOGD("SharedMemoryParcelable mSizeInBytes = %d", mSizeInBytes);
150204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk    ALOGD("SharedMemoryParcelable mResolvedAddress = %p", mResolvedAddress);
151204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk}
152