• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "AAudioServiceEndpointMMAP"
18 //#define LOG_NDEBUG 0
19 #include <utils/Log.h>
20 
21 #include <algorithm>
22 #include <assert.h>
23 #include <map>
24 #include <mutex>
25 #include <set>
26 #include <sstream>
27 #include <thread>
28 #include <utils/Singleton.h>
29 #include <vector>
30 
31 #include "AAudioEndpointManager.h"
32 #include "AAudioServiceEndpoint.h"
33 
34 #include "core/AudioStreamBuilder.h"
35 #include "AAudioServiceEndpoint.h"
36 #include "AAudioServiceStreamShared.h"
37 #include "AAudioServiceEndpointPlay.h"
38 #include "AAudioServiceEndpointMMAP.h"
39 
40 #define AAUDIO_BUFFER_CAPACITY_MIN    (4 * 512)
41 #define AAUDIO_SAMPLE_RATE_DEFAULT    48000
42 
43 // This is an estimate of the time difference between the HW and the MMAP time.
44 // TODO Get presentation timestamps from the HAL instead of using these estimates.
45 #define OUTPUT_ESTIMATED_HARDWARE_OFFSET_NANOS  (3 * AAUDIO_NANOS_PER_MILLISECOND)
46 #define INPUT_ESTIMATED_HARDWARE_OFFSET_NANOS   (-1 * AAUDIO_NANOS_PER_MILLISECOND)
47 
48 using namespace android;  // TODO just import names needed
49 using namespace aaudio;   // TODO just import names needed
50 
AAudioServiceEndpointMMAP(AAudioService & audioService)51 AAudioServiceEndpointMMAP::AAudioServiceEndpointMMAP(AAudioService &audioService)
52         : mMmapStream(nullptr)
53         , mAAudioService(audioService) {}
54 
dump() const55 std::string AAudioServiceEndpointMMAP::dump() const {
56     std::stringstream result;
57 
58     result << "  MMAP: framesTransferred = " << mFramesTransferred.get();
59     result << ", HW nanos = " << mHardwareTimeOffsetNanos;
60     result << ", port handle = " << mPortHandle;
61     result << ", audio data FD = " << mAudioDataWrapper->getDataFileDescriptor();
62     result << "\n";
63 
64     result << "    HW Offset Micros:     " <<
65                                       (getHardwareTimeOffsetNanos()
66                                        / AAUDIO_NANOS_PER_MICROSECOND) << "\n";
67 
68     result << AAudioServiceEndpoint::dump();
69     return result.str();
70 }
71 
72 namespace {
73 
74 const static std::map<audio_format_t, audio_format_t> NEXT_FORMAT_TO_TRY = {
75         {AUDIO_FORMAT_PCM_FLOAT,         AUDIO_FORMAT_PCM_32_BIT},
76         {AUDIO_FORMAT_PCM_32_BIT,        AUDIO_FORMAT_PCM_24_BIT_PACKED},
77         {AUDIO_FORMAT_PCM_24_BIT_PACKED, AUDIO_FORMAT_PCM_16_BIT}
78 };
79 
getNextFormatToTry(audio_format_t curFormat,audio_format_t returnedFromAPM)80 audio_format_t getNextFormatToTry(audio_format_t curFormat, audio_format_t returnedFromAPM) {
81     if (returnedFromAPM != AUDIO_FORMAT_DEFAULT) {
82         return returnedFromAPM;
83     }
84     const auto it = NEXT_FORMAT_TO_TRY.find(curFormat);
85     return it != NEXT_FORMAT_TO_TRY.end() ? it->second : AUDIO_FORMAT_DEFAULT;
86 }
87 
88 } // namespace
89 
open(const aaudio::AAudioStreamRequest & request)90 aaudio_result_t AAudioServiceEndpointMMAP::open(const aaudio::AAudioStreamRequest &request) {
91     aaudio_result_t result = AAUDIO_OK;
92     mAudioDataWrapper = std::make_unique<SharedMemoryWrapper>();
93     copyFrom(request.getConstantConfiguration());
94     mRequestedDeviceId = getDeviceId();
95 
96     mMmapClient.attributionSource = request.getAttributionSource();
97     // TODO b/182392769: use attribution source util
98     mMmapClient.attributionSource.uid = VALUE_OR_FATAL(
99         legacy2aidl_uid_t_int32_t(IPCThreadState::self()->getCallingUid()));
100     mMmapClient.attributionSource.pid = VALUE_OR_FATAL(
101         legacy2aidl_pid_t_int32_t(IPCThreadState::self()->getCallingPid()));
102 
103     audio_format_t audioFormat = getFormat();
104     std::set<audio_format_t> formatsTried;
105     while (true) {
106         if (formatsTried.find(audioFormat) != formatsTried.end()) {
107             // APM returning something that has already tried.
108             ALOGW("Have already tried to open with format=%#x, but failed before", audioFormat);
109             break;
110         }
111         formatsTried.insert(audioFormat);
112 
113         audio_format_t nextFormatToTry = AUDIO_FORMAT_DEFAULT;
114         result = openWithFormat(audioFormat, &nextFormatToTry);
115         if (result != AAUDIO_ERROR_UNAVAILABLE) {
116             // Return if it is successful or there is an error that is not
117             // AAUDIO_ERROR_UNAVAILABLE happens.
118             ALOGI("Opened format=%#x with result=%d", audioFormat, result);
119             break;
120         }
121 
122         nextFormatToTry = getNextFormatToTry(audioFormat, nextFormatToTry);
123         ALOGD("%s() %#x failed, perhaps due to format. Try again with %#x",
124               __func__, audioFormat, nextFormatToTry);
125         audioFormat = nextFormatToTry;
126         if (audioFormat == AUDIO_FORMAT_DEFAULT) {
127             // Nothing else to try
128             break;
129         }
130     }
131     return result;
132 }
133 
openWithFormat(audio_format_t audioFormat,audio_format_t * nextFormatToTry)134 aaudio_result_t AAudioServiceEndpointMMAP::openWithFormat(
135         audio_format_t audioFormat, audio_format_t* nextFormatToTry) {
136     aaudio_result_t result = AAUDIO_OK;
137     audio_config_base_t config;
138     audio_port_handle_t deviceId;
139 
140     const audio_attributes_t attributes = getAudioAttributesFrom(this);
141 
142     deviceId = mRequestedDeviceId;
143 
144     // Fill in config
145     config.format = audioFormat;
146 
147     int32_t aaudioSampleRate = getSampleRate();
148     if (aaudioSampleRate == AAUDIO_UNSPECIFIED) {
149         aaudioSampleRate = AAUDIO_SAMPLE_RATE_DEFAULT;
150     }
151     config.sample_rate = aaudioSampleRate;
152 
153     const aaudio_direction_t direction = getDirection();
154 
155     config.channel_mask = AAudio_getChannelMaskForOpen(
156             getChannelMask(), getSamplesPerFrame(), direction == AAUDIO_DIRECTION_INPUT);
157 
158     if (direction == AAUDIO_DIRECTION_OUTPUT) {
159         mHardwareTimeOffsetNanos = OUTPUT_ESTIMATED_HARDWARE_OFFSET_NANOS; // frames at DAC later
160 
161     } else if (direction == AAUDIO_DIRECTION_INPUT) {
162         mHardwareTimeOffsetNanos = INPUT_ESTIMATED_HARDWARE_OFFSET_NANOS; // frames at ADC earlier
163 
164     } else {
165         ALOGE("%s() invalid direction = %d", __func__, direction);
166         return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
167     }
168 
169     const MmapStreamInterface::stream_direction_t streamDirection =
170             (direction == AAUDIO_DIRECTION_OUTPUT)
171             ? MmapStreamInterface::DIRECTION_OUTPUT
172             : MmapStreamInterface::DIRECTION_INPUT;
173 
174     const aaudio_session_id_t requestedSessionId = getSessionId();
175     audio_session_t sessionId = AAudioConvert_aaudioToAndroidSessionId(requestedSessionId);
176 
177     // Open HAL stream. Set mMmapStream
178     ALOGD("%s trying to open MMAP stream with format=%#x, "
179           "sample_rate=%u, channel_mask=%#x, device=%d",
180           __func__, config.format, config.sample_rate,
181           config.channel_mask, deviceId);
182     const status_t status = MmapStreamInterface::openMmapStream(streamDirection,
183                                                                 &attributes,
184                                                                 &config,
185                                                                 mMmapClient,
186                                                                 &deviceId,
187                                                                 &sessionId,
188                                                                 this, // callback
189                                                                 mMmapStream,
190                                                                 &mPortHandle);
191     ALOGD("%s() mMapClient.attributionSource = %s => portHandle = %d\n",
192           __func__, mMmapClient.attributionSource.toString().c_str(), mPortHandle);
193     if (status != OK) {
194         // This can happen if the resource is busy or the config does
195         // not match the hardware.
196         ALOGD("%s() - openMmapStream() returned status=%d, suggested format=%#x, sample_rate=%u, "
197               "channel_mask=%#x",
198               __func__, status, config.format, config.sample_rate, config.channel_mask);
199         *nextFormatToTry = config.format != audioFormat ? config.format
200                                                         : *nextFormatToTry;
201         return AAUDIO_ERROR_UNAVAILABLE;
202     }
203 
204     if (deviceId == AAUDIO_UNSPECIFIED) {
205         ALOGW("%s() - openMmapStream() failed to set deviceId", __func__);
206     }
207     setDeviceId(deviceId);
208 
209     if (sessionId == AUDIO_SESSION_ALLOCATE) {
210         ALOGW("%s() - openMmapStream() failed to set sessionId", __func__);
211     }
212 
213     const aaudio_session_id_t actualSessionId =
214             (requestedSessionId == AAUDIO_SESSION_ID_NONE)
215             ? AAUDIO_SESSION_ID_NONE
216             : (aaudio_session_id_t) sessionId;
217     setSessionId(actualSessionId);
218 
219     ALOGD("%s(format = 0x%X) deviceId = %d, sessionId = %d",
220           __func__, audioFormat, getDeviceId(), getSessionId());
221 
222     // Create MMAP/NOIRQ buffer.
223     result = createMmapBuffer();
224     if (result != AAUDIO_OK) {
225         goto error;
226     }
227 
228     // Get information about the stream and pass it back to the caller.
229     setChannelMask(AAudioConvert_androidToAAudioChannelMask(
230             config.channel_mask, getDirection() == AAUDIO_DIRECTION_INPUT,
231             AAudio_isChannelIndexMask(config.channel_mask)));
232 
233     setFormat(config.format);
234     setSampleRate(config.sample_rate);
235     setHardwareSampleRate(getSampleRate());
236     setHardwareFormat(getFormat());
237     setHardwareSamplesPerFrame(AAudioConvert_channelMaskToCount(getChannelMask()));
238 
239     // If the position is not updated while the timestamp is updated for more than a certain amount,
240     // the timestamp reported from the HAL may not be accurate. Here, a timestamp grace period is
241     // set as 5 burst size. We may want to update this value if there is any report from OEMs saying
242     // that is too short.
243     static constexpr int kTimestampGraceBurstCount = 5;
244     mTimestampGracePeriodMs = ((int64_t) kTimestampGraceBurstCount * mFramesPerBurst
245             * AAUDIO_MILLIS_PER_SECOND) / getSampleRate();
246 
247     mDataReportOffsetNanos = ((int64_t)mTimestampGracePeriodMs) * AAUDIO_NANOS_PER_MILLISECOND;
248 
249     ALOGD("%s() got rate = %d, channels = %d channelMask = %#x, deviceId = %d, capacity = %d\n",
250           __func__, getSampleRate(), getSamplesPerFrame(), getChannelMask(),
251           deviceId, getBufferCapacity());
252 
253     ALOGD("%s() got format = 0x%X = %s, frame size = %d, burst size = %d",
254           __func__, getFormat(), audio_format_to_string(getFormat()),
255           calculateBytesPerFrame(), mFramesPerBurst);
256 
257     return result;
258 
259 error:
260     close();
261     // restore original requests
262     setDeviceId(mRequestedDeviceId);
263     setSessionId(requestedSessionId);
264     return result;
265 }
266 
close()267 void AAudioServiceEndpointMMAP::close() {
268     if (mMmapStream != nullptr) {
269         // Needs to be explicitly cleared or CTS will fail but it is not clear why.
270         mMmapStream.clear();
271         AudioClock::sleepForNanos(100 * AAUDIO_NANOS_PER_MILLISECOND);
272     }
273 }
274 
startStream(sp<AAudioServiceStreamBase> stream,audio_port_handle_t * clientHandle __unused)275 aaudio_result_t AAudioServiceEndpointMMAP::startStream(sp<AAudioServiceStreamBase> stream,
276                                                    audio_port_handle_t *clientHandle __unused) {
277     // Start the client on behalf of the AAudio service.
278     // Use the port handle that was provided by openMmapStream().
279     audio_port_handle_t tempHandle = mPortHandle;
280     audio_attributes_t attr = {};
281     if (stream != nullptr) {
282         attr = getAudioAttributesFrom(stream.get());
283     }
284     const aaudio_result_t result = startClient(
285             mMmapClient, stream == nullptr ? nullptr : &attr, &tempHandle);
286     // When AudioFlinger is passed a valid port handle then it should not change it.
287     LOG_ALWAYS_FATAL_IF(tempHandle != mPortHandle,
288                         "%s() port handle not expected to change from %d to %d",
289                         __func__, mPortHandle, tempHandle);
290     ALOGV("%s() mPortHandle = %d", __func__, mPortHandle);
291     return result;
292 }
293 
stopStream(sp<AAudioServiceStreamBase>,audio_port_handle_t)294 aaudio_result_t AAudioServiceEndpointMMAP::stopStream(sp<AAudioServiceStreamBase> /*stream*/,
295                                                       audio_port_handle_t /*clientHandle*/) {
296     mFramesTransferred.reset32();
297 
298     // Round 64-bit counter up to a multiple of the buffer capacity.
299     // This is required because the 64-bit counter is used as an index
300     // into a circular buffer and the actual HW position is reset to zero
301     // when the stream is stopped.
302     mFramesTransferred.roundUp64(getBufferCapacity());
303 
304     // Use the port handle that was provided by openMmapStream().
305     ALOGV("%s() mPortHandle = %d", __func__, mPortHandle);
306     return stopClient(mPortHandle);
307 }
308 
startClient(const android::AudioClient & client,const audio_attributes_t * attr,audio_port_handle_t * clientHandle)309 aaudio_result_t AAudioServiceEndpointMMAP::startClient(const android::AudioClient& client,
310                                                        const audio_attributes_t *attr,
311                                                        audio_port_handle_t *clientHandle) {
312     return mMmapStream == nullptr
313             ? AAUDIO_ERROR_NULL
314             : AAudioConvert_androidToAAudioResult(mMmapStream->start(client, attr, clientHandle));
315 }
316 
stopClient(audio_port_handle_t clientHandle)317 aaudio_result_t AAudioServiceEndpointMMAP::stopClient(audio_port_handle_t clientHandle) {
318     return mMmapStream == nullptr
319             ? AAUDIO_ERROR_NULL
320             : AAudioConvert_androidToAAudioResult(mMmapStream->stop(clientHandle));
321 }
322 
standby()323 aaudio_result_t AAudioServiceEndpointMMAP::standby() {
324     return mMmapStream == nullptr
325             ? AAUDIO_ERROR_NULL
326             : AAudioConvert_androidToAAudioResult(mMmapStream->standby());
327 }
328 
exitStandby(AudioEndpointParcelable * parcelable)329 aaudio_result_t AAudioServiceEndpointMMAP::exitStandby(AudioEndpointParcelable* parcelable) {
330     if (mMmapStream == nullptr) {
331         return AAUDIO_ERROR_NULL;
332     }
333     mAudioDataWrapper->reset();
334     const aaudio_result_t result = createMmapBuffer();
335     if (result == AAUDIO_OK) {
336         getDownDataDescription(parcelable);
337     }
338     return result;
339 }
340 
341 // Get free-running DSP or DMA hardware position from the HAL.
getFreeRunningPosition(int64_t * positionFrames,int64_t * timeNanos)342 aaudio_result_t AAudioServiceEndpointMMAP::getFreeRunningPosition(int64_t *positionFrames,
343                                                                 int64_t *timeNanos) {
344     struct audio_mmap_position position;
345     if (mMmapStream == nullptr) {
346         return AAUDIO_ERROR_NULL;
347     }
348     const status_t status = mMmapStream->getMmapPosition(&position);
349     ALOGV("%s() status= %d, pos = %d, nanos = %lld\n",
350           __func__, status, position.position_frames, (long long) position.time_nanoseconds);
351     const aaudio_result_t result = AAudioConvert_androidToAAudioResult(status);
352     if (result == AAUDIO_ERROR_UNAVAILABLE) {
353         ALOGW("%s(): getMmapPosition() has no position data available", __func__);
354     } else if (result != AAUDIO_OK) {
355         ALOGE("%s(): getMmapPosition() returned status %d", __func__, status);
356     } else {
357         // Convert 32-bit position to 64-bit position.
358         mFramesTransferred.update32(position.position_frames);
359         *positionFrames = mFramesTransferred.get();
360         *timeNanos = position.time_nanoseconds;
361     }
362     return result;
363 }
364 
getTimestamp(int64_t *,int64_t *)365 aaudio_result_t AAudioServiceEndpointMMAP::getTimestamp(int64_t* /*positionFrames*/,
366                                                         int64_t* /*timeNanos*/) {
367     return 0; // TODO
368 }
369 
370 // This is called by onTearDown() in a separate thread to avoid deadlocks.
handleTearDownAsync(audio_port_handle_t portHandle)371 void AAudioServiceEndpointMMAP::handleTearDownAsync(audio_port_handle_t portHandle) {
372     // Are we tearing down the EXCLUSIVE MMAP stream?
373     if (isStreamRegistered(portHandle)) {
374         ALOGD("%s(%d) tearing down this entire MMAP endpoint", __func__, portHandle);
375         disconnectRegisteredStreams();
376     } else {
377         // Must be a SHARED stream?
378         ALOGD("%s(%d) disconnect a specific stream", __func__, portHandle);
379         const aaudio_result_t result = mAAudioService.disconnectStreamByPortHandle(portHandle);
380         ALOGD("%s(%d) disconnectStreamByPortHandle returned %d", __func__, portHandle, result);
381     }
382 };
383 
384 // This is called by AudioFlinger when it wants to destroy a stream.
onTearDown(audio_port_handle_t portHandle)385 void AAudioServiceEndpointMMAP::onTearDown(audio_port_handle_t portHandle) {
386     ALOGD("%s(portHandle = %d) called", __func__, portHandle);
387     const android::sp<AAudioServiceEndpointMMAP> holdEndpoint(this);
388     std::thread asyncTask([holdEndpoint, portHandle]() {
389         holdEndpoint->handleTearDownAsync(portHandle);
390     });
391     asyncTask.detach();
392 }
393 
onVolumeChanged(float volume)394 void AAudioServiceEndpointMMAP::onVolumeChanged(float volume) {
395     ALOGD("%s() volume = %f", __func__, volume);
396     const std::lock_guard<std::mutex> lock(mLockStreams);
397     for(const auto& stream : mRegisteredStreams) {
398         stream->onVolumeChanged(volume);
399     }
400 };
401 
onRoutingChanged(audio_port_handle_t portHandle)402 void AAudioServiceEndpointMMAP::onRoutingChanged(audio_port_handle_t portHandle) {
403     const auto deviceId = static_cast<int32_t>(portHandle);
404     ALOGD("%s() called with dev %d, old = %d", __func__, deviceId, getDeviceId());
405     if (getDeviceId() != deviceId) {
406         if (getDeviceId() != AUDIO_PORT_HANDLE_NONE) {
407             const android::sp<AAudioServiceEndpointMMAP> holdEndpoint(this);
408             std::thread asyncTask([holdEndpoint, deviceId]() {
409                 ALOGD("onRoutingChanged() asyncTask launched");
410                 holdEndpoint->disconnectRegisteredStreams();
411                 holdEndpoint->setDeviceId(deviceId);
412             });
413             asyncTask.detach();
414         } else {
415             setDeviceId(deviceId);
416         }
417     }
418 };
419 
420 /**
421  * Get an immutable description of the data queue from the HAL.
422  */
getDownDataDescription(AudioEndpointParcelable * parcelable)423 aaudio_result_t AAudioServiceEndpointMMAP::getDownDataDescription(
424         AudioEndpointParcelable* parcelable)
425 {
426     if (mAudioDataWrapper->setupFifoBuffer(calculateBytesPerFrame(), getBufferCapacity())
427         != AAUDIO_OK) {
428         ALOGE("Failed to setup audio data wrapper, will not be able to "
429               "set data for sound dose computation");
430         // This will not affect the audio processing capability
431     }
432     // Gather information on the data queue based on HAL info.
433     mAudioDataWrapper->fillParcelable(parcelable, parcelable->mDownDataQueueParcelable,
434                                       calculateBytesPerFrame(), mFramesPerBurst,
435                                       getBufferCapacity(),
436                                       getDirection() == AAUDIO_DIRECTION_OUTPUT
437                                               ? SharedMemoryWrapper::WRITE
438                                               : SharedMemoryWrapper::NONE);
439     return AAUDIO_OK;
440 }
441 
getExternalPosition(uint64_t * positionFrames,int64_t * timeNanos)442 aaudio_result_t AAudioServiceEndpointMMAP::getExternalPosition(uint64_t *positionFrames,
443                                                                int64_t *timeNanos)
444 {
445     if (mHalExternalPositionStatus != AAUDIO_OK) {
446         return mHalExternalPositionStatus;
447     }
448     uint64_t tempPositionFrames;
449     int64_t tempTimeNanos;
450     const status_t status = mMmapStream->getExternalPosition(&tempPositionFrames, &tempTimeNanos);
451     if (status != OK) {
452         // getExternalPosition reports error. The HAL may not support the API. Cache the result
453         // so that the call will not go to the HAL next time.
454         mHalExternalPositionStatus = AAudioConvert_androidToAAudioResult(status);
455         return mHalExternalPositionStatus;
456     }
457 
458     // If the HAL keeps reporting the same position or timestamp, the HAL may be having some issues
459     // to report correct external position. In that case, we will not trust the values reported from
460     // the HAL. Ideally, we may want to stop querying external position if the HAL cannot report
461     // correct position within a period. But it may not be a good idea to get system time too often.
462     // In that case, a maximum number of frozen external position is defined so that if the
463     // count of the same timestamp or position is reported by the HAL continuously, the values from
464     // the HAL will no longer be trusted.
465     static constexpr int kMaxFrozenCount = 20;
466     // If the HAL version is less than 7.0, the getPresentationPosition is an optional API.
467     // If the HAL version is 7.0 or later, the getPresentationPosition is a mandatory API.
468     // In that case, even the returned status is NO_ERROR, it doesn't indicate the returned
469     // position is a valid one. Do a simple validation, which is checking if the position is
470     // forward within half a second or not, here so that this function can return error if
471     // the validation fails. Note that we don't only apply this validation logic to HAL API
472     // less than 7.0. The reason is that there is a chance the HAL is not reporting the
473     // timestamp and position correctly.
474     if (mLastPositionFrames > tempPositionFrames) {
475         // If the position is going backwards, there must be something wrong with the HAL.
476         // In that case, we do not trust the values reported by the HAL.
477         ALOGW("%s position is going backwards, last position(%jd) current position(%jd)",
478               __func__, mLastPositionFrames, tempPositionFrames);
479         mHalExternalPositionStatus = AAUDIO_ERROR_INTERNAL;
480         return mHalExternalPositionStatus;
481     } else if (mLastPositionFrames == tempPositionFrames) {
482         if (tempTimeNanos - mTimestampNanosForLastPosition >
483                 AAUDIO_NANOS_PER_MILLISECOND * mTimestampGracePeriodMs) {
484             ALOGW("%s, the reported position is not changed within %d msec. "
485                   "Set the external position as not supported", __func__, mTimestampGracePeriodMs);
486             mHalExternalPositionStatus = AAUDIO_ERROR_INTERNAL;
487             return mHalExternalPositionStatus;
488         }
489         mFrozenPositionCount++;
490     } else {
491         mFrozenPositionCount = 0;
492     }
493 
494     if (mTimestampNanosForLastPosition > tempTimeNanos) {
495         // If the timestamp is going backwards, there must be something wrong with the HAL.
496         // In that case, we do not trust the values reported by the HAL.
497         ALOGW("%s timestamp is going backwards, last timestamp(%jd), current timestamp(%jd)",
498               __func__, mTimestampNanosForLastPosition, tempTimeNanos);
499         mHalExternalPositionStatus = AAUDIO_ERROR_INTERNAL;
500         return mHalExternalPositionStatus;
501     } else if (mTimestampNanosForLastPosition == tempTimeNanos) {
502         mFrozenTimestampCount++;
503     } else {
504         mFrozenTimestampCount = 0;
505     }
506 
507     if (mFrozenTimestampCount + mFrozenPositionCount > kMaxFrozenCount) {
508         ALOGW("%s too many frozen external position from HAL.", __func__);
509         mHalExternalPositionStatus = AAUDIO_ERROR_INTERNAL;
510         return mHalExternalPositionStatus;
511     }
512 
513     mLastPositionFrames = tempPositionFrames;
514     mTimestampNanosForLastPosition = tempTimeNanos;
515 
516     // Only update the timestamp and position when they looks valid.
517     *positionFrames = tempPositionFrames;
518     *timeNanos = tempTimeNanos;
519     return mHalExternalPositionStatus;
520 }
521 
createMmapBuffer()522 aaudio_result_t AAudioServiceEndpointMMAP::createMmapBuffer()
523 {
524     memset(&mMmapBufferinfo, 0, sizeof(struct audio_mmap_buffer_info));
525     int32_t minSizeFrames = getBufferCapacity();
526     if (minSizeFrames <= 0) { // zero will get rejected
527         minSizeFrames = AAUDIO_BUFFER_CAPACITY_MIN;
528     }
529     const status_t status = mMmapStream->createMmapBuffer(minSizeFrames, &mMmapBufferinfo);
530     const bool isBufferShareable = mMmapBufferinfo.flags & AUDIO_MMAP_APPLICATION_SHAREABLE;
531     if (status != OK) {
532         ALOGE("%s() - createMmapBuffer() failed with status %d %s",
533               __func__, status, strerror(-status));
534         return AAUDIO_ERROR_UNAVAILABLE;
535     } else {
536         ALOGD("%s() createMmapBuffer() buffer_size = %d fr, burst_size %d fr"
537                       ", Sharable FD: %s",
538               __func__,
539               mMmapBufferinfo.buffer_size_frames,
540               mMmapBufferinfo.burst_size_frames,
541               isBufferShareable ? "Yes" : "No");
542     }
543 
544     setBufferCapacity(mMmapBufferinfo.buffer_size_frames);
545     if (!isBufferShareable) {
546         // Exclusive mode can only be used by the service because the FD cannot be shared.
547         const int32_t audioServiceUid =
548             VALUE_OR_FATAL(legacy2aidl_uid_t_int32_t(getuid()));
549         if ((mMmapClient.attributionSource.uid != audioServiceUid) &&
550             getSharingMode() == AAUDIO_SHARING_MODE_EXCLUSIVE) {
551             ALOGW("%s() - exclusive FD cannot be used by client", __func__);
552             return AAUDIO_ERROR_UNAVAILABLE;
553         }
554     }
555 
556     // AAudio creates a copy of this FD and retains ownership of the copy.
557     // Assume that AudioFlinger will close the original shared_memory_fd.
558 
559     mAudioDataWrapper->getDataFileDescriptor().reset(dup(mMmapBufferinfo.shared_memory_fd));
560     if (mAudioDataWrapper->getDataFileDescriptor().get() == -1) {
561         ALOGE("%s() - could not dup shared_memory_fd", __func__);
562         return AAUDIO_ERROR_INTERNAL;
563     }
564 
565     // Call to HAL to make sure the transport FD was able to be closed by binder.
566     // This is a tricky workaround for a problem in Binder.
567     // TODO:[b/192048842] When that problem is fixed we may be able to remove or change this code.
568     struct audio_mmap_position position;
569     mMmapStream->getMmapPosition(&position);
570 
571     mFramesPerBurst = mMmapBufferinfo.burst_size_frames;
572 
573     return AAUDIO_OK;
574 }
575 
nextDataReportTime()576 int64_t AAudioServiceEndpointMMAP::nextDataReportTime() {
577     return getDirection() == AAUDIO_DIRECTION_OUTPUT
578             ? AudioClock::getNanoseconds() + mDataReportOffsetNanos
579             : std::numeric_limits<int64_t>::max();
580 }
581 
reportData()582 void AAudioServiceEndpointMMAP::reportData() {
583     if (mMmapStream == nullptr) {
584         // This must not happen
585         ALOGE("%s() invalid state, mmap stream is not initialized", __func__);
586         return;
587     }
588     auto fifo = mAudioDataWrapper->getFifoBuffer();
589     if (fifo == nullptr) {
590         ALOGE("%s() fifo buffer is not initialized, cannot report data", __func__);
591         return;
592     }
593 
594     WrappingBuffer wrappingBuffer;
595     fifo_frames_t framesAvailable = fifo->getFullDataAvailable(&wrappingBuffer);
596     for (size_t i = 0; i < WrappingBuffer::SIZE; ++i) {
597         if (wrappingBuffer.numFrames[i] > 0) {
598             mMmapStream->reportData(wrappingBuffer.data[i], wrappingBuffer.numFrames[i]);
599         }
600     }
601     fifo->advanceReadIndex(framesAvailable);
602 }
603