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