xref: /aosp_15_r20/frameworks/av/services/oboeservice/AAudioServiceStreamShared.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker  * Copyright (C) 2017 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker  *
4*ec779b8eSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker  *
8*ec779b8eSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker  *
10*ec779b8eSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker  * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker  */
16*ec779b8eSAndroid Build Coastguard Worker 
17*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "AAudioServiceStreamShared"
18*ec779b8eSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
19*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
20*ec779b8eSAndroid Build Coastguard Worker 
21*ec779b8eSAndroid Build Coastguard Worker #include <iomanip>
22*ec779b8eSAndroid Build Coastguard Worker #include <iostream>
23*ec779b8eSAndroid Build Coastguard Worker #include <mutex>
24*ec779b8eSAndroid Build Coastguard Worker 
25*ec779b8eSAndroid Build Coastguard Worker #include <aaudio/AAudio.h>
26*ec779b8eSAndroid Build Coastguard Worker 
27*ec779b8eSAndroid Build Coastguard Worker #include "binding/AAudioServiceMessage.h"
28*ec779b8eSAndroid Build Coastguard Worker #include "AAudioServiceStreamBase.h"
29*ec779b8eSAndroid Build Coastguard Worker #include "AAudioServiceStreamShared.h"
30*ec779b8eSAndroid Build Coastguard Worker #include "AAudioEndpointManager.h"
31*ec779b8eSAndroid Build Coastguard Worker #include "AAudioService.h"
32*ec779b8eSAndroid Build Coastguard Worker #include "AAudioServiceEndpoint.h"
33*ec779b8eSAndroid Build Coastguard Worker 
34*ec779b8eSAndroid Build Coastguard Worker using namespace android;
35*ec779b8eSAndroid Build Coastguard Worker using namespace aaudio;
36*ec779b8eSAndroid Build Coastguard Worker 
37*ec779b8eSAndroid Build Coastguard Worker #define MIN_BURSTS_PER_BUFFER       2
38*ec779b8eSAndroid Build Coastguard Worker #define DEFAULT_BURSTS_PER_BUFFER   16
39*ec779b8eSAndroid Build Coastguard Worker // This is an arbitrary range. TODO review.
40*ec779b8eSAndroid Build Coastguard Worker #define MAX_FRAMES_PER_BUFFER       (32 * 1024)
41*ec779b8eSAndroid Build Coastguard Worker 
AAudioServiceStreamShared(AAudioService & audioService)42*ec779b8eSAndroid Build Coastguard Worker AAudioServiceStreamShared::AAudioServiceStreamShared(AAudioService &audioService)
43*ec779b8eSAndroid Build Coastguard Worker     : AAudioServiceStreamBase(audioService)
44*ec779b8eSAndroid Build Coastguard Worker     , mTimestampPositionOffset(0)
45*ec779b8eSAndroid Build Coastguard Worker     , mXRunCount(0) {
46*ec779b8eSAndroid Build Coastguard Worker }
47*ec779b8eSAndroid Build Coastguard Worker 
dumpHeader()48*ec779b8eSAndroid Build Coastguard Worker std::string AAudioServiceStreamShared::dumpHeader() {
49*ec779b8eSAndroid Build Coastguard Worker     std::stringstream result;
50*ec779b8eSAndroid Build Coastguard Worker     result << AAudioServiceStreamBase::dumpHeader();
51*ec779b8eSAndroid Build Coastguard Worker     result << "    Write#     Read#   Avail   XRuns";
52*ec779b8eSAndroid Build Coastguard Worker     return result.str();
53*ec779b8eSAndroid Build Coastguard Worker }
54*ec779b8eSAndroid Build Coastguard Worker 
dump() const55*ec779b8eSAndroid Build Coastguard Worker std::string AAudioServiceStreamShared::dump() const NO_THREAD_SAFETY_ANALYSIS {
56*ec779b8eSAndroid Build Coastguard Worker     std::stringstream result;
57*ec779b8eSAndroid Build Coastguard Worker 
58*ec779b8eSAndroid Build Coastguard Worker     const bool isLocked = AAudio_tryUntilTrue(
59*ec779b8eSAndroid Build Coastguard Worker             [this]()->bool { return audioDataQueueLock.try_lock(); } /* f */,
60*ec779b8eSAndroid Build Coastguard Worker             50 /* times */,
61*ec779b8eSAndroid Build Coastguard Worker             20 /* sleepMs */);
62*ec779b8eSAndroid Build Coastguard Worker     if (!isLocked) {
63*ec779b8eSAndroid Build Coastguard Worker         result << "AAudioServiceStreamShared may be deadlocked\n";
64*ec779b8eSAndroid Build Coastguard Worker     }
65*ec779b8eSAndroid Build Coastguard Worker 
66*ec779b8eSAndroid Build Coastguard Worker     result << AAudioServiceStreamBase::dump();
67*ec779b8eSAndroid Build Coastguard Worker 
68*ec779b8eSAndroid Build Coastguard Worker     result << mAudioDataQueue->dump();
69*ec779b8eSAndroid Build Coastguard Worker     result << std::setw(8) << getXRunCount();
70*ec779b8eSAndroid Build Coastguard Worker 
71*ec779b8eSAndroid Build Coastguard Worker     if (isLocked) {
72*ec779b8eSAndroid Build Coastguard Worker         audioDataQueueLock.unlock();
73*ec779b8eSAndroid Build Coastguard Worker     }
74*ec779b8eSAndroid Build Coastguard Worker 
75*ec779b8eSAndroid Build Coastguard Worker     return result.str();
76*ec779b8eSAndroid Build Coastguard Worker }
77*ec779b8eSAndroid Build Coastguard Worker 
calculateBufferCapacity(int32_t requestedCapacityFrames,int32_t framesPerBurst)78*ec779b8eSAndroid Build Coastguard Worker int32_t AAudioServiceStreamShared::calculateBufferCapacity(int32_t requestedCapacityFrames,
79*ec779b8eSAndroid Build Coastguard Worker                                                            int32_t framesPerBurst) {
80*ec779b8eSAndroid Build Coastguard Worker 
81*ec779b8eSAndroid Build Coastguard Worker     if (requestedCapacityFrames > MAX_FRAMES_PER_BUFFER) {
82*ec779b8eSAndroid Build Coastguard Worker         ALOGE("calculateBufferCapacity() requested capacity %d > max %d",
83*ec779b8eSAndroid Build Coastguard Worker               requestedCapacityFrames, MAX_FRAMES_PER_BUFFER);
84*ec779b8eSAndroid Build Coastguard Worker         return AAUDIO_ERROR_OUT_OF_RANGE;
85*ec779b8eSAndroid Build Coastguard Worker     }
86*ec779b8eSAndroid Build Coastguard Worker 
87*ec779b8eSAndroid Build Coastguard Worker     // Determine how many bursts will fit in the buffer.
88*ec779b8eSAndroid Build Coastguard Worker     int32_t numBursts;
89*ec779b8eSAndroid Build Coastguard Worker     if (requestedCapacityFrames == AAUDIO_UNSPECIFIED) {
90*ec779b8eSAndroid Build Coastguard Worker         // Use fewer bursts if default is too many.
91*ec779b8eSAndroid Build Coastguard Worker         if ((DEFAULT_BURSTS_PER_BUFFER * framesPerBurst) > MAX_FRAMES_PER_BUFFER) {
92*ec779b8eSAndroid Build Coastguard Worker             numBursts = MAX_FRAMES_PER_BUFFER / framesPerBurst;
93*ec779b8eSAndroid Build Coastguard Worker         } else {
94*ec779b8eSAndroid Build Coastguard Worker             numBursts = DEFAULT_BURSTS_PER_BUFFER;
95*ec779b8eSAndroid Build Coastguard Worker         }
96*ec779b8eSAndroid Build Coastguard Worker     } else {
97*ec779b8eSAndroid Build Coastguard Worker         // round up to nearest burst boundary
98*ec779b8eSAndroid Build Coastguard Worker         numBursts = (requestedCapacityFrames + framesPerBurst - 1) / framesPerBurst;
99*ec779b8eSAndroid Build Coastguard Worker     }
100*ec779b8eSAndroid Build Coastguard Worker 
101*ec779b8eSAndroid Build Coastguard Worker     // Clip to bare minimum.
102*ec779b8eSAndroid Build Coastguard Worker     if (numBursts < MIN_BURSTS_PER_BUFFER) {
103*ec779b8eSAndroid Build Coastguard Worker         numBursts = MIN_BURSTS_PER_BUFFER;
104*ec779b8eSAndroid Build Coastguard Worker     }
105*ec779b8eSAndroid Build Coastguard Worker     // Check for numeric overflow.
106*ec779b8eSAndroid Build Coastguard Worker     if (numBursts > 0x8000 || framesPerBurst > 0x8000) {
107*ec779b8eSAndroid Build Coastguard Worker         ALOGE("calculateBufferCapacity() overflow, capacity = %d * %d",
108*ec779b8eSAndroid Build Coastguard Worker               numBursts, framesPerBurst);
109*ec779b8eSAndroid Build Coastguard Worker         return AAUDIO_ERROR_OUT_OF_RANGE;
110*ec779b8eSAndroid Build Coastguard Worker     }
111*ec779b8eSAndroid Build Coastguard Worker     int32_t capacityInFrames = numBursts * framesPerBurst;
112*ec779b8eSAndroid Build Coastguard Worker 
113*ec779b8eSAndroid Build Coastguard Worker     // Final range check.
114*ec779b8eSAndroid Build Coastguard Worker     if (capacityInFrames > MAX_FRAMES_PER_BUFFER) {
115*ec779b8eSAndroid Build Coastguard Worker         ALOGE("calculateBufferCapacity() calc capacity %d > max %d",
116*ec779b8eSAndroid Build Coastguard Worker               capacityInFrames, MAX_FRAMES_PER_BUFFER);
117*ec779b8eSAndroid Build Coastguard Worker         return AAUDIO_ERROR_OUT_OF_RANGE;
118*ec779b8eSAndroid Build Coastguard Worker     }
119*ec779b8eSAndroid Build Coastguard Worker     ALOGV("calculateBufferCapacity() requested %d frames, actual = %d",
120*ec779b8eSAndroid Build Coastguard Worker           requestedCapacityFrames, capacityInFrames);
121*ec779b8eSAndroid Build Coastguard Worker     return capacityInFrames;
122*ec779b8eSAndroid Build Coastguard Worker }
123*ec779b8eSAndroid Build Coastguard Worker 
open(const aaudio::AAudioStreamRequest & request)124*ec779b8eSAndroid Build Coastguard Worker aaudio_result_t AAudioServiceStreamShared::open(const aaudio::AAudioStreamRequest &request)  {
125*ec779b8eSAndroid Build Coastguard Worker 
126*ec779b8eSAndroid Build Coastguard Worker     sp<AAudioServiceStreamShared> keep(this);
127*ec779b8eSAndroid Build Coastguard Worker 
128*ec779b8eSAndroid Build Coastguard Worker     if (request.getConstantConfiguration().getSharingMode() != AAUDIO_SHARING_MODE_SHARED) {
129*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s() sharingMode mismatch %d", __func__,
130*ec779b8eSAndroid Build Coastguard Worker               request.getConstantConfiguration().getSharingMode());
131*ec779b8eSAndroid Build Coastguard Worker         return AAUDIO_ERROR_INTERNAL;
132*ec779b8eSAndroid Build Coastguard Worker     }
133*ec779b8eSAndroid Build Coastguard Worker 
134*ec779b8eSAndroid Build Coastguard Worker     aaudio_result_t result = AAudioServiceStreamBase::open(request);
135*ec779b8eSAndroid Build Coastguard Worker     if (result != AAUDIO_OK) {
136*ec779b8eSAndroid Build Coastguard Worker         return result;
137*ec779b8eSAndroid Build Coastguard Worker     }
138*ec779b8eSAndroid Build Coastguard Worker 
139*ec779b8eSAndroid Build Coastguard Worker     const AAudioStreamConfiguration &configurationInput = request.getConstantConfiguration();
140*ec779b8eSAndroid Build Coastguard Worker 
141*ec779b8eSAndroid Build Coastguard Worker     sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote();
142*ec779b8eSAndroid Build Coastguard Worker     if (endpoint == nullptr) {
143*ec779b8eSAndroid Build Coastguard Worker         result = AAUDIO_ERROR_INVALID_STATE;
144*ec779b8eSAndroid Build Coastguard Worker         goto error;
145*ec779b8eSAndroid Build Coastguard Worker     }
146*ec779b8eSAndroid Build Coastguard Worker 
147*ec779b8eSAndroid Build Coastguard Worker     // Use the sample rate of the endpoint as each shared stream should use its own SRC.
148*ec779b8eSAndroid Build Coastguard Worker     setSampleRate(endpoint->getSampleRate());
149*ec779b8eSAndroid Build Coastguard Worker 
150*ec779b8eSAndroid Build Coastguard Worker     // Is the request compatible with the shared endpoint?
151*ec779b8eSAndroid Build Coastguard Worker     setFormat(configurationInput.getFormat());
152*ec779b8eSAndroid Build Coastguard Worker     if (getFormat() == AUDIO_FORMAT_DEFAULT) {
153*ec779b8eSAndroid Build Coastguard Worker         setFormat(AUDIO_FORMAT_PCM_FLOAT);
154*ec779b8eSAndroid Build Coastguard Worker     } else if (getFormat() != AUDIO_FORMAT_PCM_FLOAT) {
155*ec779b8eSAndroid Build Coastguard Worker         ALOGD("%s() audio_format_t mAudioFormat = %d, need FLOAT", __func__, getFormat());
156*ec779b8eSAndroid Build Coastguard Worker         result = AAUDIO_ERROR_INVALID_FORMAT;
157*ec779b8eSAndroid Build Coastguard Worker         goto error;
158*ec779b8eSAndroid Build Coastguard Worker     }
159*ec779b8eSAndroid Build Coastguard Worker 
160*ec779b8eSAndroid Build Coastguard Worker     setChannelMask(configurationInput.getChannelMask());
161*ec779b8eSAndroid Build Coastguard Worker     if (getChannelMask() == AAUDIO_UNSPECIFIED) {
162*ec779b8eSAndroid Build Coastguard Worker         setChannelMask(endpoint->getChannelMask());
163*ec779b8eSAndroid Build Coastguard Worker     } else if (getSamplesPerFrame() != endpoint->getSamplesPerFrame()) {
164*ec779b8eSAndroid Build Coastguard Worker         ALOGD("%s() mSamplesPerFrame = %#x, need %#x",
165*ec779b8eSAndroid Build Coastguard Worker               __func__, getSamplesPerFrame(), endpoint->getSamplesPerFrame());
166*ec779b8eSAndroid Build Coastguard Worker         result = AAUDIO_ERROR_OUT_OF_RANGE;
167*ec779b8eSAndroid Build Coastguard Worker         goto error;
168*ec779b8eSAndroid Build Coastguard Worker     }
169*ec779b8eSAndroid Build Coastguard Worker 
170*ec779b8eSAndroid Build Coastguard Worker     setBufferCapacity(calculateBufferCapacity(configurationInput.getBufferCapacity(),
171*ec779b8eSAndroid Build Coastguard Worker                                      mFramesPerBurst));
172*ec779b8eSAndroid Build Coastguard Worker     if (getBufferCapacity() < 0) {
173*ec779b8eSAndroid Build Coastguard Worker         result = getBufferCapacity(); // negative error code
174*ec779b8eSAndroid Build Coastguard Worker         setBufferCapacity(0);
175*ec779b8eSAndroid Build Coastguard Worker         goto error;
176*ec779b8eSAndroid Build Coastguard Worker     }
177*ec779b8eSAndroid Build Coastguard Worker 
178*ec779b8eSAndroid Build Coastguard Worker     {
179*ec779b8eSAndroid Build Coastguard Worker         std::lock_guard<std::mutex> lock(audioDataQueueLock);
180*ec779b8eSAndroid Build Coastguard Worker         // Create audio data shared memory buffer for client.
181*ec779b8eSAndroid Build Coastguard Worker         mAudioDataQueue = std::make_shared<SharedRingBuffer>();
182*ec779b8eSAndroid Build Coastguard Worker         result = mAudioDataQueue->allocate(calculateBytesPerFrame(), getBufferCapacity());
183*ec779b8eSAndroid Build Coastguard Worker         if (result != AAUDIO_OK) {
184*ec779b8eSAndroid Build Coastguard Worker             ALOGE("%s() could not allocate FIFO with %d frames",
185*ec779b8eSAndroid Build Coastguard Worker                   __func__, getBufferCapacity());
186*ec779b8eSAndroid Build Coastguard Worker             result = AAUDIO_ERROR_NO_MEMORY;
187*ec779b8eSAndroid Build Coastguard Worker             goto error;
188*ec779b8eSAndroid Build Coastguard Worker         }
189*ec779b8eSAndroid Build Coastguard Worker     }
190*ec779b8eSAndroid Build Coastguard Worker 
191*ec779b8eSAndroid Build Coastguard Worker     result = endpoint->registerStream(keep);
192*ec779b8eSAndroid Build Coastguard Worker     if (result != AAUDIO_OK) {
193*ec779b8eSAndroid Build Coastguard Worker         goto error;
194*ec779b8eSAndroid Build Coastguard Worker     }
195*ec779b8eSAndroid Build Coastguard Worker 
196*ec779b8eSAndroid Build Coastguard Worker     setState(AAUDIO_STREAM_STATE_OPEN);
197*ec779b8eSAndroid Build Coastguard Worker     return AAUDIO_OK;
198*ec779b8eSAndroid Build Coastguard Worker 
199*ec779b8eSAndroid Build Coastguard Worker error:
200*ec779b8eSAndroid Build Coastguard Worker     close();
201*ec779b8eSAndroid Build Coastguard Worker     return result;
202*ec779b8eSAndroid Build Coastguard Worker }
203*ec779b8eSAndroid Build Coastguard Worker 
204*ec779b8eSAndroid Build Coastguard Worker /**
205*ec779b8eSAndroid Build Coastguard Worker  * Get an immutable description of the data queue created by this service.
206*ec779b8eSAndroid Build Coastguard Worker  */
getAudioDataDescription_l(AudioEndpointParcelable * parcelable)207*ec779b8eSAndroid Build Coastguard Worker aaudio_result_t AAudioServiceStreamShared::getAudioDataDescription_l(
208*ec779b8eSAndroid Build Coastguard Worker         AudioEndpointParcelable* parcelable)
209*ec779b8eSAndroid Build Coastguard Worker {
210*ec779b8eSAndroid Build Coastguard Worker     std::lock_guard<std::mutex> lock(audioDataQueueLock);
211*ec779b8eSAndroid Build Coastguard Worker     if (mAudioDataQueue == nullptr) {
212*ec779b8eSAndroid Build Coastguard Worker         ALOGW("%s(): mUpMessageQueue null! - stream not open", __func__);
213*ec779b8eSAndroid Build Coastguard Worker         return AAUDIO_ERROR_NULL;
214*ec779b8eSAndroid Build Coastguard Worker     }
215*ec779b8eSAndroid Build Coastguard Worker     // Gather information on the data queue.
216*ec779b8eSAndroid Build Coastguard Worker     mAudioDataQueue->fillParcelable(parcelable,
217*ec779b8eSAndroid Build Coastguard Worker                                     parcelable->mDownDataQueueParcelable);
218*ec779b8eSAndroid Build Coastguard Worker     parcelable->mDownDataQueueParcelable.setFramesPerBurst(getFramesPerBurst());
219*ec779b8eSAndroid Build Coastguard Worker     return AAUDIO_OK;
220*ec779b8eSAndroid Build Coastguard Worker }
221*ec779b8eSAndroid Build Coastguard Worker 
markTransferTime(Timestamp & timestamp)222*ec779b8eSAndroid Build Coastguard Worker void AAudioServiceStreamShared::markTransferTime(Timestamp &timestamp) {
223*ec779b8eSAndroid Build Coastguard Worker     mAtomicStreamTimestamp.write(timestamp);
224*ec779b8eSAndroid Build Coastguard Worker }
225*ec779b8eSAndroid Build Coastguard Worker 
226*ec779b8eSAndroid Build Coastguard Worker // Get timestamp that was written by mixer or distributor.
getFreeRunningPosition_l(int64_t * positionFrames,int64_t * timeNanos)227*ec779b8eSAndroid Build Coastguard Worker aaudio_result_t AAudioServiceStreamShared::getFreeRunningPosition_l(int64_t *positionFrames,
228*ec779b8eSAndroid Build Coastguard Worker                                                                     int64_t *timeNanos) {
229*ec779b8eSAndroid Build Coastguard Worker     // TODO Get presentation timestamp from the HAL
230*ec779b8eSAndroid Build Coastguard Worker     if (mAtomicStreamTimestamp.isValid()) {
231*ec779b8eSAndroid Build Coastguard Worker         Timestamp timestamp = mAtomicStreamTimestamp.read();
232*ec779b8eSAndroid Build Coastguard Worker         *positionFrames = timestamp.getPosition();
233*ec779b8eSAndroid Build Coastguard Worker         *timeNanos = timestamp.getNanoseconds();
234*ec779b8eSAndroid Build Coastguard Worker         return AAUDIO_OK;
235*ec779b8eSAndroid Build Coastguard Worker     } else {
236*ec779b8eSAndroid Build Coastguard Worker         return AAUDIO_ERROR_UNAVAILABLE;
237*ec779b8eSAndroid Build Coastguard Worker     }
238*ec779b8eSAndroid Build Coastguard Worker }
239*ec779b8eSAndroid Build Coastguard Worker 
240*ec779b8eSAndroid Build Coastguard Worker // Get timestamp from lower level service.
getHardwareTimestamp_l(int64_t * positionFrames,int64_t * timeNanos)241*ec779b8eSAndroid Build Coastguard Worker aaudio_result_t AAudioServiceStreamShared::getHardwareTimestamp_l(int64_t *positionFrames,
242*ec779b8eSAndroid Build Coastguard Worker                                                                   int64_t *timeNanos) {
243*ec779b8eSAndroid Build Coastguard Worker 
244*ec779b8eSAndroid Build Coastguard Worker     int64_t position = 0;
245*ec779b8eSAndroid Build Coastguard Worker     sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote();
246*ec779b8eSAndroid Build Coastguard Worker     if (endpoint == nullptr) {
247*ec779b8eSAndroid Build Coastguard Worker         ALOGW("%s() has no endpoint", __func__);
248*ec779b8eSAndroid Build Coastguard Worker         return AAUDIO_ERROR_INVALID_STATE;
249*ec779b8eSAndroid Build Coastguard Worker     }
250*ec779b8eSAndroid Build Coastguard Worker 
251*ec779b8eSAndroid Build Coastguard Worker     aaudio_result_t result = endpoint->getTimestamp(&position, timeNanos);
252*ec779b8eSAndroid Build Coastguard Worker     if (result == AAUDIO_OK) {
253*ec779b8eSAndroid Build Coastguard Worker         int64_t offset = mTimestampPositionOffset.load();
254*ec779b8eSAndroid Build Coastguard Worker         // TODO, do not go below starting value
255*ec779b8eSAndroid Build Coastguard Worker         position -= offset; // Offset from shared MMAP stream
256*ec779b8eSAndroid Build Coastguard Worker         ALOGV("%s() %8lld = %8lld - %8lld",
257*ec779b8eSAndroid Build Coastguard Worker               __func__, (long long) position, (long long) (position + offset), (long long) offset);
258*ec779b8eSAndroid Build Coastguard Worker     }
259*ec779b8eSAndroid Build Coastguard Worker     *positionFrames = position;
260*ec779b8eSAndroid Build Coastguard Worker     return result;
261*ec779b8eSAndroid Build Coastguard Worker }
262*ec779b8eSAndroid Build Coastguard Worker 
writeDataIfRoom(int64_t mmapFramesRead,const void * buffer,int32_t numFrames)263*ec779b8eSAndroid Build Coastguard Worker void AAudioServiceStreamShared::writeDataIfRoom(int64_t mmapFramesRead,
264*ec779b8eSAndroid Build Coastguard Worker                                                 const void *buffer, int32_t numFrames) {
265*ec779b8eSAndroid Build Coastguard Worker     int64_t clientFramesWritten = 0;
266*ec779b8eSAndroid Build Coastguard Worker 
267*ec779b8eSAndroid Build Coastguard Worker     // Lock the AudioFifo to protect against close.
268*ec779b8eSAndroid Build Coastguard Worker     std::lock_guard <std::mutex> lock(audioDataQueueLock);
269*ec779b8eSAndroid Build Coastguard Worker 
270*ec779b8eSAndroid Build Coastguard Worker     if (mAudioDataQueue != nullptr) {
271*ec779b8eSAndroid Build Coastguard Worker         std::shared_ptr<FifoBuffer> fifo = mAudioDataQueue->getFifoBuffer();
272*ec779b8eSAndroid Build Coastguard Worker         // Determine offset between framePosition in client's stream
273*ec779b8eSAndroid Build Coastguard Worker         // vs the underlying MMAP stream.
274*ec779b8eSAndroid Build Coastguard Worker         clientFramesWritten = fifo->getWriteCounter();
275*ec779b8eSAndroid Build Coastguard Worker         // There are two indices that refer to the same frame.
276*ec779b8eSAndroid Build Coastguard Worker         int64_t positionOffset = mmapFramesRead - clientFramesWritten;
277*ec779b8eSAndroid Build Coastguard Worker         setTimestampPositionOffset(positionOffset);
278*ec779b8eSAndroid Build Coastguard Worker 
279*ec779b8eSAndroid Build Coastguard Worker         // Is the buffer too full to write a burst?
280*ec779b8eSAndroid Build Coastguard Worker         if (fifo->getEmptyFramesAvailable() < getFramesPerBurst()) {
281*ec779b8eSAndroid Build Coastguard Worker             incrementXRunCount();
282*ec779b8eSAndroid Build Coastguard Worker         } else {
283*ec779b8eSAndroid Build Coastguard Worker             fifo->write(buffer, numFrames);
284*ec779b8eSAndroid Build Coastguard Worker         }
285*ec779b8eSAndroid Build Coastguard Worker         clientFramesWritten = fifo->getWriteCounter();
286*ec779b8eSAndroid Build Coastguard Worker     }
287*ec779b8eSAndroid Build Coastguard Worker 
288*ec779b8eSAndroid Build Coastguard Worker     if (clientFramesWritten > 0) {
289*ec779b8eSAndroid Build Coastguard Worker         // This timestamp represents the completion of data being written into the
290*ec779b8eSAndroid Build Coastguard Worker         // client buffer. It is sent to the client and used in the timing model
291*ec779b8eSAndroid Build Coastguard Worker         // to decide when data will be available to read.
292*ec779b8eSAndroid Build Coastguard Worker         Timestamp timestamp(clientFramesWritten, AudioClock::getNanoseconds());
293*ec779b8eSAndroid Build Coastguard Worker         markTransferTime(timestamp);
294*ec779b8eSAndroid Build Coastguard Worker     }
295*ec779b8eSAndroid Build Coastguard Worker }
296