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 "AudioEndpointParcelable"
18 //#define LOG_NDEBUG 0
19 #include <utils/Log.h>
20 
21 #include <map>
22 #include <stdint.h>
23 
24 #include <binder/Parcel.h>
25 #include <binder/Parcelable.h>
26 #include <utility/AAudioUtilities.h>
27 
28 #include "binding/AAudioServiceDefinitions.h"
29 #include "binding/RingBufferParcelable.h"
30 #include "binding/AudioEndpointParcelable.h"
31 
32 using android::base::unique_fd;
33 using android::status_t;
34 
35 using namespace aaudio;
36 
AudioEndpointParcelable(Endpoint && parcelable)37 AudioEndpointParcelable::AudioEndpointParcelable(Endpoint&& parcelable)
38         : mUpMessageQueueParcelable(parcelable.upMessageQueueParcelable),
39           mDownMessageQueueParcelable(parcelable.downMessageQueueParcelable),
40           mUpDataQueueParcelable(parcelable.upDataQueueParcelable),
41           mDownDataQueueParcelable(parcelable.downDataQueueParcelable) {
42     for (size_t i = 0; i < parcelable.sharedMemories.size() && i < MAX_SHARED_MEMORIES; ++i) {
43         // Re-construct.
44         mSharedMemories[i].~SharedMemoryParcelable();
45         new(&mSharedMemories[i]) SharedMemoryParcelable(std::move(parcelable.sharedMemories[i]));
46     }
47 }
48 
operator =(Endpoint && parcelable)49 AudioEndpointParcelable& AudioEndpointParcelable::operator=(Endpoint&& parcelable) {
50     this->~AudioEndpointParcelable();
51     new(this) AudioEndpointParcelable(std::move(parcelable));
52     return *this;
53 }
54 
55 namespace {
56 
updateSharedMemoryIndex(SharedRegion * sharedRegion,int oldIndex,int newIndex)57 void updateSharedMemoryIndex(SharedRegion* sharedRegion, int oldIndex, int newIndex) {
58     if (sharedRegion->sharedMemoryIndex == oldIndex) {
59         sharedRegion->sharedMemoryIndex = newIndex;
60     }
61 }
62 
updateSharedMemoryIndex(RingBuffer * ringBuffer,int oldIndex,int newIndex)63 void updateSharedMemoryIndex(RingBuffer* ringBuffer, int oldIndex, int newIndex) {
64     updateSharedMemoryIndex(&ringBuffer->readCounterParcelable, oldIndex, newIndex);
65     updateSharedMemoryIndex(&ringBuffer->writeCounterParcelable, oldIndex, newIndex);
66     updateSharedMemoryIndex(&ringBuffer->dataParcelable, oldIndex, newIndex);
67 }
68 
updateSharedMemoryIndex(Endpoint * endpoint,int oldIndex,int newIndex)69 void updateSharedMemoryIndex(Endpoint* endpoint, int oldIndex, int newIndex) {
70     updateSharedMemoryIndex(&endpoint->upMessageQueueParcelable, oldIndex, newIndex);
71     updateSharedMemoryIndex(&endpoint->downMessageQueueParcelable, oldIndex, newIndex);
72     updateSharedMemoryIndex(&endpoint->upDataQueueParcelable, oldIndex, newIndex);
73     updateSharedMemoryIndex(&endpoint->downDataQueueParcelable, oldIndex, newIndex);
74 }
75 
76 } // namespace
77 
parcelable()78 Endpoint AudioEndpointParcelable::parcelable()&& {
79     Endpoint result;
80     result.upMessageQueueParcelable = mUpMessageQueueParcelable.parcelable();
81     result.downMessageQueueParcelable = mDownMessageQueueParcelable.parcelable();
82     result.upDataQueueParcelable = mUpDataQueueParcelable.parcelable();
83     result.downDataQueueParcelable = mDownDataQueueParcelable.parcelable();
84     // To transfer through binder, only valid/in-use shared memory is allowed. By design, the
85     // shared memories that are currently in-use may not be placed continuously from position 0.
86     // However, when marshalling the shared memories into Endpoint, the shared memories will be
87     // re-indexed from 0. In that case, when placing a shared memory, it is needed to update the
88     // corresponding cached indexes.
89     for (int i = 0; i < MAX_SHARED_MEMORIES; ++i) {
90         if (mSharedMemories[i].isInUse()) {
91             const int index = result.sharedMemories.size();
92             result.sharedMemories.emplace_back(std::move(mSharedMemories[i]).parcelable());
93             // Updating all the SharedRegion that is using `i` as shared memory index with the
94             // new shared memory index as `result.sharedMemories.size() - 1`.
95             updateSharedMemoryIndex(&result, i, index);
96         }
97     }
98     return result;
99 }
100 
101 /**
102  * Add the file descriptor to the table.
103  * @return index in table or negative error
104  */
addFileDescriptor(const unique_fd & fd,int32_t sizeInBytes)105 int32_t AudioEndpointParcelable::addFileDescriptor(const unique_fd& fd,
106                                                    int32_t sizeInBytes) {
107     const int32_t index = getNextAvailableSharedMemoryPosition();
108     if (index < 0) {
109         return AAUDIO_ERROR_OUT_OF_RANGE;
110     }
111     mSharedMemories[index].setup(fd, sizeInBytes);
112     return index;
113 }
114 
closeDataFileDescriptor()115 void AudioEndpointParcelable::closeDataFileDescriptor() {
116     for (const int32_t memoryIndex : std::set{mDownDataQueueParcelable.getDataSharedMemoryIndex(),
117                                 mDownDataQueueParcelable.getReadCounterSharedMemoryIndex(),
118                                 mDownDataQueueParcelable.getWriteCounterSharedMemoryIndex()}) {
119         mSharedMemories[memoryIndex].closeAndReleaseFd();
120     }
121 }
122 
updateDataFileDescriptor(AudioEndpointParcelable * endpointParcelable)123 aaudio_result_t AudioEndpointParcelable::updateDataFileDescriptor(
124         AudioEndpointParcelable* endpointParcelable) {
125     // Before updating data file descriptor, close the old shared memories.
126     closeDataFileDescriptor();
127     // The given endpoint parcelable and this one are two different objects, the indexes in
128     // `mSharedMemories` for `mDownDataQueueParcelable` can be different. In that case, an index
129     // map, which maps from the index in given endpoint parcelable to the index in this endpoint
130     // parcelable, is required when updating shared memory.
131     std::map<int32_t, int32_t> memoryIndexMap;
132     auto& downDataQueueParcelable = endpointParcelable->mDownDataQueueParcelable;
133     for (const int32_t memoryIndex : {downDataQueueParcelable.getDataSharedMemoryIndex(),
134                                       downDataQueueParcelable.getReadCounterSharedMemoryIndex(),
135                                       downDataQueueParcelable.getWriteCounterSharedMemoryIndex()}) {
136         if (memoryIndexMap.find(memoryIndex) != memoryIndexMap.end()) {
137             // This shared memory has been set up in this endpoint parcelable.
138             continue;
139         }
140         // Set up the memory in the next available shared memory position.
141         const int index = getNextAvailableSharedMemoryPosition();
142         if (index < 0) {
143             return AAUDIO_ERROR_OUT_OF_RANGE;
144         }
145         mSharedMemories[index].setup(endpointParcelable->mSharedMemories[memoryIndex]);
146         memoryIndexMap.emplace(memoryIndex, index);
147     }
148     mDownDataQueueParcelable.updateMemory(
149             endpointParcelable->mDownDataQueueParcelable, memoryIndexMap);
150     return AAUDIO_OK;
151 }
152 
resolve(EndpointDescriptor * descriptor)153 aaudio_result_t AudioEndpointParcelable::resolve(EndpointDescriptor *descriptor) {
154     aaudio_result_t result = mUpMessageQueueParcelable.resolve(mSharedMemories,
155                                                            &descriptor->upMessageQueueDescriptor);
156     if (result != AAUDIO_OK) return result;
157     result = mDownMessageQueueParcelable.resolve(mSharedMemories,
158                                         &descriptor->downMessageQueueDescriptor);
159     if (result != AAUDIO_OK) return result;
160 
161     result = mDownDataQueueParcelable.resolve(mSharedMemories,
162                                               &descriptor->dataQueueDescriptor);
163     return result;
164 }
165 
resolveDataQueue(RingBufferDescriptor * descriptor)166 aaudio_result_t AudioEndpointParcelable::resolveDataQueue(RingBufferDescriptor *descriptor) {
167     return mDownDataQueueParcelable.resolve(mSharedMemories, descriptor);
168 }
169 
close()170 aaudio_result_t AudioEndpointParcelable::close() {
171     int err = 0;
172     for (auto& sharedMemory : mSharedMemories) {
173         const int lastErr = sharedMemory.close();
174         if (lastErr < 0) err = lastErr;
175     }
176     return AAudioConvert_androidToAAudioResult(err);
177 }
178 
getNextAvailableSharedMemoryPosition() const179 int32_t AudioEndpointParcelable::getNextAvailableSharedMemoryPosition() const {
180     for (int i = 0; i < MAX_SHARED_MEMORIES; ++i) {
181         if (!mSharedMemories[i].isInUse()) {
182             return i;
183         }
184     }
185     return -1;
186 }
187 
dump()188 void AudioEndpointParcelable::dump() {
189     ALOGD("======================================= BEGIN");
190     for (int i = 0; i < MAX_SHARED_MEMORIES; ++i) {
191         if (mSharedMemories[i].isInUse()) {
192             ALOGD("Shared memory index=%d", i);
193             mSharedMemories[i].dump();
194         }
195     }
196     ALOGD("mUpMessageQueueParcelable =========");
197     mUpMessageQueueParcelable.dump();
198     ALOGD("mDownMessageQueueParcelable =======");
199     mDownMessageQueueParcelable.dump();
200     ALOGD("mUpDataQueueParcelable ============");
201     mUpDataQueueParcelable.dump();
202     ALOGD("mDownDataQueueParcelable ==========");
203     mDownDataQueueParcelable.dump();
204     ALOGD("======================================= END");
205 }
206 
207