• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 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 #ifndef ANDROID_AUDIO_TRACK_SHARED_H
18 #define ANDROID_AUDIO_TRACK_SHARED_H
19 
20 #include <stdint.h>
21 #include <sys/types.h>
22 
23 #include <audio_utils/minifloat.h>
24 #include <utils/threads.h>
25 #include <utils/Log.h>
26 #include <utils/RefBase.h>
27 #include <media/nbaio/roundup.h>
28 #include <media/SingleStateQueue.h>
29 #include <private/media/StaticAudioTrackState.h>
30 
31 namespace android {
32 
33 // ----------------------------------------------------------------------------
34 
35 // for audio_track_cblk_t::mFlags
36 #define CBLK_UNDERRUN   0x01 // set by server immediately on output underrun, cleared by client
37 #define CBLK_FORCEREADY 0x02 // set: track is considered ready immediately by AudioFlinger,
38                              // clear: track is ready when buffer full
39 #define CBLK_INVALID    0x04 // track buffer invalidated by AudioFlinger, need to re-create
40 #define CBLK_DISABLED   0x08 // output track disabled by AudioFlinger due to underrun,
41                              // need to re-start.  Unlike CBLK_UNDERRUN, this is not set
42                              // immediately, but only after a long string of underruns.
43 // 0x10 unused
44 #define CBLK_LOOP_CYCLE 0x20 // set by server each time a loop cycle other than final one completes
45 #define CBLK_LOOP_FINAL 0x40 // set by server when the final loop cycle completes
46 #define CBLK_BUFFER_END 0x80 // set by server when the position reaches end of buffer if not looping
47 #define CBLK_OVERRUN   0x100 // set by server immediately on input overrun, cleared by client
48 #define CBLK_INTERRUPT 0x200 // set by client on interrupt(), cleared by client in obtainBuffer()
49 #define CBLK_STREAM_END_DONE 0x400 // set by server on render completion, cleared by client
50 
51 //EL_FIXME 20 seconds may not be enough and must be reconciled with new obtainBuffer implementation
52 #define MAX_RUN_OFFLOADED_TIMEOUT_MS 20000 // assuming up to a maximum of 20 seconds of offloaded
53 
54 struct AudioTrackSharedStreaming {
55     // similar to NBAIO MonoPipe
56     // in continuously incrementing frame units, take modulo buffer size, which must be a power of 2
57     volatile int32_t mFront;    // read by server
58     volatile int32_t mRear;     // write by client
59     volatile int32_t mFlush;    // incremented by client to indicate a request to flush;
60                                 // server notices and discards all data between mFront and mRear
61     volatile uint32_t mUnderrunFrames;  // server increments for each unavailable but desired frame
62 };
63 
64 typedef SingleStateQueue<StaticAudioTrackState> StaticAudioTrackSingleStateQueue;
65 
66 struct AudioTrackSharedStatic {
67     StaticAudioTrackSingleStateQueue::Shared
68                     mSingleStateQueue;
69     // This field should be a size_t, but since it is located in shared memory we
70     // force to 32-bit.  The client and server may have different typedefs for size_t.
71     uint32_t        mBufferPosition;    // updated asynchronously by server,
72                                         // "for entertainment purposes only"
73 };
74 
75 // ----------------------------------------------------------------------------
76 
77 // Important: do not add any virtual methods, including ~
78 struct audio_track_cblk_t
79 {
80                 // Since the control block is always located in shared memory, this constructor
81                 // is only used for placement new().  It is never used for regular new() or stack.
82                             audio_track_cblk_t();
~audio_track_cblk_taudio_track_cblk_t83                 /*virtual*/ ~audio_track_cblk_t() { }
84 
85                 friend class Proxy;
86                 friend class ClientProxy;
87                 friend class AudioTrackClientProxy;
88                 friend class AudioRecordClientProxy;
89                 friend class ServerProxy;
90                 friend class AudioTrackServerProxy;
91                 friend class AudioRecordServerProxy;
92 
93     // The data members are grouped so that members accessed frequently and in the same context
94     // are in the same line of data cache.
95 
96                 uint32_t    mServer;    // Number of filled frames consumed by server (mIsOut),
97                                         // or filled frames provided by server (!mIsOut).
98                                         // It is updated asynchronously by server without a barrier.
99                                         // The value should be used "for entertainment purposes only",
100                                         // which means don't make important decisions based on it.
101 
102                 uint32_t    mPad1;      // unused
103 
104     volatile    int32_t     mFutex;     // event flag: down (P) by client,
105                                         // up (V) by server or binderDied() or interrupt()
106 #define CBLK_FUTEX_WAKE 1               // if event flag bit is set, then a deferred wake is pending
107 
108 private:
109 
110                 // This field should be a size_t, but since it is located in shared memory we
111                 // force to 32-bit.  The client and server may have different typedefs for size_t.
112                 uint32_t    mMinimum;       // server wakes up client if available >= mMinimum
113 
114                 // Stereo gains for AudioTrack only, not used by AudioRecord.
115                 gain_minifloat_packed_t mVolumeLR;
116 
117                 uint32_t    mSampleRate;    // AudioTrack only: client's requested sample rate in Hz
118                                             // or 0 == default. Write-only client, read-only server.
119 
120                 // client write-only, server read-only
121                 uint16_t    mSendLevel;      // Fixed point U4.12 so 0x1000 means 1.0
122 
123                 uint16_t    mPad2;           // unused
124 
125 public:
126 
127     volatile    int32_t     mFlags;         // combinations of CBLK_*
128 
129                 // Cache line boundary (32 bytes)
130 
131 public:
132                 union {
133                     AudioTrackSharedStreaming   mStreaming;
134                     AudioTrackSharedStatic      mStatic;
135                     int                         mAlign[8];
136                 } u;
137 
138                 // Cache line boundary (32 bytes)
139 };
140 
141 // ----------------------------------------------------------------------------
142 
143 // Proxy for shared memory control block, to isolate callers from needing to know the details.
144 // There is exactly one ClientProxy and one ServerProxy per shared memory control block.
145 // The proxies are located in normal memory, and are not multi-thread safe within a given side.
146 class Proxy : public RefBase {
147 protected:
148     Proxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize, bool isOut,
149             bool clientInServer);
~Proxy()150     virtual ~Proxy() { }
151 
152 public:
153     struct Buffer {
154         size_t  mFrameCount;            // number of frames available in this buffer
155         void*   mRaw;                   // pointer to first frame
156         size_t  mNonContig;             // number of additional non-contiguous frames available
157     };
158 
159 protected:
160     // These refer to shared memory, and are virtual addresses with respect to the current process.
161     // They may have different virtual addresses within the other process.
162     audio_track_cblk_t* const   mCblk;  // the control block
163     void* const     mBuffers;           // starting address of buffers
164 
165     const size_t    mFrameCount;        // not necessarily a power of 2
166     const size_t    mFrameSize;         // in bytes
167     const size_t    mFrameCountP2;      // mFrameCount rounded to power of 2, streaming mode
168     const bool      mIsOut;             // true for AudioTrack, false for AudioRecord
169     const bool      mClientInServer;    // true for OutputTrack, false for AudioTrack & AudioRecord
170     bool            mIsShutdown;        // latch set to true when shared memory corruption detected
171     size_t          mUnreleased;        // unreleased frames remaining from most recent obtainBuffer
172 };
173 
174 // ----------------------------------------------------------------------------
175 
176 // Proxy seen by AudioTrack client and AudioRecord client
177 class ClientProxy : public Proxy {
178 public:
179     ClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize,
180             bool isOut, bool clientInServer);
~ClientProxy()181     virtual ~ClientProxy() { }
182 
183     static const struct timespec kForever;
184     static const struct timespec kNonBlocking;
185 
186     // Obtain a buffer with filled frames (reading) or empty frames (writing).
187     // It is permitted to call obtainBuffer() multiple times in succession, without any intervening
188     // calls to releaseBuffer().  In that case, the final obtainBuffer() is the one that effectively
189     // sets or extends the unreleased frame count.
190     // On entry:
191     //  buffer->mFrameCount should be initialized to maximum number of desired frames,
192     //      which must be > 0.
193     //  buffer->mNonContig is unused.
194     //  buffer->mRaw is unused.
195     //  requested is the requested timeout in local monotonic delta time units:
196     //      NULL or &kNonBlocking means non-blocking (zero timeout).
197     //      &kForever means block forever (infinite timeout).
198     //      Other values mean a specific timeout in local monotonic delta time units.
199     //  elapsed is a pointer to a location that will hold the total local monotonic time that
200     //      elapsed while blocked, or NULL if not needed.
201     // On exit:
202     //  buffer->mFrameCount has the actual number of contiguous available frames,
203     //      which is always 0 when the return status != NO_ERROR.
204     //  buffer->mNonContig is the number of additional non-contiguous available frames.
205     //  buffer->mRaw is a pointer to the first available frame,
206     //      or NULL when buffer->mFrameCount == 0.
207     // The return status is one of:
208     //  NO_ERROR    Success, buffer->mFrameCount > 0.
209     //  WOULD_BLOCK Non-blocking mode and no frames are available.
210     //  TIMED_OUT   Timeout occurred before any frames became available.
211     //              This can happen even for infinite timeout, due to a spurious wakeup.
212     //              In this case, the caller should investigate and then re-try as appropriate.
213     //  DEAD_OBJECT Server has died or invalidated, caller should destroy this proxy and re-create.
214     //  -EINTR      Call has been interrupted.  Look around to see why, and then perhaps try again.
215     //  NO_INIT     Shared memory is corrupt.
216     // Assertion failure on entry, if buffer == NULL or buffer->mFrameCount == 0.
217     status_t    obtainBuffer(Buffer* buffer, const struct timespec *requested = NULL,
218             struct timespec *elapsed = NULL);
219 
220     // Release (some of) the frames last obtained.
221     // On entry, buffer->mFrameCount should have the number of frames to release,
222     // which must (cumulatively) be <= the number of frames last obtained but not yet released.
223     // buffer->mRaw is ignored, but is normally same pointer returned by last obtainBuffer().
224     // It is permitted to call releaseBuffer() multiple times to release the frames in chunks.
225     // On exit:
226     //  buffer->mFrameCount is zero.
227     //  buffer->mRaw is NULL.
228     void        releaseBuffer(Buffer* buffer);
229 
230     // Call after detecting server's death
231     void        binderDied();
232 
233     // Call to force an obtainBuffer() to return quickly with -EINTR
234     void        interrupt();
235 
getPosition()236     size_t      getPosition() {
237         return mEpoch + mCblk->mServer;
238     }
239 
setEpoch(size_t epoch)240     void        setEpoch(size_t epoch) {
241         mEpoch = epoch;
242     }
243 
setMinimum(size_t minimum)244     void        setMinimum(size_t minimum) {
245         // This can only happen on a 64-bit client
246         if (minimum > UINT32_MAX) {
247             minimum = UINT32_MAX;
248         }
249         mCblk->mMinimum = (uint32_t) minimum;
250     }
251 
252     // Return the number of frames that would need to be obtained and released
253     // in order for the client to be aligned at start of buffer
254     virtual size_t  getMisalignment();
255 
getEpoch()256     size_t      getEpoch() const {
257         return mEpoch;
258     }
259 
260     size_t      getFramesFilled();
261 
262 private:
263     size_t      mEpoch;
264 };
265 
266 // ----------------------------------------------------------------------------
267 
268 // Proxy used by AudioTrack client, which also includes AudioFlinger::PlaybackThread::OutputTrack
269 class AudioTrackClientProxy : public ClientProxy {
270 public:
271     AudioTrackClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
272             size_t frameSize, bool clientInServer = false)
ClientProxy(cblk,buffers,frameCount,frameSize,true,clientInServer)273         : ClientProxy(cblk, buffers, frameCount, frameSize, true /*isOut*/,
274           clientInServer) { }
~AudioTrackClientProxy()275     virtual ~AudioTrackClientProxy() { }
276 
277     // No barriers on the following operations, so the ordering of loads/stores
278     // with respect to other parameters is UNPREDICTABLE. That's considered safe.
279 
280     // caller must limit to 0.0 <= sendLevel <= 1.0
setSendLevel(float sendLevel)281     void        setSendLevel(float sendLevel) {
282         mCblk->mSendLevel = uint16_t(sendLevel * 0x1000);
283     }
284 
285     // set stereo gains
setVolumeLR(gain_minifloat_packed_t volumeLR)286     void        setVolumeLR(gain_minifloat_packed_t volumeLR) {
287         mCblk->mVolumeLR = volumeLR;
288     }
289 
setSampleRate(uint32_t sampleRate)290     void        setSampleRate(uint32_t sampleRate) {
291         mCblk->mSampleRate = sampleRate;
292     }
293 
294     virtual void flush();
295 
getUnderrunFrames()296     virtual uint32_t    getUnderrunFrames() const {
297         return mCblk->u.mStreaming.mUnderrunFrames;
298     }
299 
300     bool        clearStreamEndDone();   // and return previous value
301 
302     bool        getStreamEndDone() const;
303 
304     status_t    waitStreamEndDone(const struct timespec *requested);
305 };
306 
307 class StaticAudioTrackClientProxy : public AudioTrackClientProxy {
308 public:
309     StaticAudioTrackClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
310             size_t frameSize);
~StaticAudioTrackClientProxy()311     virtual ~StaticAudioTrackClientProxy() { }
312 
313     virtual void    flush();
314 
315 #define MIN_LOOP    16  // minimum length of each loop iteration in frames
316             void    setLoop(size_t loopStart, size_t loopEnd, int loopCount);
317             size_t  getBufferPosition();
318 
getMisalignment()319     virtual size_t  getMisalignment() {
320         return 0;
321     }
322 
getUnderrunFrames()323     virtual uint32_t    getUnderrunFrames() const {
324         return 0;
325     }
326 
327 private:
328     StaticAudioTrackSingleStateQueue::Mutator   mMutator;
329     size_t          mBufferPosition;    // so that getBufferPosition() appears to be synchronous
330 };
331 
332 // ----------------------------------------------------------------------------
333 
334 // Proxy used by AudioRecord client
335 class AudioRecordClientProxy : public ClientProxy {
336 public:
AudioRecordClientProxy(audio_track_cblk_t * cblk,void * buffers,size_t frameCount,size_t frameSize)337     AudioRecordClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
338             size_t frameSize)
339         : ClientProxy(cblk, buffers, frameCount, frameSize,
340             false /*isOut*/, false /*clientInServer*/) { }
~AudioRecordClientProxy()341     ~AudioRecordClientProxy() { }
342 };
343 
344 // ----------------------------------------------------------------------------
345 
346 // Proxy used by AudioFlinger server
347 class ServerProxy : public Proxy {
348 protected:
349     ServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize,
350             bool isOut, bool clientInServer);
351 public:
~ServerProxy()352     virtual ~ServerProxy() { }
353 
354     // Obtain a buffer with filled frames (writing) or empty frames (reading).
355     // It is permitted to call obtainBuffer() multiple times in succession, without any intervening
356     // calls to releaseBuffer().  In that case, the final obtainBuffer() is the one that effectively
357     // sets or extends the unreleased frame count.
358     // Always non-blocking.
359     // On entry:
360     //  buffer->mFrameCount should be initialized to maximum number of desired frames,
361     //      which must be > 0.
362     //  buffer->mNonContig is unused.
363     //  buffer->mRaw is unused.
364     //  ackFlush is true iff being called from Track::start to acknowledge a pending flush.
365     // On exit:
366     //  buffer->mFrameCount has the actual number of contiguous available frames,
367     //      which is always 0 when the return status != NO_ERROR.
368     //  buffer->mNonContig is the number of additional non-contiguous available frames.
369     //  buffer->mRaw is a pointer to the first available frame,
370     //      or NULL when buffer->mFrameCount == 0.
371     // The return status is one of:
372     //  NO_ERROR    Success, buffer->mFrameCount > 0.
373     //  WOULD_BLOCK No frames are available.
374     //  NO_INIT     Shared memory is corrupt.
375     virtual status_t    obtainBuffer(Buffer* buffer, bool ackFlush = false);
376 
377     // Release (some of) the frames last obtained.
378     // On entry, buffer->mFrameCount should have the number of frames to release,
379     // which must (cumulatively) be <= the number of frames last obtained but not yet released.
380     // It is permitted to call releaseBuffer() multiple times to release the frames in chunks.
381     // buffer->mRaw is ignored, but is normally same pointer returned by last obtainBuffer().
382     // On exit:
383     //  buffer->mFrameCount is zero.
384     //  buffer->mRaw is NULL.
385     virtual void        releaseBuffer(Buffer* buffer);
386 
387 protected:
388     size_t      mAvailToClient; // estimated frames available to client prior to releaseBuffer()
389     int32_t     mFlush;         // our copy of cblk->u.mStreaming.mFlush, for streaming output only
390 };
391 
392 // Proxy used by AudioFlinger for servicing AudioTrack
393 class AudioTrackServerProxy : public ServerProxy {
394 public:
395     AudioTrackServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
396             size_t frameSize, bool clientInServer = false, uint32_t sampleRate = 0)
ServerProxy(cblk,buffers,frameCount,frameSize,true,clientInServer)397         : ServerProxy(cblk, buffers, frameCount, frameSize, true /*isOut*/, clientInServer) {
398         mCblk->mSampleRate = sampleRate;
399     }
400 protected:
~AudioTrackServerProxy()401     virtual ~AudioTrackServerProxy() { }
402 
403 public:
404     // return value of these methods must be validated by the caller
getSampleRate()405     uint32_t    getSampleRate() const { return mCblk->mSampleRate; }
getSendLevel_U4_12()406     uint16_t    getSendLevel_U4_12() const { return mCblk->mSendLevel; }
getVolumeLR()407     gain_minifloat_packed_t getVolumeLR() const { return mCblk->mVolumeLR; }
408 
409     // estimated total number of filled frames available to server to read,
410     // which may include non-contiguous frames
411     virtual size_t      framesReady();
412 
413     // Currently AudioFlinger will call framesReady() for a fast track from two threads:
414     // FastMixer thread, and normal mixer thread.  This is dangerous, as the proxy is intended
415     // to be called from at most one thread of server, and one thread of client.
416     // As a temporary workaround, this method informs the proxy implementation that it
417     // should avoid doing a state queue poll from within framesReady().
418     // FIXME Change AudioFlinger to not call framesReady() from normal mixer thread.
framesReadyIsCalledByMultipleThreads()419     virtual void        framesReadyIsCalledByMultipleThreads() { }
420 
421     bool     setStreamEndDone();    // and return previous value
422 
423     // Add to the tally of underrun frames, and inform client of underrun
424     virtual void        tallyUnderrunFrames(uint32_t frameCount);
425 
426     // Return the total number of frames which AudioFlinger desired but were unavailable,
427     // and thus which resulted in an underrun.
getUnderrunFrames()428     virtual uint32_t    getUnderrunFrames() const { return mCblk->u.mStreaming.mUnderrunFrames; }
429 
430     // Return the total number of frames that AudioFlinger has obtained and released
framesReleased()431     virtual size_t      framesReleased() const { return mCblk->mServer; }
432 };
433 
434 class StaticAudioTrackServerProxy : public AudioTrackServerProxy {
435 public:
436     StaticAudioTrackServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
437             size_t frameSize);
438 protected:
~StaticAudioTrackServerProxy()439     virtual ~StaticAudioTrackServerProxy() { }
440 
441 public:
442     virtual size_t      framesReady();
443     virtual void        framesReadyIsCalledByMultipleThreads();
444     virtual status_t    obtainBuffer(Buffer* buffer, bool ackFlush);
445     virtual void        releaseBuffer(Buffer* buffer);
446     virtual void        tallyUnderrunFrames(uint32_t frameCount);
getUnderrunFrames()447     virtual uint32_t    getUnderrunFrames() const { return 0; }
448 
449 private:
450     ssize_t             pollPosition(); // poll for state queue update, and return current position
451     StaticAudioTrackSingleStateQueue::Observer  mObserver;
452     size_t              mPosition;  // server's current play position in frames, relative to 0
453     size_t              mEnd;       // cached value computed from mState, safe for asynchronous read
454     bool                mFramesReadyIsCalledByMultipleThreads;
455     StaticAudioTrackState   mState;
456 };
457 
458 // Proxy used by AudioFlinger for servicing AudioRecord
459 class AudioRecordServerProxy : public ServerProxy {
460 public:
AudioRecordServerProxy(audio_track_cblk_t * cblk,void * buffers,size_t frameCount,size_t frameSize,bool clientInServer)461     AudioRecordServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
462             size_t frameSize, bool clientInServer)
463         : ServerProxy(cblk, buffers, frameCount, frameSize, false /*isOut*/, clientInServer) { }
464 protected:
~AudioRecordServerProxy()465     virtual ~AudioRecordServerProxy() { }
466 };
467 
468 // ----------------------------------------------------------------------------
469 
470 }; // namespace android
471 
472 #endif // ANDROID_AUDIO_TRACK_SHARED_H
473