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 <audio_utils/roundup.h>
28#include <media/AudioResamplerPublic.h>
29#include <media/SingleStateQueue.h>
30
31namespace 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
54struct 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 consumer (output: server, input: client)
58    volatile int32_t mRear;     // written by producer (output: client, input: server)
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// Represents a single state of an AudioTrack that was created in static mode (shared memory buffer
65// supplied by the client).  This state needs to be communicated from the client to server.  As this
66// state is too large to be updated atomically without a mutex, and mutexes aren't allowed here, the
67// state is wrapped by a SingleStateQueue.
68struct StaticAudioTrackState {
69    // Do not define constructors, destructors, or virtual methods as this is part of a
70    // union in shared memory and they will not get called properly.
71
72    // These fields should both be size_t, but since they are located in shared memory we
73    // force to 32-bit.  The client and server may have different typedefs for size_t.
74
75    // The state has a sequence counter to indicate whether changes are made to loop or position.
76    // The sequence counter also currently indicates whether loop or position is first depending
77    // on which is greater; it jumps by max(mLoopSequence, mPositionSequence) + 1.
78
79    uint32_t    mLoopStart;
80    uint32_t    mLoopEnd;
81    int32_t     mLoopCount;
82    uint32_t    mLoopSequence; // a sequence counter to indicate changes to loop
83    uint32_t    mPosition;
84    uint32_t    mPositionSequence; // a sequence counter to indicate changes to position
85};
86
87typedef SingleStateQueue<StaticAudioTrackState> StaticAudioTrackSingleStateQueue;
88
89struct StaticAudioTrackPosLoop {
90    // Do not define constructors, destructors, or virtual methods as this is part of a
91    // union in shared memory and will not get called properly.
92
93    // These fields should both be size_t, but since they are located in shared memory we
94    // force to 32-bit.  The client and server may have different typedefs for size_t.
95
96    // This struct information is stored in a single state queue to communicate the
97    // static AudioTrack server state to the client while data is consumed.
98    // It is smaller than StaticAudioTrackState to prevent unnecessary information from
99    // being sent.
100
101    uint32_t mBufferPosition;
102    int32_t  mLoopCount;
103};
104
105typedef SingleStateQueue<StaticAudioTrackPosLoop> StaticAudioTrackPosLoopQueue;
106
107struct AudioTrackSharedStatic {
108    // client requests to the server for loop or position changes.
109    StaticAudioTrackSingleStateQueue::Shared
110                    mSingleStateQueue;
111    // position info updated asynchronously by server and read by client,
112    // "for entertainment purposes only"
113    StaticAudioTrackPosLoopQueue::Shared
114                    mPosLoopQueue;
115};
116
117typedef SingleStateQueue<AudioPlaybackRate> PlaybackRateQueue;
118
119// ----------------------------------------------------------------------------
120
121// Important: do not add any virtual methods, including ~
122struct audio_track_cblk_t
123{
124                // Since the control block is always located in shared memory, this constructor
125                // is only used for placement new().  It is never used for regular new() or stack.
126                            audio_track_cblk_t();
127                /*virtual*/ ~audio_track_cblk_t() { }
128
129                friend class Proxy;
130                friend class ClientProxy;
131                friend class AudioTrackClientProxy;
132                friend class AudioRecordClientProxy;
133                friend class ServerProxy;
134                friend class AudioTrackServerProxy;
135                friend class AudioRecordServerProxy;
136
137    // The data members are grouped so that members accessed frequently and in the same context
138    // are in the same line of data cache.
139
140                uint32_t    mServer;    // Number of filled frames consumed by server (mIsOut),
141                                        // or filled frames provided by server (!mIsOut).
142                                        // It is updated asynchronously by server without a barrier.
143                                        // The value should be used
144                                        // "for entertainment purposes only",
145                                        // which means don't make important decisions based on it.
146
147                uint32_t    mPad1;      // unused
148
149    volatile    int32_t     mFutex;     // event flag: down (P) by client,
150                                        // up (V) by server or binderDied() or interrupt()
151#define CBLK_FUTEX_WAKE 1               // if event flag bit is set, then a deferred wake is pending
152
153private:
154
155                // This field should be a size_t, but since it is located in shared memory we
156                // force to 32-bit.  The client and server may have different typedefs for size_t.
157                uint32_t    mMinimum;       // server wakes up client if available >= mMinimum
158
159                // Stereo gains for AudioTrack only, not used by AudioRecord.
160                gain_minifloat_packed_t mVolumeLR;
161
162                uint32_t    mSampleRate;    // AudioTrack only: client's requested sample rate in Hz
163                                            // or 0 == default. Write-only client, read-only server.
164
165                PlaybackRateQueue::Shared mPlaybackRateQueue;
166
167                // client write-only, server read-only
168                uint16_t    mSendLevel;      // Fixed point U4.12 so 0x1000 means 1.0
169
170                uint16_t    mPad2;           // unused
171
172public:
173
174    volatile    int32_t     mFlags;         // combinations of CBLK_*
175
176                // Cache line boundary (32 bytes)
177
178public:
179                union {
180                    AudioTrackSharedStreaming   mStreaming;
181                    AudioTrackSharedStatic      mStatic;
182                    int                         mAlign[8];
183                } u;
184
185                // Cache line boundary (32 bytes)
186};
187
188// ----------------------------------------------------------------------------
189
190// Proxy for shared memory control block, to isolate callers from needing to know the details.
191// There is exactly one ClientProxy and one ServerProxy per shared memory control block.
192// The proxies are located in normal memory, and are not multi-thread safe within a given side.
193class Proxy : public RefBase {
194protected:
195    Proxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize, bool isOut,
196            bool clientInServer);
197    virtual ~Proxy() { }
198
199public:
200    struct Buffer {
201        size_t  mFrameCount;            // number of frames available in this buffer
202        void*   mRaw;                   // pointer to first frame
203        size_t  mNonContig;             // number of additional non-contiguous frames available
204    };
205
206protected:
207    // These refer to shared memory, and are virtual addresses with respect to the current process.
208    // They may have different virtual addresses within the other process.
209    audio_track_cblk_t* const   mCblk;  // the control block
210    void* const     mBuffers;           // starting address of buffers
211
212    const size_t    mFrameCount;        // not necessarily a power of 2
213    const size_t    mFrameSize;         // in bytes
214    const size_t    mFrameCountP2;      // mFrameCount rounded to power of 2, streaming mode
215    const bool      mIsOut;             // true for AudioTrack, false for AudioRecord
216    const bool      mClientInServer;    // true for OutputTrack, false for AudioTrack & AudioRecord
217    bool            mIsShutdown;        // latch set to true when shared memory corruption detected
218    size_t          mUnreleased;        // unreleased frames remaining from most recent obtainBuffer
219};
220
221// ----------------------------------------------------------------------------
222
223// Proxy seen by AudioTrack client and AudioRecord client
224class ClientProxy : public Proxy {
225public:
226    ClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize,
227            bool isOut, bool clientInServer);
228    virtual ~ClientProxy() { }
229
230    static const struct timespec kForever;
231    static const struct timespec kNonBlocking;
232
233    // Obtain a buffer with filled frames (reading) or empty frames (writing).
234    // It is permitted to call obtainBuffer() multiple times in succession, without any intervening
235    // calls to releaseBuffer().  In that case, the final obtainBuffer() is the one that effectively
236    // sets or extends the unreleased frame count.
237    // On entry:
238    //  buffer->mFrameCount should be initialized to maximum number of desired frames,
239    //      which must be > 0.
240    //  buffer->mNonContig is unused.
241    //  buffer->mRaw is unused.
242    //  requested is the requested timeout in local monotonic delta time units:
243    //      NULL or &kNonBlocking means non-blocking (zero timeout).
244    //      &kForever means block forever (infinite timeout).
245    //      Other values mean a specific timeout in local monotonic delta time units.
246    //  elapsed is a pointer to a location that will hold the total local monotonic time that
247    //      elapsed while blocked, or NULL if not needed.
248    // On exit:
249    //  buffer->mFrameCount has the actual number of contiguous available frames,
250    //      which is always 0 when the return status != NO_ERROR.
251    //  buffer->mNonContig is the number of additional non-contiguous available frames.
252    //  buffer->mRaw is a pointer to the first available frame,
253    //      or NULL when buffer->mFrameCount == 0.
254    // The return status is one of:
255    //  NO_ERROR    Success, buffer->mFrameCount > 0.
256    //  WOULD_BLOCK Non-blocking mode and no frames are available.
257    //  TIMED_OUT   Timeout occurred before any frames became available.
258    //              This can happen even for infinite timeout, due to a spurious wakeup.
259    //              In this case, the caller should investigate and then re-try as appropriate.
260    //  DEAD_OBJECT Server has died or invalidated, caller should destroy this proxy and re-create.
261    //  -EINTR      Call has been interrupted.  Look around to see why, and then perhaps try again.
262    //  NO_INIT     Shared memory is corrupt.
263    // Assertion failure on entry, if buffer == NULL or buffer->mFrameCount == 0.
264    status_t    obtainBuffer(Buffer* buffer, const struct timespec *requested = NULL,
265            struct timespec *elapsed = NULL);
266
267    // Release (some of) the frames last obtained.
268    // On entry, buffer->mFrameCount should have the number of frames to release,
269    // which must (cumulatively) be <= the number of frames last obtained but not yet released.
270    // buffer->mRaw is ignored, but is normally same pointer returned by last obtainBuffer().
271    // It is permitted to call releaseBuffer() multiple times to release the frames in chunks.
272    // On exit:
273    //  buffer->mFrameCount is zero.
274    //  buffer->mRaw is NULL.
275    void        releaseBuffer(Buffer* buffer);
276
277    // Call after detecting server's death
278    void        binderDied();
279
280    // Call to force an obtainBuffer() to return quickly with -EINTR
281    void        interrupt();
282
283    size_t      getPosition() {
284        return mEpoch + mCblk->mServer;
285    }
286
287    void        setEpoch(size_t epoch) {
288        mEpoch = epoch;
289    }
290
291    void        setMinimum(size_t minimum) {
292        // This can only happen on a 64-bit client
293        if (minimum > UINT32_MAX) {
294            minimum = UINT32_MAX;
295        }
296        mCblk->mMinimum = (uint32_t) minimum;
297    }
298
299    // Return the number of frames that would need to be obtained and released
300    // in order for the client to be aligned at start of buffer
301    virtual size_t  getMisalignment();
302
303    size_t      getEpoch() const {
304        return mEpoch;
305    }
306
307    size_t      getFramesFilled();
308
309private:
310    size_t      mEpoch;
311};
312
313// ----------------------------------------------------------------------------
314
315// Proxy used by AudioTrack client, which also includes AudioFlinger::PlaybackThread::OutputTrack
316class AudioTrackClientProxy : public ClientProxy {
317public:
318    AudioTrackClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
319            size_t frameSize, bool clientInServer = false)
320        : ClientProxy(cblk, buffers, frameCount, frameSize, true /*isOut*/,
321          clientInServer),
322          mPlaybackRateMutator(&cblk->mPlaybackRateQueue) { }
323    virtual ~AudioTrackClientProxy() { }
324
325    // No barriers on the following operations, so the ordering of loads/stores
326    // with respect to other parameters is UNPREDICTABLE. That's considered safe.
327
328    // caller must limit to 0.0 <= sendLevel <= 1.0
329    void        setSendLevel(float sendLevel) {
330        mCblk->mSendLevel = uint16_t(sendLevel * 0x1000);
331    }
332
333    // set stereo gains
334    void        setVolumeLR(gain_minifloat_packed_t volumeLR) {
335        mCblk->mVolumeLR = volumeLR;
336    }
337
338    void        setSampleRate(uint32_t sampleRate) {
339        mCblk->mSampleRate = sampleRate;
340    }
341
342    void        setPlaybackRate(const AudioPlaybackRate& playbackRate) {
343        mPlaybackRateMutator.push(playbackRate);
344    }
345
346    virtual void flush();
347
348    virtual uint32_t    getUnderrunFrames() const {
349        return mCblk->u.mStreaming.mUnderrunFrames;
350    }
351
352    bool        clearStreamEndDone();   // and return previous value
353
354    bool        getStreamEndDone() const;
355
356    status_t    waitStreamEndDone(const struct timespec *requested);
357
358private:
359    PlaybackRateQueue::Mutator   mPlaybackRateMutator;
360};
361
362class StaticAudioTrackClientProxy : public AudioTrackClientProxy {
363public:
364    StaticAudioTrackClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
365            size_t frameSize);
366    virtual ~StaticAudioTrackClientProxy() { }
367
368    virtual void    flush();
369
370#define MIN_LOOP    16  // minimum length of each loop iteration in frames
371
372            // setLoop(), setBufferPosition(), and setBufferPositionAndLoop() set the
373            // static buffer position and looping parameters.  These commands are not
374            // synchronous (they do not wait or block); instead they take effect at the
375            // next buffer data read from the server side. However, the client side
376            // getters will read a cached version of the position and loop variables
377            // until the setting takes effect.
378            //
379            // setBufferPositionAndLoop() is equivalent to calling, in order, setLoop() and
380            // setBufferPosition().
381            //
382            // The functions should not be relied upon to do parameter or state checking.
383            // That is done at the AudioTrack level.
384
385            void    setLoop(size_t loopStart, size_t loopEnd, int loopCount);
386            void    setBufferPosition(size_t position);
387            void    setBufferPositionAndLoop(size_t position, size_t loopStart, size_t loopEnd,
388                                             int loopCount);
389            size_t  getBufferPosition();
390                    // getBufferPositionAndLoopCount() provides the proper snapshot of
391                    // position and loopCount together.
392            void    getBufferPositionAndLoopCount(size_t *position, int *loopCount);
393
394    virtual size_t  getMisalignment() {
395        return 0;
396    }
397
398    virtual uint32_t    getUnderrunFrames() const {
399        return 0;
400    }
401
402private:
403    StaticAudioTrackSingleStateQueue::Mutator   mMutator;
404    StaticAudioTrackPosLoopQueue::Observer      mPosLoopObserver;
405                        StaticAudioTrackState   mState;   // last communicated state to server
406                        StaticAudioTrackPosLoop mPosLoop; // snapshot of position and loop.
407};
408
409// ----------------------------------------------------------------------------
410
411// Proxy used by AudioRecord client
412class AudioRecordClientProxy : public ClientProxy {
413public:
414    AudioRecordClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
415            size_t frameSize)
416        : ClientProxy(cblk, buffers, frameCount, frameSize,
417            false /*isOut*/, false /*clientInServer*/) { }
418    ~AudioRecordClientProxy() { }
419};
420
421// ----------------------------------------------------------------------------
422
423// Proxy used by AudioFlinger server
424class ServerProxy : public Proxy {
425protected:
426    ServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize,
427            bool isOut, bool clientInServer);
428public:
429    virtual ~ServerProxy() { }
430
431    // Obtain a buffer with filled frames (writing) or empty frames (reading).
432    // It is permitted to call obtainBuffer() multiple times in succession, without any intervening
433    // calls to releaseBuffer().  In that case, the final obtainBuffer() is the one that effectively
434    // sets or extends the unreleased frame count.
435    // Always non-blocking.
436    // On entry:
437    //  buffer->mFrameCount should be initialized to maximum number of desired frames,
438    //      which must be > 0.
439    //  buffer->mNonContig is unused.
440    //  buffer->mRaw is unused.
441    //  ackFlush is true iff being called from Track::start to acknowledge a pending flush.
442    // On exit:
443    //  buffer->mFrameCount has the actual number of contiguous available frames,
444    //      which is always 0 when the return status != NO_ERROR.
445    //  buffer->mNonContig is the number of additional non-contiguous available frames.
446    //  buffer->mRaw is a pointer to the first available frame,
447    //      or NULL when buffer->mFrameCount == 0.
448    // The return status is one of:
449    //  NO_ERROR    Success, buffer->mFrameCount > 0.
450    //  WOULD_BLOCK No frames are available.
451    //  NO_INIT     Shared memory is corrupt.
452    virtual status_t    obtainBuffer(Buffer* buffer, bool ackFlush = false);
453
454    // Release (some of) the frames last obtained.
455    // On entry, buffer->mFrameCount should have the number of frames to release,
456    // which must (cumulatively) be <= the number of frames last obtained but not yet released.
457    // It is permitted to call releaseBuffer() multiple times to release the frames in chunks.
458    // buffer->mRaw is ignored, but is normally same pointer returned by last obtainBuffer().
459    // On exit:
460    //  buffer->mFrameCount is zero.
461    //  buffer->mRaw is NULL.
462    virtual void        releaseBuffer(Buffer* buffer);
463
464protected:
465    size_t      mAvailToClient; // estimated frames available to client prior to releaseBuffer()
466    int32_t     mFlush;         // our copy of cblk->u.mStreaming.mFlush, for streaming output only
467};
468
469// Proxy used by AudioFlinger for servicing AudioTrack
470class AudioTrackServerProxy : public ServerProxy {
471public:
472    AudioTrackServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
473            size_t frameSize, bool clientInServer = false, uint32_t sampleRate = 0)
474        : ServerProxy(cblk, buffers, frameCount, frameSize, true /*isOut*/, clientInServer),
475          mPlaybackRateObserver(&cblk->mPlaybackRateQueue) {
476        mCblk->mSampleRate = sampleRate;
477        mPlaybackRate = AUDIO_PLAYBACK_RATE_DEFAULT;
478    }
479protected:
480    virtual ~AudioTrackServerProxy() { }
481
482public:
483    // return value of these methods must be validated by the caller
484    uint32_t    getSampleRate() const { return mCblk->mSampleRate; }
485    uint16_t    getSendLevel_U4_12() const { return mCblk->mSendLevel; }
486    gain_minifloat_packed_t getVolumeLR() const { return mCblk->mVolumeLR; }
487
488    // estimated total number of filled frames available to server to read,
489    // which may include non-contiguous frames
490    virtual size_t      framesReady();
491
492    // Currently AudioFlinger will call framesReady() for a fast track from two threads:
493    // FastMixer thread, and normal mixer thread.  This is dangerous, as the proxy is intended
494    // to be called from at most one thread of server, and one thread of client.
495    // As a temporary workaround, this method informs the proxy implementation that it
496    // should avoid doing a state queue poll from within framesReady().
497    // FIXME Change AudioFlinger to not call framesReady() from normal mixer thread.
498    virtual void        framesReadyIsCalledByMultipleThreads() { }
499
500    bool     setStreamEndDone();    // and return previous value
501
502    // Add to the tally of underrun frames, and inform client of underrun
503    virtual void        tallyUnderrunFrames(uint32_t frameCount);
504
505    // Return the total number of frames which AudioFlinger desired but were unavailable,
506    // and thus which resulted in an underrun.
507    virtual uint32_t    getUnderrunFrames() const { return mCblk->u.mStreaming.mUnderrunFrames; }
508
509    // Return the total number of frames that AudioFlinger has obtained and released
510    virtual size_t      framesReleased() const { return mCblk->mServer; }
511
512    // Return the playback speed and pitch read atomically. Not multi-thread safe on server side.
513    AudioPlaybackRate getPlaybackRate();
514
515private:
516    AudioPlaybackRate             mPlaybackRate;  // last observed playback rate
517    PlaybackRateQueue::Observer   mPlaybackRateObserver;
518};
519
520class StaticAudioTrackServerProxy : public AudioTrackServerProxy {
521public:
522    StaticAudioTrackServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
523            size_t frameSize);
524protected:
525    virtual ~StaticAudioTrackServerProxy() { }
526
527public:
528    virtual size_t      framesReady();
529    virtual void        framesReadyIsCalledByMultipleThreads();
530    virtual status_t    obtainBuffer(Buffer* buffer, bool ackFlush);
531    virtual void        releaseBuffer(Buffer* buffer);
532    virtual void        tallyUnderrunFrames(uint32_t frameCount);
533    virtual uint32_t    getUnderrunFrames() const { return 0; }
534
535private:
536    status_t            updateStateWithLoop(StaticAudioTrackState *localState,
537                                            const StaticAudioTrackState &update) const;
538    status_t            updateStateWithPosition(StaticAudioTrackState *localState,
539                                                const StaticAudioTrackState &update) const;
540    ssize_t             pollPosition(); // poll for state queue update, and return current position
541    StaticAudioTrackSingleStateQueue::Observer  mObserver;
542    StaticAudioTrackPosLoopQueue::Mutator       mPosLoopMutator;
543    size_t              mFramesReadySafe; // Assuming size_t read/writes are atomic on 32 / 64 bit
544                                          // processors, this is a thread-safe version of
545                                          // mFramesReady.
546    int64_t             mFramesReady;     // The number of frames ready in the static buffer
547                                          // including loops.  This is 64 bits since loop mode
548                                          // can cause a track to appear to have a large number
549                                          // of frames. INT64_MAX means an infinite loop.
550    bool                mFramesReadyIsCalledByMultipleThreads;
551    StaticAudioTrackState mState;         // Server side state. Any updates from client must be
552                                          // passed by the mObserver SingleStateQueue.
553};
554
555// Proxy used by AudioFlinger for servicing AudioRecord
556class AudioRecordServerProxy : public ServerProxy {
557public:
558    AudioRecordServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
559            size_t frameSize, bool clientInServer)
560        : ServerProxy(cblk, buffers, frameCount, frameSize, false /*isOut*/, clientInServer) { }
561protected:
562    virtual ~AudioRecordServerProxy() { }
563};
564
565// ----------------------------------------------------------------------------
566
567}; // namespace android
568
569#endif // ANDROID_AUDIO_TRACK_SHARED_H
570