1 /*
2  * Copyright (C) 2017 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 "AAudioServiceStreamMMAP"
18 //#define LOG_NDEBUG 0
19 #include <utils/Log.h>
20 
21 #include <atomic>
22 #include <inttypes.h>
23 #include <iomanip>
24 #include <iostream>
25 #include <stdint.h>
26 
27 #include <com_android_media_aaudio.h>
28 #include <utils/String16.h>
29 #include <media/nbaio/AudioStreamOutSink.h>
30 #include <media/MmapStreamInterface.h>
31 
32 #include "binding/AudioEndpointParcelable.h"
33 #include "utility/AAudioUtilities.h"
34 
35 #include "AAudioServiceEndpointMMAP.h"
36 #include "AAudioServiceStreamBase.h"
37 #include "AAudioServiceStreamMMAP.h"
38 #include "SharedMemoryProxy.h"
39 
40 using android::base::unique_fd;
41 using namespace android;
42 using namespace aaudio;
43 
44 /**
45  * Service Stream that uses an MMAP buffer.
46  */
47 
AAudioServiceStreamMMAP(android::AAudioService & aAudioService,bool inService)48 AAudioServiceStreamMMAP::AAudioServiceStreamMMAP(android::AAudioService &aAudioService,
49                                                  bool inService)
50         : AAudioServiceStreamBase(aAudioService)
51         , mInService(inService) {
52 }
53 
54 // Open stream on HAL and pass information about the shared memory buffer back to the client.
open(const aaudio::AAudioStreamRequest & request)55 aaudio_result_t AAudioServiceStreamMMAP::open(const aaudio::AAudioStreamRequest &request) {
56 
57     sp<AAudioServiceStreamMMAP> keep(this);
58 
59     if (request.getConstantConfiguration().getSharingMode() != AAUDIO_SHARING_MODE_EXCLUSIVE) {
60         ALOGE("%s() sharingMode mismatch %d", __func__,
61               request.getConstantConfiguration().getSharingMode());
62         return AAUDIO_ERROR_INTERNAL;
63     }
64 
65     aaudio_result_t result = AAudioServiceStreamBase::open(request);
66     if (result != AAUDIO_OK) {
67         return result;
68     }
69 
70     sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote();
71     if (endpoint == nullptr) {
72         ALOGE("%s() has no endpoint", __func__);
73         return AAUDIO_ERROR_INVALID_STATE;
74     }
75 
76     result = endpoint->registerStream(keep);
77     if (result != AAUDIO_OK) {
78         return result;
79     }
80 
81     setState(AAUDIO_STREAM_STATE_OPEN);
82 
83     return AAUDIO_OK;
84 }
85 
86 // Start the flow of data.
startDevice_l()87 aaudio_result_t AAudioServiceStreamMMAP::startDevice_l() {
88     aaudio_result_t result = AAudioServiceStreamBase::startDevice_l();
89     if (!mInService && result == AAUDIO_OK) {
90         // Note that this can sometimes take 200 to 300 msec for a cold start!
91         result = startClient_l(
92                 mMmapClient, nullptr /*const audio_attributes_t* */, &mClientHandle);
93     }
94     return result;
95 }
96 
97 // Stop the flow of data such that start() can resume with loss of data.
pause_l()98 aaudio_result_t AAudioServiceStreamMMAP::pause_l() {
99     if (!isRunning()) {
100         return AAUDIO_OK;
101     }
102     aaudio_result_t result = AAudioServiceStreamBase::pause_l();
103     // TODO put before base::pause()?
104     if (!mInService) {
105         (void) stopClient_l(mClientHandle);
106     }
107     return result;
108 }
109 
stop_l()110 aaudio_result_t AAudioServiceStreamMMAP::stop_l() {
111     if (!isRunning()) {
112         return AAUDIO_OK;
113     }
114     aaudio_result_t result = AAudioServiceStreamBase::stop_l();
115     // TODO put before base::stop()?
116     if (!mInService) {
117         (void) stopClient_l(mClientHandle);
118     }
119     return result;
120 }
121 
standby_l()122 aaudio_result_t AAudioServiceStreamMMAP::standby_l() {
123     sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote();
124     if (endpoint == nullptr) {
125         ALOGE("%s() has no endpoint", __func__);
126         return AAUDIO_ERROR_INVALID_STATE;
127     }
128     aaudio_result_t result = endpoint->standby();
129     if (result == AAUDIO_OK) {
130         setStandby_l(true);
131     }
132     return result;
133 }
134 
exitStandby_l(AudioEndpointParcelable * parcelable)135 aaudio_result_t AAudioServiceStreamMMAP::exitStandby_l(AudioEndpointParcelable* parcelable) {
136     sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote();
137     if (endpoint == nullptr) {
138         ALOGE("%s() has no endpoint", __func__);
139         return AAUDIO_ERROR_INVALID_STATE;
140     }
141     aaudio_result_t result = endpoint->exitStandby(parcelable);
142     if (result == AAUDIO_OK) {
143         setStandby_l(false);
144     } else {
145         ALOGE("%s failed, result %d, disconnecting stream.", __func__, result);
146         disconnect_l();
147     }
148     return result;
149 }
150 
startClient(const android::AudioClient & client,const audio_attributes_t * attr,audio_port_handle_t * portHandlePtr)151 aaudio_result_t AAudioServiceStreamMMAP::startClient(const android::AudioClient& client,
152                                                      const audio_attributes_t *attr,
153                                                      audio_port_handle_t *portHandlePtr) {
154     if (com::android::media::aaudio::start_stop_client_from_command_thread()) {
155         return sendStartClientCommand(client, attr, portHandlePtr);
156     } else {
157         sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote();
158         if (endpoint == nullptr) {
159             ALOGE("%s() has no endpoint", __func__);
160             return AAUDIO_ERROR_INVALID_STATE;
161         }
162         // Start the client on behalf of the application. Generate a new porthandle.
163         aaudio_result_t result = endpoint->startClient(client, attr, portHandlePtr);
164         ALOGD("%s() flag off, got port %d", __func__,
165               ((portHandlePtr == nullptr) ? -1 : *portHandlePtr));
166         return result;
167     }
168 }
169 
stopClient(audio_port_handle_t clientHandle)170 aaudio_result_t AAudioServiceStreamMMAP::stopClient(audio_port_handle_t clientHandle) {
171     if (com::android::media::aaudio::start_stop_client_from_command_thread()) {
172         return sendStopClientCommand(clientHandle);
173     } else {
174         sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote();
175         if (endpoint == nullptr) {
176             ALOGE("%s() has no endpoint", __func__);
177             return AAUDIO_ERROR_INVALID_STATE;
178         }
179         aaudio_result_t result = endpoint->stopClient(clientHandle);
180         return result;
181     }
182 }
183 
startClient_l(const android::AudioClient & client,const audio_attributes_t * attr,audio_port_handle_t * clientHandle)184 aaudio_result_t AAudioServiceStreamMMAP::startClient_l(const android::AudioClient& client,
185                                                        const audio_attributes_t *attr,
186                                                        audio_port_handle_t *clientHandle) {
187     sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote();
188     if (endpoint == nullptr) {
189         ALOGE("%s() has no endpoint", __func__);
190         return AAUDIO_ERROR_INVALID_STATE;
191     }
192     // Start the client on behalf of the application. Generate a new porthandle.
193     aaudio_result_t result = endpoint->startClient(client, attr, clientHandle);
194     return result;
195 }
196 
stopClient_l(audio_port_handle_t clientHandle)197 aaudio_result_t AAudioServiceStreamMMAP::stopClient_l(audio_port_handle_t clientHandle) {
198     sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote();
199     if (endpoint == nullptr) {
200         ALOGE("%s() has no endpoint", __func__);
201         return AAUDIO_ERROR_INVALID_STATE;
202     }
203     aaudio_result_t result = endpoint->stopClient(clientHandle);
204     return result;
205 }
206 
207 // Get free-running DSP or DMA hardware position from the HAL.
getFreeRunningPosition_l(int64_t * positionFrames,int64_t * timeNanos)208 aaudio_result_t AAudioServiceStreamMMAP::getFreeRunningPosition_l(int64_t *positionFrames,
209                                                                   int64_t *timeNanos) {
210     sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote();
211     if (endpoint == nullptr) {
212         ALOGE("%s() has no endpoint", __func__);
213         return AAUDIO_ERROR_INVALID_STATE;
214     }
215     sp<AAudioServiceEndpointMMAP> serviceEndpointMMAP =
216             static_cast<AAudioServiceEndpointMMAP *>(endpoint.get());
217 
218     aaudio_result_t result = serviceEndpointMMAP->getFreeRunningPosition(positionFrames, timeNanos);
219     if (result == AAUDIO_OK) {
220         Timestamp timestamp(*positionFrames, *timeNanos);
221         mAtomicStreamTimestamp.write(timestamp);
222         *positionFrames = timestamp.getPosition();
223         *timeNanos = timestamp.getNanoseconds();
224     } else if (result != AAUDIO_ERROR_UNAVAILABLE) {
225         disconnect_l();
226     }
227     return result;
228 }
229 
230 // Get timestamp from presentation position.
231 // If it fails, get timestamp that was written by getFreeRunningPosition()
getHardwareTimestamp_l(int64_t * positionFrames,int64_t * timeNanos)232 aaudio_result_t AAudioServiceStreamMMAP::getHardwareTimestamp_l(int64_t *positionFrames,
233                                                                 int64_t *timeNanos) {
234     sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote();
235     if (endpoint == nullptr) {
236         ALOGE("%s() has no endpoint", __func__);
237         return AAUDIO_ERROR_INVALID_STATE;
238     }
239     sp<AAudioServiceEndpointMMAP> serviceEndpointMMAP =
240             static_cast<AAudioServiceEndpointMMAP *>(endpoint.get());
241 
242     uint64_t position;
243     aaudio_result_t result = serviceEndpointMMAP->getExternalPosition(&position, timeNanos);
244     if (result == AAUDIO_OK) {
245         ALOGV("%s() getExternalPosition() says pos = %" PRIi64 ", time = %" PRIi64,
246                 __func__, position, *timeNanos);
247         *positionFrames = (int64_t) position;
248         return AAUDIO_OK;
249     } else {
250         ALOGV("%s() getExternalPosition() returns error %d", __func__, result);
251     }
252 
253     if (mAtomicStreamTimestamp.isValid()) {
254         Timestamp timestamp = mAtomicStreamTimestamp.read();
255         *positionFrames = timestamp.getPosition();
256         *timeNanos = timestamp.getNanoseconds() + serviceEndpointMMAP->getHardwareTimeOffsetNanos();
257         return AAUDIO_OK;
258     } else {
259         return AAUDIO_ERROR_UNAVAILABLE;
260     }
261 }
262 
263 // Get an immutable description of the data queue from the HAL.
getAudioDataDescription_l(AudioEndpointParcelable * parcelable)264 aaudio_result_t AAudioServiceStreamMMAP::getAudioDataDescription_l(
265         AudioEndpointParcelable* parcelable)
266 {
267     sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote();
268     if (endpoint == nullptr) {
269         ALOGE("%s() has no endpoint", __func__);
270         return AAUDIO_ERROR_INVALID_STATE;
271     }
272     sp<AAudioServiceEndpointMMAP> serviceEndpointMMAP =
273             static_cast<AAudioServiceEndpointMMAP *>(endpoint.get());
274     return serviceEndpointMMAP->getDownDataDescription(parcelable);
275 }
276 
nextDataReportTime_l()277 int64_t AAudioServiceStreamMMAP::nextDataReportTime_l() {
278     sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote();
279     if (endpoint == nullptr) {
280         ALOGE("%s() has no endpoint", __func__);
281         return std::numeric_limits<int64_t>::max();
282     }
283     sp<AAudioServiceEndpointMMAP> serviceEndpointMMAP =
284             static_cast<AAudioServiceEndpointMMAP *>(endpoint.get());
285     return serviceEndpointMMAP->nextDataReportTime();
286 }
287 
reportData_l()288 void AAudioServiceStreamMMAP::reportData_l() {
289     sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote();
290     if (endpoint == nullptr) {
291         ALOGE("%s() has no endpoint", __func__);
292         return;
293     }
294     sp<AAudioServiceEndpointMMAP> serviceEndpointMMAP =
295             static_cast<AAudioServiceEndpointMMAP *>(endpoint.get());
296     return serviceEndpointMMAP->reportData();
297 }
298