1*ec779b8eSAndroid Build Coastguard Worker /* 2*ec779b8eSAndroid Build Coastguard Worker * Copyright (C) 2007 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 #ifndef ANDROID_AUDIO_TRACK_SHARED_H 18*ec779b8eSAndroid Build Coastguard Worker #define ANDROID_AUDIO_TRACK_SHARED_H 19*ec779b8eSAndroid Build Coastguard Worker 20*ec779b8eSAndroid Build Coastguard Worker #include <stdint.h> 21*ec779b8eSAndroid Build Coastguard Worker #include <sys/types.h> 22*ec779b8eSAndroid Build Coastguard Worker 23*ec779b8eSAndroid Build Coastguard Worker #include <audio_utils/minifloat.h> 24*ec779b8eSAndroid Build Coastguard Worker #include <utils/threads.h> 25*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h> 26*ec779b8eSAndroid Build Coastguard Worker #include <utils/RefBase.h> 27*ec779b8eSAndroid Build Coastguard Worker #include <audio_utils/roundup.h> 28*ec779b8eSAndroid Build Coastguard Worker #include <media/AudioResamplerPublic.h> 29*ec779b8eSAndroid Build Coastguard Worker #include <media/AudioTimestamp.h> 30*ec779b8eSAndroid Build Coastguard Worker #include <media/Modulo.h> 31*ec779b8eSAndroid Build Coastguard Worker #include <media/nbaio/SingleStateQueue.h> 32*ec779b8eSAndroid Build Coastguard Worker 33*ec779b8eSAndroid Build Coastguard Worker namespace android { 34*ec779b8eSAndroid Build Coastguard Worker 35*ec779b8eSAndroid Build Coastguard Worker // ---------------------------------------------------------------------------- 36*ec779b8eSAndroid Build Coastguard Worker 37*ec779b8eSAndroid Build Coastguard Worker // for audio_track_cblk_t::mFlags 38*ec779b8eSAndroid Build Coastguard Worker #define CBLK_UNDERRUN 0x01 // set by server immediately on output underrun, cleared by client 39*ec779b8eSAndroid Build Coastguard Worker #define CBLK_FORCEREADY 0x02 // set: track is considered ready immediately by AudioFlinger, 40*ec779b8eSAndroid Build Coastguard Worker // clear: track is ready when buffer full 41*ec779b8eSAndroid Build Coastguard Worker #define CBLK_INVALID 0x04 // track buffer invalidated by AudioFlinger, need to re-create 42*ec779b8eSAndroid Build Coastguard Worker #define CBLK_DISABLED 0x08 // output track disabled by AudioFlinger due to underrun, 43*ec779b8eSAndroid Build Coastguard Worker // need to re-start. Unlike CBLK_UNDERRUN, this is not set 44*ec779b8eSAndroid Build Coastguard Worker // immediately, but only after a long string of underruns. 45*ec779b8eSAndroid Build Coastguard Worker // 0x10 unused 46*ec779b8eSAndroid Build Coastguard Worker #define CBLK_LOOP_CYCLE 0x20 // set by server each time a loop cycle other than final one completes 47*ec779b8eSAndroid Build Coastguard Worker #define CBLK_LOOP_FINAL 0x40 // set by server when the final loop cycle completes 48*ec779b8eSAndroid Build Coastguard Worker #define CBLK_BUFFER_END 0x80 // set by server when the position reaches end of buffer if not looping 49*ec779b8eSAndroid Build Coastguard Worker #define CBLK_OVERRUN 0x100 // set by server immediately on input overrun, cleared by client 50*ec779b8eSAndroid Build Coastguard Worker #define CBLK_INTERRUPT 0x200 // set by client on interrupt(), cleared by client in obtainBuffer() 51*ec779b8eSAndroid Build Coastguard Worker #define CBLK_STREAM_END_DONE 0x400 // set by server on render completion, cleared by client 52*ec779b8eSAndroid Build Coastguard Worker 53*ec779b8eSAndroid Build Coastguard Worker //EL_FIXME 20 seconds may not be enough and must be reconciled with new obtainBuffer implementation 54*ec779b8eSAndroid Build Coastguard Worker #define MAX_RUN_OFFLOADED_TIMEOUT_MS 20000 // assuming up to a maximum of 20 seconds of offloaded 55*ec779b8eSAndroid Build Coastguard Worker 56*ec779b8eSAndroid Build Coastguard Worker // for audio_track_cblk_t::mState, to match TrackBase.h 57*ec779b8eSAndroid Build Coastguard Worker static inline constexpr int CBLK_STATE_IDLE = 0; 58*ec779b8eSAndroid Build Coastguard Worker static inline constexpr int CBLK_STATE_ACTIVE = 6; 59*ec779b8eSAndroid Build Coastguard Worker static inline constexpr int CBLK_STATE_PAUSING = 7; 60*ec779b8eSAndroid Build Coastguard Worker 61*ec779b8eSAndroid Build Coastguard Worker /** 62*ec779b8eSAndroid Build Coastguard Worker * MirroredVariable is a local variable which simultaneously updates 63*ec779b8eSAndroid Build Coastguard Worker * a mirrored storage location. This is useful for server side variables 64*ec779b8eSAndroid Build Coastguard Worker * where a local copy is kept, but a client visible copy is offered through shared memory. 65*ec779b8eSAndroid Build Coastguard Worker * 66*ec779b8eSAndroid Build Coastguard Worker * We use std::atomic as the default container class to access this memory. 67*ec779b8eSAndroid Build Coastguard Worker */ 68*ec779b8eSAndroid Build Coastguard Worker template <typename T, template <typename> class Container = std::atomic> 69*ec779b8eSAndroid Build Coastguard Worker class MirroredVariable { 70*ec779b8eSAndroid Build Coastguard Worker template <typename C> 71*ec779b8eSAndroid Build Coastguard Worker struct Constraints { 72*ec779b8eSAndroid Build Coastguard Worker // If setMirror is used with a different type U != T passed in, 73*ec779b8eSAndroid Build Coastguard Worker // as a general rule, the Container must issue a memcpy to read or write 74*ec779b8eSAndroid Build Coastguard Worker // (or its equivalent) to avoid possible strict aliasing issues. 75*ec779b8eSAndroid Build Coastguard Worker // The memcpy also avoids gaps in structs and alignment issues with different types. 76*ec779b8eSAndroid Build Coastguard Worker static constexpr bool ok_ = false; // Containers must specify constraints. 77*ec779b8eSAndroid Build Coastguard Worker }; 78*ec779b8eSAndroid Build Coastguard Worker template <typename X> 79*ec779b8eSAndroid Build Coastguard Worker struct Constraints<std::atomic<X>> { 80*ec779b8eSAndroid Build Coastguard Worker // Atomics force read and write to memory. 81*ec779b8eSAndroid Build Coastguard Worker static constexpr bool ok = std::is_same_v<X, T> || 82*ec779b8eSAndroid Build Coastguard Worker (std::atomic<X>::is_always_lock_free // no additional locking 83*ec779b8eSAndroid Build Coastguard Worker && sizeof(std::atomic<X>) == sizeof(X) // layout identical to X. 84*ec779b8eSAndroid Build Coastguard Worker && (std::is_arithmetic_v<X> || std::is_enum_v<X>)); // No gaps in the layout. 85*ec779b8eSAndroid Build Coastguard Worker }; 86*ec779b8eSAndroid Build Coastguard Worker 87*ec779b8eSAndroid Build Coastguard Worker static_assert(Constraints<Container<T>>::ok); 88*ec779b8eSAndroid Build Coastguard Worker public: 89*ec779b8eSAndroid Build Coastguard Worker explicit MirroredVariable(const T& t) : t_{t} {} 90*ec779b8eSAndroid Build Coastguard Worker 91*ec779b8eSAndroid Build Coastguard Worker // implicit conversion operator 92*ec779b8eSAndroid Build Coastguard Worker operator T() const { 93*ec779b8eSAndroid Build Coastguard Worker return t_; 94*ec779b8eSAndroid Build Coastguard Worker } 95*ec779b8eSAndroid Build Coastguard Worker 96*ec779b8eSAndroid Build Coastguard Worker MirroredVariable& operator=(const T& t) { 97*ec779b8eSAndroid Build Coastguard Worker t_ = t; 98*ec779b8eSAndroid Build Coastguard Worker if (mirror_ != nullptr) { 99*ec779b8eSAndroid Build Coastguard Worker *mirror_ = t; 100*ec779b8eSAndroid Build Coastguard Worker } 101*ec779b8eSAndroid Build Coastguard Worker return *this; 102*ec779b8eSAndroid Build Coastguard Worker } 103*ec779b8eSAndroid Build Coastguard Worker 104*ec779b8eSAndroid Build Coastguard Worker template <typename U> 105*ec779b8eSAndroid Build Coastguard Worker void setMirror(Container<U> *other_mirror) { 106*ec779b8eSAndroid Build Coastguard Worker // Much of the concern is with T != U, however there are additional concerns 107*ec779b8eSAndroid Build Coastguard Worker // when storage uses shared memory between processes. For atomics, it must be 108*ec779b8eSAndroid Build Coastguard Worker // lock free. 109*ec779b8eSAndroid Build Coastguard Worker static_assert(sizeof(U) == sizeof(T)); 110*ec779b8eSAndroid Build Coastguard Worker static_assert(alignof(U) == alignof(T)); 111*ec779b8eSAndroid Build Coastguard Worker static_assert(Constraints<Container<U>>::ok); 112*ec779b8eSAndroid Build Coastguard Worker static_assert(sizeof(Container<U>) == sizeof(Container<T>)); 113*ec779b8eSAndroid Build Coastguard Worker static_assert(alignof(Container<U>) == alignof(Container<T>)); 114*ec779b8eSAndroid Build Coastguard Worker auto mirror = reinterpret_cast<Container<T>*>(other_mirror); 115*ec779b8eSAndroid Build Coastguard Worker if (mirror_ != mirror) { 116*ec779b8eSAndroid Build Coastguard Worker mirror_ = mirror; 117*ec779b8eSAndroid Build Coastguard Worker if (mirror != nullptr) { 118*ec779b8eSAndroid Build Coastguard Worker *mirror = t_; 119*ec779b8eSAndroid Build Coastguard Worker } 120*ec779b8eSAndroid Build Coastguard Worker } 121*ec779b8eSAndroid Build Coastguard Worker } 122*ec779b8eSAndroid Build Coastguard Worker 123*ec779b8eSAndroid Build Coastguard Worker void clear() { 124*ec779b8eSAndroid Build Coastguard Worker mirror_ = nullptr; 125*ec779b8eSAndroid Build Coastguard Worker } 126*ec779b8eSAndroid Build Coastguard Worker 127*ec779b8eSAndroid Build Coastguard Worker MirroredVariable& operator&() const = delete; 128*ec779b8eSAndroid Build Coastguard Worker 129*ec779b8eSAndroid Build Coastguard Worker protected: 130*ec779b8eSAndroid Build Coastguard Worker T t_{}; 131*ec779b8eSAndroid Build Coastguard Worker Container<T>* mirror_ = nullptr; 132*ec779b8eSAndroid Build Coastguard Worker }; 133*ec779b8eSAndroid Build Coastguard Worker 134*ec779b8eSAndroid Build Coastguard Worker struct AudioTrackSharedStreaming { 135*ec779b8eSAndroid Build Coastguard Worker // similar to NBAIO MonoPipe 136*ec779b8eSAndroid Build Coastguard Worker // in continuously incrementing frame units, take modulo buffer size, which must be a power of 2 137*ec779b8eSAndroid Build Coastguard Worker volatile int32_t mFront; // read by consumer (output: server, input: client) 138*ec779b8eSAndroid Build Coastguard Worker volatile int32_t mRear; // written by producer (output: client, input: server) 139*ec779b8eSAndroid Build Coastguard Worker volatile int32_t mFlush; // incremented by client to indicate a request to flush; 140*ec779b8eSAndroid Build Coastguard Worker // server notices and discards all data between mFront and mRear 141*ec779b8eSAndroid Build Coastguard Worker volatile int32_t mStop; // set by client to indicate a stop frame position; server 142*ec779b8eSAndroid Build Coastguard Worker // will not read beyond this position until start is called. 143*ec779b8eSAndroid Build Coastguard Worker volatile uint32_t mUnderrunFrames; // server increments for each unavailable but desired frame 144*ec779b8eSAndroid Build Coastguard Worker volatile uint32_t mUnderrunCount; // server increments for each underrun occurrence 145*ec779b8eSAndroid Build Coastguard Worker }; 146*ec779b8eSAndroid Build Coastguard Worker 147*ec779b8eSAndroid Build Coastguard Worker // Represents a single state of an AudioTrack that was created in static mode (shared memory buffer 148*ec779b8eSAndroid Build Coastguard Worker // supplied by the client). This state needs to be communicated from the client to server. As this 149*ec779b8eSAndroid Build Coastguard Worker // state is too large to be updated atomically without a mutex, and mutexes aren't allowed here, the 150*ec779b8eSAndroid Build Coastguard Worker // state is wrapped by a SingleStateQueue. 151*ec779b8eSAndroid Build Coastguard Worker struct StaticAudioTrackState { 152*ec779b8eSAndroid Build Coastguard Worker // Do not define constructors, destructors, or virtual methods as this is part of a 153*ec779b8eSAndroid Build Coastguard Worker // union in shared memory and they will not get called properly. 154*ec779b8eSAndroid Build Coastguard Worker 155*ec779b8eSAndroid Build Coastguard Worker // These fields should both be size_t, but since they are located in shared memory we 156*ec779b8eSAndroid Build Coastguard Worker // force to 32-bit. The client and server may have different typedefs for size_t. 157*ec779b8eSAndroid Build Coastguard Worker 158*ec779b8eSAndroid Build Coastguard Worker // The state has a sequence counter to indicate whether changes are made to loop or position. 159*ec779b8eSAndroid Build Coastguard Worker // The sequence counter also currently indicates whether loop or position is first depending 160*ec779b8eSAndroid Build Coastguard Worker // on which is greater; it jumps by max(mLoopSequence, mPositionSequence) + 1. 161*ec779b8eSAndroid Build Coastguard Worker 162*ec779b8eSAndroid Build Coastguard Worker uint32_t mLoopStart; 163*ec779b8eSAndroid Build Coastguard Worker uint32_t mLoopEnd; 164*ec779b8eSAndroid Build Coastguard Worker int32_t mLoopCount; 165*ec779b8eSAndroid Build Coastguard Worker uint32_t mLoopSequence; // a sequence counter to indicate changes to loop 166*ec779b8eSAndroid Build Coastguard Worker uint32_t mPosition; 167*ec779b8eSAndroid Build Coastguard Worker uint32_t mPositionSequence; // a sequence counter to indicate changes to position 168*ec779b8eSAndroid Build Coastguard Worker }; 169*ec779b8eSAndroid Build Coastguard Worker 170*ec779b8eSAndroid Build Coastguard Worker typedef SingleStateQueue<StaticAudioTrackState> StaticAudioTrackSingleStateQueue; 171*ec779b8eSAndroid Build Coastguard Worker 172*ec779b8eSAndroid Build Coastguard Worker struct StaticAudioTrackPosLoop { 173*ec779b8eSAndroid Build Coastguard Worker // Do not define constructors, destructors, or virtual methods as this is part of a 174*ec779b8eSAndroid Build Coastguard Worker // union in shared memory and will not get called properly. 175*ec779b8eSAndroid Build Coastguard Worker 176*ec779b8eSAndroid Build Coastguard Worker // These fields should both be size_t, but since they are located in shared memory we 177*ec779b8eSAndroid Build Coastguard Worker // force to 32-bit. The client and server may have different typedefs for size_t. 178*ec779b8eSAndroid Build Coastguard Worker 179*ec779b8eSAndroid Build Coastguard Worker // This struct information is stored in a single state queue to communicate the 180*ec779b8eSAndroid Build Coastguard Worker // static AudioTrack server state to the client while data is consumed. 181*ec779b8eSAndroid Build Coastguard Worker // It is smaller than StaticAudioTrackState to prevent unnecessary information from 182*ec779b8eSAndroid Build Coastguard Worker // being sent. 183*ec779b8eSAndroid Build Coastguard Worker 184*ec779b8eSAndroid Build Coastguard Worker uint32_t mBufferPosition; 185*ec779b8eSAndroid Build Coastguard Worker int32_t mLoopCount; 186*ec779b8eSAndroid Build Coastguard Worker }; 187*ec779b8eSAndroid Build Coastguard Worker 188*ec779b8eSAndroid Build Coastguard Worker typedef SingleStateQueue<StaticAudioTrackPosLoop> StaticAudioTrackPosLoopQueue; 189*ec779b8eSAndroid Build Coastguard Worker 190*ec779b8eSAndroid Build Coastguard Worker struct AudioTrackSharedStatic { 191*ec779b8eSAndroid Build Coastguard Worker // client requests to the server for loop or position changes. 192*ec779b8eSAndroid Build Coastguard Worker StaticAudioTrackSingleStateQueue::Shared 193*ec779b8eSAndroid Build Coastguard Worker mSingleStateQueue; 194*ec779b8eSAndroid Build Coastguard Worker // position info updated asynchronously by server and read by client, 195*ec779b8eSAndroid Build Coastguard Worker // "for entertainment purposes only" 196*ec779b8eSAndroid Build Coastguard Worker StaticAudioTrackPosLoopQueue::Shared 197*ec779b8eSAndroid Build Coastguard Worker mPosLoopQueue; 198*ec779b8eSAndroid Build Coastguard Worker }; 199*ec779b8eSAndroid Build Coastguard Worker 200*ec779b8eSAndroid Build Coastguard Worker typedef SingleStateQueue<AudioPlaybackRate> PlaybackRateQueue; 201*ec779b8eSAndroid Build Coastguard Worker 202*ec779b8eSAndroid Build Coastguard Worker typedef SingleStateQueue<ExtendedTimestamp> ExtendedTimestampQueue; 203*ec779b8eSAndroid Build Coastguard Worker 204*ec779b8eSAndroid Build Coastguard Worker // ---------------------------------------------------------------------------- 205*ec779b8eSAndroid Build Coastguard Worker 206*ec779b8eSAndroid Build Coastguard Worker // Important: do not add any virtual methods, including ~ 207*ec779b8eSAndroid Build Coastguard Worker struct audio_track_cblk_t 208*ec779b8eSAndroid Build Coastguard Worker { 209*ec779b8eSAndroid Build Coastguard Worker // Since the control block is always located in shared memory, this constructor 210*ec779b8eSAndroid Build Coastguard Worker // is only used for placement new(). It is never used for regular new() or stack. 211*ec779b8eSAndroid Build Coastguard Worker audio_track_cblk_t(); 212*ec779b8eSAndroid Build Coastguard Worker /*virtual*/ ~audio_track_cblk_t() { } 213*ec779b8eSAndroid Build Coastguard Worker 214*ec779b8eSAndroid Build Coastguard Worker friend class Proxy; 215*ec779b8eSAndroid Build Coastguard Worker friend class ClientProxy; 216*ec779b8eSAndroid Build Coastguard Worker friend class AudioTrackClientProxy; 217*ec779b8eSAndroid Build Coastguard Worker friend class AudioRecordClientProxy; 218*ec779b8eSAndroid Build Coastguard Worker friend class ServerProxy; 219*ec779b8eSAndroid Build Coastguard Worker friend class AudioTrackServerProxy; 220*ec779b8eSAndroid Build Coastguard Worker friend class AudioRecordServerProxy; 221*ec779b8eSAndroid Build Coastguard Worker 222*ec779b8eSAndroid Build Coastguard Worker // The data members are grouped so that members accessed frequently and in the same context 223*ec779b8eSAndroid Build Coastguard Worker // are in the same line of data cache. 224*ec779b8eSAndroid Build Coastguard Worker 225*ec779b8eSAndroid Build Coastguard Worker uint32_t mServer; // Number of filled frames consumed by server (mIsOut), 226*ec779b8eSAndroid Build Coastguard Worker // or filled frames provided by server (!mIsOut). 227*ec779b8eSAndroid Build Coastguard Worker // It is updated asynchronously by server without a barrier. 228*ec779b8eSAndroid Build Coastguard Worker // The value should be used 229*ec779b8eSAndroid Build Coastguard Worker // "for entertainment purposes only", 230*ec779b8eSAndroid Build Coastguard Worker // which means don't make important decisions based on it. 231*ec779b8eSAndroid Build Coastguard Worker 232*ec779b8eSAndroid Build Coastguard Worker uint32_t mPad1; // unused 233*ec779b8eSAndroid Build Coastguard Worker 234*ec779b8eSAndroid Build Coastguard Worker volatile int32_t mFutex; // event flag: down (P) by client, 235*ec779b8eSAndroid Build Coastguard Worker // up (V) by server or binderDied() or interrupt() 236*ec779b8eSAndroid Build Coastguard Worker #define CBLK_FUTEX_WAKE 1 // if event flag bit is set, then a deferred wake is pending 237*ec779b8eSAndroid Build Coastguard Worker 238*ec779b8eSAndroid Build Coastguard Worker private: 239*ec779b8eSAndroid Build Coastguard Worker 240*ec779b8eSAndroid Build Coastguard Worker // This field should be a size_t, but since it is located in shared memory we 241*ec779b8eSAndroid Build Coastguard Worker // force to 32-bit. The client and server may have different typedefs for size_t. 242*ec779b8eSAndroid Build Coastguard Worker uint32_t mMinimum; // server wakes up client if available >= mMinimum 243*ec779b8eSAndroid Build Coastguard Worker 244*ec779b8eSAndroid Build Coastguard Worker // Stereo gains for AudioTrack only, not used by AudioRecord. 245*ec779b8eSAndroid Build Coastguard Worker gain_minifloat_packed_t mVolumeLR; 246*ec779b8eSAndroid Build Coastguard Worker 247*ec779b8eSAndroid Build Coastguard Worker uint32_t mSampleRate; // AudioTrack only: client's requested sample rate in Hz 248*ec779b8eSAndroid Build Coastguard Worker // or 0 == default. Write-only client, read-only server. 249*ec779b8eSAndroid Build Coastguard Worker 250*ec779b8eSAndroid Build Coastguard Worker PlaybackRateQueue::Shared mPlaybackRateQueue; 251*ec779b8eSAndroid Build Coastguard Worker 252*ec779b8eSAndroid Build Coastguard Worker // client write-only, server read-only 253*ec779b8eSAndroid Build Coastguard Worker uint16_t mSendLevel; // Fixed point U4.12 so 0x1000 means 1.0 254*ec779b8eSAndroid Build Coastguard Worker 255*ec779b8eSAndroid Build Coastguard Worker uint16_t mPad2 __attribute__((__unused__)); // unused 256*ec779b8eSAndroid Build Coastguard Worker 257*ec779b8eSAndroid Build Coastguard Worker // server write-only, client read 258*ec779b8eSAndroid Build Coastguard Worker ExtendedTimestampQueue::Shared mExtendedTimestampQueue; 259*ec779b8eSAndroid Build Coastguard Worker 260*ec779b8eSAndroid Build Coastguard Worker // This is set by AudioTrack.setBufferSizeInFrames(). 261*ec779b8eSAndroid Build Coastguard Worker // A write will not fill the buffer above this limit. 262*ec779b8eSAndroid Build Coastguard Worker volatile uint32_t mBufferSizeInFrames; // effective size of the buffer 263*ec779b8eSAndroid Build Coastguard Worker volatile uint32_t mStartThresholdInFrames; // min frames in buffer to start streaming 264*ec779b8eSAndroid Build Coastguard Worker 265*ec779b8eSAndroid Build Coastguard Worker public: 266*ec779b8eSAndroid Build Coastguard Worker 267*ec779b8eSAndroid Build Coastguard Worker volatile int32_t mFlags; // combinations of CBLK_* 268*ec779b8eSAndroid Build Coastguard Worker 269*ec779b8eSAndroid Build Coastguard Worker std::atomic<int32_t> mState; // current TrackBase state. 270*ec779b8eSAndroid Build Coastguard Worker 271*ec779b8eSAndroid Build Coastguard Worker public: 272*ec779b8eSAndroid Build Coastguard Worker union { 273*ec779b8eSAndroid Build Coastguard Worker AudioTrackSharedStreaming mStreaming; 274*ec779b8eSAndroid Build Coastguard Worker AudioTrackSharedStatic mStatic; 275*ec779b8eSAndroid Build Coastguard Worker int mAlign[8]; 276*ec779b8eSAndroid Build Coastguard Worker } u; 277*ec779b8eSAndroid Build Coastguard Worker 278*ec779b8eSAndroid Build Coastguard Worker // Cache line boundary (32 bytes) 279*ec779b8eSAndroid Build Coastguard Worker }; 280*ec779b8eSAndroid Build Coastguard Worker 281*ec779b8eSAndroid Build Coastguard Worker // TODO: ensure standard layout. 282*ec779b8eSAndroid Build Coastguard Worker // static_assert(std::is_standard_layout_v<audio_track_cblk_t>); 283*ec779b8eSAndroid Build Coastguard Worker 284*ec779b8eSAndroid Build Coastguard Worker // ---------------------------------------------------------------------------- 285*ec779b8eSAndroid Build Coastguard Worker 286*ec779b8eSAndroid Build Coastguard Worker // Proxy for shared memory control block, to isolate callers from needing to know the details. 287*ec779b8eSAndroid Build Coastguard Worker // There is exactly one ClientProxy and one ServerProxy per shared memory control block. 288*ec779b8eSAndroid Build Coastguard Worker // The proxies are located in normal memory, and are not multi-thread safe within a given side. 289*ec779b8eSAndroid Build Coastguard Worker class Proxy : public RefBase { 290*ec779b8eSAndroid Build Coastguard Worker protected: 291*ec779b8eSAndroid Build Coastguard Worker Proxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize, bool isOut, 292*ec779b8eSAndroid Build Coastguard Worker bool clientInServer); 293*ec779b8eSAndroid Build Coastguard Worker virtual ~Proxy() { } 294*ec779b8eSAndroid Build Coastguard Worker 295*ec779b8eSAndroid Build Coastguard Worker public: 296*ec779b8eSAndroid Build Coastguard Worker struct Buffer { 297*ec779b8eSAndroid Build Coastguard Worker size_t mFrameCount; // number of frames available in this buffer 298*ec779b8eSAndroid Build Coastguard Worker void* mRaw; // pointer to first frame 299*ec779b8eSAndroid Build Coastguard Worker size_t mNonContig; // number of additional non-contiguous frames available 300*ec779b8eSAndroid Build Coastguard Worker }; 301*ec779b8eSAndroid Build Coastguard Worker 302*ec779b8eSAndroid Build Coastguard Worker size_t frameCount() const { return mFrameCount; } 303*ec779b8eSAndroid Build Coastguard Worker uint32_t getStartThresholdInFrames() const; 304*ec779b8eSAndroid Build Coastguard Worker uint32_t setStartThresholdInFrames(uint32_t startThresholdInFrames); 305*ec779b8eSAndroid Build Coastguard Worker 306*ec779b8eSAndroid Build Coastguard Worker protected: 307*ec779b8eSAndroid Build Coastguard Worker // These refer to shared memory, and are virtual addresses with respect to the current process. 308*ec779b8eSAndroid Build Coastguard Worker // They may have different virtual addresses within the other process. 309*ec779b8eSAndroid Build Coastguard Worker audio_track_cblk_t* const mCblk; // the control block 310*ec779b8eSAndroid Build Coastguard Worker void* const mBuffers; // starting address of buffers 311*ec779b8eSAndroid Build Coastguard Worker 312*ec779b8eSAndroid Build Coastguard Worker const size_t mFrameCount; // not necessarily a power of 2 313*ec779b8eSAndroid Build Coastguard Worker const size_t mFrameSize; // in bytes 314*ec779b8eSAndroid Build Coastguard Worker const size_t mFrameCountP2; // mFrameCount rounded to power of 2, streaming mode 315*ec779b8eSAndroid Build Coastguard Worker const bool mIsOut; // true for AudioTrack, false for AudioRecord 316*ec779b8eSAndroid Build Coastguard Worker const bool mClientInServer; // true for OutputTrack, false for AudioTrack & AudioRecord 317*ec779b8eSAndroid Build Coastguard Worker bool mIsShutdown; // latch set to true when shared memory corruption detected 318*ec779b8eSAndroid Build Coastguard Worker size_t mUnreleased; // unreleased frames remaining from most recent obtainBuffer 319*ec779b8eSAndroid Build Coastguard Worker }; 320*ec779b8eSAndroid Build Coastguard Worker 321*ec779b8eSAndroid Build Coastguard Worker // ---------------------------------------------------------------------------- 322*ec779b8eSAndroid Build Coastguard Worker 323*ec779b8eSAndroid Build Coastguard Worker // Proxy seen by AudioTrack client and AudioRecord client 324*ec779b8eSAndroid Build Coastguard Worker class ClientProxy : public Proxy { 325*ec779b8eSAndroid Build Coastguard Worker public: 326*ec779b8eSAndroid Build Coastguard Worker ClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize, 327*ec779b8eSAndroid Build Coastguard Worker bool isOut, bool clientInServer); 328*ec779b8eSAndroid Build Coastguard Worker virtual ~ClientProxy() { } 329*ec779b8eSAndroid Build Coastguard Worker 330*ec779b8eSAndroid Build Coastguard Worker static const struct timespec kForever; 331*ec779b8eSAndroid Build Coastguard Worker static const struct timespec kNonBlocking; 332*ec779b8eSAndroid Build Coastguard Worker 333*ec779b8eSAndroid Build Coastguard Worker // Obtain a buffer with filled frames (reading) or empty frames (writing). 334*ec779b8eSAndroid Build Coastguard Worker // It is permitted to call obtainBuffer() multiple times in succession, without any intervening 335*ec779b8eSAndroid Build Coastguard Worker // calls to releaseBuffer(). In that case, the final obtainBuffer() is the one that effectively 336*ec779b8eSAndroid Build Coastguard Worker // sets or extends the unreleased frame count. 337*ec779b8eSAndroid Build Coastguard Worker // On entry: 338*ec779b8eSAndroid Build Coastguard Worker // buffer->mFrameCount should be initialized to maximum number of desired frames, 339*ec779b8eSAndroid Build Coastguard Worker // which must be > 0. 340*ec779b8eSAndroid Build Coastguard Worker // buffer->mNonContig is unused. 341*ec779b8eSAndroid Build Coastguard Worker // buffer->mRaw is unused. 342*ec779b8eSAndroid Build Coastguard Worker // requested is the requested timeout in local monotonic delta time units: 343*ec779b8eSAndroid Build Coastguard Worker // NULL or &kNonBlocking means non-blocking (zero timeout). 344*ec779b8eSAndroid Build Coastguard Worker // &kForever means block forever (infinite timeout). 345*ec779b8eSAndroid Build Coastguard Worker // Other values mean a specific timeout in local monotonic delta time units. 346*ec779b8eSAndroid Build Coastguard Worker // elapsed is a pointer to a location that will hold the total local monotonic time that 347*ec779b8eSAndroid Build Coastguard Worker // elapsed while blocked, or NULL if not needed. 348*ec779b8eSAndroid Build Coastguard Worker // On exit: 349*ec779b8eSAndroid Build Coastguard Worker // buffer->mFrameCount has the actual number of contiguous available frames, 350*ec779b8eSAndroid Build Coastguard Worker // which is always 0 when the return status != NO_ERROR. 351*ec779b8eSAndroid Build Coastguard Worker // buffer->mNonContig is the number of additional non-contiguous available frames. 352*ec779b8eSAndroid Build Coastguard Worker // buffer->mRaw is a pointer to the first available frame, 353*ec779b8eSAndroid Build Coastguard Worker // or NULL when buffer->mFrameCount == 0. 354*ec779b8eSAndroid Build Coastguard Worker // The return status is one of: 355*ec779b8eSAndroid Build Coastguard Worker // NO_ERROR Success, buffer->mFrameCount > 0. 356*ec779b8eSAndroid Build Coastguard Worker // WOULD_BLOCK Non-blocking mode and no frames are available. 357*ec779b8eSAndroid Build Coastguard Worker // TIMED_OUT Timeout occurred before any frames became available. 358*ec779b8eSAndroid Build Coastguard Worker // This can happen even for infinite timeout, due to a spurious wakeup. 359*ec779b8eSAndroid Build Coastguard Worker // In this case, the caller should investigate and then re-try as appropriate. 360*ec779b8eSAndroid Build Coastguard Worker // DEAD_OBJECT Server has died or invalidated, caller should destroy this proxy and re-create. 361*ec779b8eSAndroid Build Coastguard Worker // -EINTR Call has been interrupted. Look around to see why, and then perhaps try again. 362*ec779b8eSAndroid Build Coastguard Worker // NO_INIT Shared memory is corrupt. 363*ec779b8eSAndroid Build Coastguard Worker // NOT_ENOUGH_DATA Server has disabled the track because of underrun: restart the track 364*ec779b8eSAndroid Build Coastguard Worker // if still in active state. 365*ec779b8eSAndroid Build Coastguard Worker // Assertion failure on entry, if buffer == NULL or buffer->mFrameCount == 0. 366*ec779b8eSAndroid Build Coastguard Worker status_t obtainBuffer(Buffer* buffer, const struct timespec *requested = NULL, 367*ec779b8eSAndroid Build Coastguard Worker struct timespec *elapsed = NULL); 368*ec779b8eSAndroid Build Coastguard Worker 369*ec779b8eSAndroid Build Coastguard Worker // Release (some of) the frames last obtained. 370*ec779b8eSAndroid Build Coastguard Worker // On entry, buffer->mFrameCount should have the number of frames to release, 371*ec779b8eSAndroid Build Coastguard Worker // which must (cumulatively) be <= the number of frames last obtained but not yet released. 372*ec779b8eSAndroid Build Coastguard Worker // buffer->mRaw is ignored, but is normally same pointer returned by last obtainBuffer(). 373*ec779b8eSAndroid Build Coastguard Worker // It is permitted to call releaseBuffer() multiple times to release the frames in chunks. 374*ec779b8eSAndroid Build Coastguard Worker // On exit: 375*ec779b8eSAndroid Build Coastguard Worker // buffer->mFrameCount is zero. 376*ec779b8eSAndroid Build Coastguard Worker // buffer->mRaw is NULL. 377*ec779b8eSAndroid Build Coastguard Worker void releaseBuffer(Buffer* buffer); 378*ec779b8eSAndroid Build Coastguard Worker 379*ec779b8eSAndroid Build Coastguard Worker // Call after detecting server's death 380*ec779b8eSAndroid Build Coastguard Worker void binderDied(); 381*ec779b8eSAndroid Build Coastguard Worker 382*ec779b8eSAndroid Build Coastguard Worker // Call to force an obtainBuffer() to return quickly with -EINTR 383*ec779b8eSAndroid Build Coastguard Worker void interrupt(); 384*ec779b8eSAndroid Build Coastguard Worker 385*ec779b8eSAndroid Build Coastguard Worker Modulo<uint32_t> getPosition() { 386*ec779b8eSAndroid Build Coastguard Worker return mEpoch + mCblk->mServer; 387*ec779b8eSAndroid Build Coastguard Worker } 388*ec779b8eSAndroid Build Coastguard Worker 389*ec779b8eSAndroid Build Coastguard Worker void setEpoch(const Modulo<uint32_t> &epoch) { 390*ec779b8eSAndroid Build Coastguard Worker mEpoch = epoch; 391*ec779b8eSAndroid Build Coastguard Worker } 392*ec779b8eSAndroid Build Coastguard Worker 393*ec779b8eSAndroid Build Coastguard Worker void setMinimum(size_t minimum) { 394*ec779b8eSAndroid Build Coastguard Worker // This can only happen on a 64-bit client 395*ec779b8eSAndroid Build Coastguard Worker if (minimum > UINT32_MAX) { 396*ec779b8eSAndroid Build Coastguard Worker minimum = UINT32_MAX; 397*ec779b8eSAndroid Build Coastguard Worker } 398*ec779b8eSAndroid Build Coastguard Worker mCblk->mMinimum = (uint32_t) minimum; 399*ec779b8eSAndroid Build Coastguard Worker } 400*ec779b8eSAndroid Build Coastguard Worker 401*ec779b8eSAndroid Build Coastguard Worker // Return the number of frames that would need to be obtained and released 402*ec779b8eSAndroid Build Coastguard Worker // in order for the client to be aligned at start of buffer 403*ec779b8eSAndroid Build Coastguard Worker virtual size_t getMisalignment(); 404*ec779b8eSAndroid Build Coastguard Worker 405*ec779b8eSAndroid Build Coastguard Worker Modulo<uint32_t> getEpoch() const { 406*ec779b8eSAndroid Build Coastguard Worker return mEpoch; 407*ec779b8eSAndroid Build Coastguard Worker } 408*ec779b8eSAndroid Build Coastguard Worker 409*ec779b8eSAndroid Build Coastguard Worker int32_t getState() const { return mCblk->mState; } 410*ec779b8eSAndroid Build Coastguard Worker uint32_t getBufferSizeInFrames() const { return mBufferSizeInFrames; } 411*ec779b8eSAndroid Build Coastguard Worker // See documentation for AudioTrack::setBufferSizeInFrames() 412*ec779b8eSAndroid Build Coastguard Worker uint32_t setBufferSizeInFrames(uint32_t requestedSize); 413*ec779b8eSAndroid Build Coastguard Worker 414*ec779b8eSAndroid Build Coastguard Worker status_t getTimestamp(ExtendedTimestamp *timestamp) { 415*ec779b8eSAndroid Build Coastguard Worker if (timestamp == nullptr) { 416*ec779b8eSAndroid Build Coastguard Worker return BAD_VALUE; 417*ec779b8eSAndroid Build Coastguard Worker } 418*ec779b8eSAndroid Build Coastguard Worker (void) mTimestampObserver.poll(mTimestamp); 419*ec779b8eSAndroid Build Coastguard Worker *timestamp = mTimestamp; 420*ec779b8eSAndroid Build Coastguard Worker return OK; 421*ec779b8eSAndroid Build Coastguard Worker } 422*ec779b8eSAndroid Build Coastguard Worker 423*ec779b8eSAndroid Build Coastguard Worker void clearTimestamp() { 424*ec779b8eSAndroid Build Coastguard Worker mTimestamp.clear(); 425*ec779b8eSAndroid Build Coastguard Worker } 426*ec779b8eSAndroid Build Coastguard Worker 427*ec779b8eSAndroid Build Coastguard Worker virtual void stop() { }; // called by client in AudioTrack::stop() 428*ec779b8eSAndroid Build Coastguard Worker 429*ec779b8eSAndroid Build Coastguard Worker private: 430*ec779b8eSAndroid Build Coastguard Worker // This is a copy of mCblk->mBufferSizeInFrames 431*ec779b8eSAndroid Build Coastguard Worker uint32_t mBufferSizeInFrames; // effective size of the buffer 432*ec779b8eSAndroid Build Coastguard Worker 433*ec779b8eSAndroid Build Coastguard Worker Modulo<uint32_t> mEpoch; 434*ec779b8eSAndroid Build Coastguard Worker 435*ec779b8eSAndroid Build Coastguard Worker // The shared buffer contents referred to by the timestamp observer 436*ec779b8eSAndroid Build Coastguard Worker // is initialized when the server proxy created. A local zero timestamp 437*ec779b8eSAndroid Build Coastguard Worker // is initialized by the client constructor. 438*ec779b8eSAndroid Build Coastguard Worker ExtendedTimestampQueue::Observer mTimestampObserver; 439*ec779b8eSAndroid Build Coastguard Worker ExtendedTimestamp mTimestamp; // initialized by constructor 440*ec779b8eSAndroid Build Coastguard Worker }; 441*ec779b8eSAndroid Build Coastguard Worker 442*ec779b8eSAndroid Build Coastguard Worker // ---------------------------------------------------------------------------- 443*ec779b8eSAndroid Build Coastguard Worker 444*ec779b8eSAndroid Build Coastguard Worker // Proxy used by AudioTrack client, which also includes AudioFlinger::PlaybackThread::OutputTrack 445*ec779b8eSAndroid Build Coastguard Worker class AudioTrackClientProxy : public ClientProxy { 446*ec779b8eSAndroid Build Coastguard Worker public: 447*ec779b8eSAndroid Build Coastguard Worker AudioTrackClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, 448*ec779b8eSAndroid Build Coastguard Worker size_t frameSize, bool clientInServer = false) 449*ec779b8eSAndroid Build Coastguard Worker : ClientProxy(cblk, buffers, frameCount, frameSize, true /*isOut*/, 450*ec779b8eSAndroid Build Coastguard Worker clientInServer), 451*ec779b8eSAndroid Build Coastguard Worker mPlaybackRateMutator(&cblk->mPlaybackRateQueue) { 452*ec779b8eSAndroid Build Coastguard Worker } 453*ec779b8eSAndroid Build Coastguard Worker 454*ec779b8eSAndroid Build Coastguard Worker virtual ~AudioTrackClientProxy() { } 455*ec779b8eSAndroid Build Coastguard Worker 456*ec779b8eSAndroid Build Coastguard Worker // No barriers on the following operations, so the ordering of loads/stores 457*ec779b8eSAndroid Build Coastguard Worker // with respect to other parameters is UNPREDICTABLE. That's considered safe. 458*ec779b8eSAndroid Build Coastguard Worker 459*ec779b8eSAndroid Build Coastguard Worker // caller must limit to 0.0 <= sendLevel <= 1.0 460*ec779b8eSAndroid Build Coastguard Worker void setSendLevel(float sendLevel) { 461*ec779b8eSAndroid Build Coastguard Worker mCblk->mSendLevel = uint16_t(sendLevel * 0x1000); 462*ec779b8eSAndroid Build Coastguard Worker } 463*ec779b8eSAndroid Build Coastguard Worker 464*ec779b8eSAndroid Build Coastguard Worker // set stereo gains 465*ec779b8eSAndroid Build Coastguard Worker void setVolumeLR(gain_minifloat_packed_t volumeLR) { 466*ec779b8eSAndroid Build Coastguard Worker mCblk->mVolumeLR = volumeLR; 467*ec779b8eSAndroid Build Coastguard Worker } 468*ec779b8eSAndroid Build Coastguard Worker 469*ec779b8eSAndroid Build Coastguard Worker void setSampleRate(uint32_t sampleRate) { 470*ec779b8eSAndroid Build Coastguard Worker mCblk->mSampleRate = sampleRate; 471*ec779b8eSAndroid Build Coastguard Worker } 472*ec779b8eSAndroid Build Coastguard Worker 473*ec779b8eSAndroid Build Coastguard Worker void setPlaybackRate(const AudioPlaybackRate& playbackRate) { 474*ec779b8eSAndroid Build Coastguard Worker mPlaybackRateMutator.push(playbackRate); 475*ec779b8eSAndroid Build Coastguard Worker } 476*ec779b8eSAndroid Build Coastguard Worker 477*ec779b8eSAndroid Build Coastguard Worker // Sends flush and stop position information from the client to the server, 478*ec779b8eSAndroid Build Coastguard Worker // used by streaming AudioTrack flush() or stop(). 479*ec779b8eSAndroid Build Coastguard Worker void sendStreamingFlushStop(bool flush); 480*ec779b8eSAndroid Build Coastguard Worker 481*ec779b8eSAndroid Build Coastguard Worker virtual void flush(); 482*ec779b8eSAndroid Build Coastguard Worker 483*ec779b8eSAndroid Build Coastguard Worker void stop() override; 484*ec779b8eSAndroid Build Coastguard Worker 485*ec779b8eSAndroid Build Coastguard Worker virtual uint32_t getUnderrunFrames() const { 486*ec779b8eSAndroid Build Coastguard Worker return mCblk->u.mStreaming.mUnderrunFrames; 487*ec779b8eSAndroid Build Coastguard Worker } 488*ec779b8eSAndroid Build Coastguard Worker virtual uint32_t getUnderrunCount() const { 489*ec779b8eSAndroid Build Coastguard Worker return mCblk->u.mStreaming.mUnderrunCount; 490*ec779b8eSAndroid Build Coastguard Worker } 491*ec779b8eSAndroid Build Coastguard Worker 492*ec779b8eSAndroid Build Coastguard Worker bool clearStreamEndDone(); // and return previous value 493*ec779b8eSAndroid Build Coastguard Worker 494*ec779b8eSAndroid Build Coastguard Worker bool getStreamEndDone() const; 495*ec779b8eSAndroid Build Coastguard Worker 496*ec779b8eSAndroid Build Coastguard Worker status_t waitStreamEndDone(const struct timespec *requested); 497*ec779b8eSAndroid Build Coastguard Worker 498*ec779b8eSAndroid Build Coastguard Worker private: 499*ec779b8eSAndroid Build Coastguard Worker PlaybackRateQueue::Mutator mPlaybackRateMutator; 500*ec779b8eSAndroid Build Coastguard Worker }; 501*ec779b8eSAndroid Build Coastguard Worker 502*ec779b8eSAndroid Build Coastguard Worker class StaticAudioTrackClientProxy : public AudioTrackClientProxy { 503*ec779b8eSAndroid Build Coastguard Worker public: 504*ec779b8eSAndroid Build Coastguard Worker StaticAudioTrackClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, 505*ec779b8eSAndroid Build Coastguard Worker size_t frameSize); 506*ec779b8eSAndroid Build Coastguard Worker virtual ~StaticAudioTrackClientProxy() { } 507*ec779b8eSAndroid Build Coastguard Worker 508*ec779b8eSAndroid Build Coastguard Worker virtual void flush(); 509*ec779b8eSAndroid Build Coastguard Worker 510*ec779b8eSAndroid Build Coastguard Worker void stop() override; 511*ec779b8eSAndroid Build Coastguard Worker 512*ec779b8eSAndroid Build Coastguard Worker #define MIN_LOOP 16 // minimum length of each loop iteration in frames 513*ec779b8eSAndroid Build Coastguard Worker 514*ec779b8eSAndroid Build Coastguard Worker // setLoop(), setBufferPosition(), and setBufferPositionAndLoop() set the 515*ec779b8eSAndroid Build Coastguard Worker // static buffer position and looping parameters. These commands are not 516*ec779b8eSAndroid Build Coastguard Worker // synchronous (they do not wait or block); instead they take effect at the 517*ec779b8eSAndroid Build Coastguard Worker // next buffer data read from the server side. However, the client side 518*ec779b8eSAndroid Build Coastguard Worker // getters will read a cached version of the position and loop variables 519*ec779b8eSAndroid Build Coastguard Worker // until the setting takes effect. 520*ec779b8eSAndroid Build Coastguard Worker // 521*ec779b8eSAndroid Build Coastguard Worker // setBufferPositionAndLoop() is equivalent to calling, in order, setLoop() and 522*ec779b8eSAndroid Build Coastguard Worker // setBufferPosition(). 523*ec779b8eSAndroid Build Coastguard Worker // 524*ec779b8eSAndroid Build Coastguard Worker // The functions should not be relied upon to do parameter or state checking. 525*ec779b8eSAndroid Build Coastguard Worker // That is done at the AudioTrack level. 526*ec779b8eSAndroid Build Coastguard Worker 527*ec779b8eSAndroid Build Coastguard Worker void setLoop(size_t loopStart, size_t loopEnd, int loopCount); 528*ec779b8eSAndroid Build Coastguard Worker void setBufferPosition(size_t position); 529*ec779b8eSAndroid Build Coastguard Worker void setBufferPositionAndLoop(size_t position, size_t loopStart, size_t loopEnd, 530*ec779b8eSAndroid Build Coastguard Worker int loopCount); 531*ec779b8eSAndroid Build Coastguard Worker size_t getBufferPosition(); 532*ec779b8eSAndroid Build Coastguard Worker // getBufferPositionAndLoopCount() provides the proper snapshot of 533*ec779b8eSAndroid Build Coastguard Worker // position and loopCount together. 534*ec779b8eSAndroid Build Coastguard Worker void getBufferPositionAndLoopCount(size_t *position, int *loopCount); 535*ec779b8eSAndroid Build Coastguard Worker 536*ec779b8eSAndroid Build Coastguard Worker virtual size_t getMisalignment() { 537*ec779b8eSAndroid Build Coastguard Worker return 0; 538*ec779b8eSAndroid Build Coastguard Worker } 539*ec779b8eSAndroid Build Coastguard Worker 540*ec779b8eSAndroid Build Coastguard Worker virtual uint32_t getUnderrunFrames() const override { 541*ec779b8eSAndroid Build Coastguard Worker return 0; 542*ec779b8eSAndroid Build Coastguard Worker } 543*ec779b8eSAndroid Build Coastguard Worker 544*ec779b8eSAndroid Build Coastguard Worker virtual uint32_t getUnderrunCount() const override { 545*ec779b8eSAndroid Build Coastguard Worker return 0; 546*ec779b8eSAndroid Build Coastguard Worker } 547*ec779b8eSAndroid Build Coastguard Worker 548*ec779b8eSAndroid Build Coastguard Worker private: 549*ec779b8eSAndroid Build Coastguard Worker StaticAudioTrackSingleStateQueue::Mutator mMutator; 550*ec779b8eSAndroid Build Coastguard Worker StaticAudioTrackPosLoopQueue::Observer mPosLoopObserver; 551*ec779b8eSAndroid Build Coastguard Worker StaticAudioTrackState mState; // last communicated state to server 552*ec779b8eSAndroid Build Coastguard Worker StaticAudioTrackPosLoop mPosLoop; // snapshot of position and loop. 553*ec779b8eSAndroid Build Coastguard Worker }; 554*ec779b8eSAndroid Build Coastguard Worker 555*ec779b8eSAndroid Build Coastguard Worker // ---------------------------------------------------------------------------- 556*ec779b8eSAndroid Build Coastguard Worker 557*ec779b8eSAndroid Build Coastguard Worker // Proxy used by AudioRecord client 558*ec779b8eSAndroid Build Coastguard Worker class AudioRecordClientProxy : public ClientProxy { 559*ec779b8eSAndroid Build Coastguard Worker public: 560*ec779b8eSAndroid Build Coastguard Worker AudioRecordClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, 561*ec779b8eSAndroid Build Coastguard Worker size_t frameSize) 562*ec779b8eSAndroid Build Coastguard Worker : ClientProxy(cblk, buffers, frameCount, frameSize, 563*ec779b8eSAndroid Build Coastguard Worker false /*isOut*/, false /*clientInServer*/) { } 564*ec779b8eSAndroid Build Coastguard Worker ~AudioRecordClientProxy() { } 565*ec779b8eSAndroid Build Coastguard Worker 566*ec779b8eSAndroid Build Coastguard Worker // Advances the client read pointer to the server write head pointer 567*ec779b8eSAndroid Build Coastguard Worker // effectively flushing the client read buffer. The effect is 568*ec779b8eSAndroid Build Coastguard Worker // instantaneous. Returns the number of frames flushed. 569*ec779b8eSAndroid Build Coastguard Worker uint32_t flush() { 570*ec779b8eSAndroid Build Coastguard Worker int32_t rear = android_atomic_acquire_load(&mCblk->u.mStreaming.mRear); 571*ec779b8eSAndroid Build Coastguard Worker int32_t front = mCblk->u.mStreaming.mFront; 572*ec779b8eSAndroid Build Coastguard Worker android_atomic_release_store(rear, &mCblk->u.mStreaming.mFront); 573*ec779b8eSAndroid Build Coastguard Worker return (Modulo<int32_t>(rear) - front).unsignedValue(); 574*ec779b8eSAndroid Build Coastguard Worker } 575*ec779b8eSAndroid Build Coastguard Worker }; 576*ec779b8eSAndroid Build Coastguard Worker 577*ec779b8eSAndroid Build Coastguard Worker // ---------------------------------------------------------------------------- 578*ec779b8eSAndroid Build Coastguard Worker 579*ec779b8eSAndroid Build Coastguard Worker // Proxy used by AudioFlinger server 580*ec779b8eSAndroid Build Coastguard Worker class ServerProxy : public Proxy { 581*ec779b8eSAndroid Build Coastguard Worker protected: 582*ec779b8eSAndroid Build Coastguard Worker ServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize, 583*ec779b8eSAndroid Build Coastguard Worker bool isOut, bool clientInServer); 584*ec779b8eSAndroid Build Coastguard Worker public: 585*ec779b8eSAndroid Build Coastguard Worker virtual ~ServerProxy() { } 586*ec779b8eSAndroid Build Coastguard Worker 587*ec779b8eSAndroid Build Coastguard Worker // Obtain a buffer with filled frames (writing) or empty frames (reading). 588*ec779b8eSAndroid Build Coastguard Worker // It is permitted to call obtainBuffer() multiple times in succession, without any intervening 589*ec779b8eSAndroid Build Coastguard Worker // calls to releaseBuffer(). In that case, the final obtainBuffer() is the one that effectively 590*ec779b8eSAndroid Build Coastguard Worker // sets or extends the unreleased frame count. 591*ec779b8eSAndroid Build Coastguard Worker // Always non-blocking. 592*ec779b8eSAndroid Build Coastguard Worker // On entry: 593*ec779b8eSAndroid Build Coastguard Worker // buffer->mFrameCount should be initialized to maximum number of desired frames, 594*ec779b8eSAndroid Build Coastguard Worker // which must be > 0. 595*ec779b8eSAndroid Build Coastguard Worker // buffer->mNonContig is unused. 596*ec779b8eSAndroid Build Coastguard Worker // buffer->mRaw is unused. 597*ec779b8eSAndroid Build Coastguard Worker // ackFlush is true iff being called from Track::start to acknowledge a pending flush. 598*ec779b8eSAndroid Build Coastguard Worker // On exit: 599*ec779b8eSAndroid Build Coastguard Worker // buffer->mFrameCount has the actual number of contiguous available frames, 600*ec779b8eSAndroid Build Coastguard Worker // which is always 0 when the return status != NO_ERROR. 601*ec779b8eSAndroid Build Coastguard Worker // buffer->mNonContig is the number of additional non-contiguous available frames. 602*ec779b8eSAndroid Build Coastguard Worker // buffer->mRaw is a pointer to the first available frame, 603*ec779b8eSAndroid Build Coastguard Worker // or NULL when buffer->mFrameCount == 0. 604*ec779b8eSAndroid Build Coastguard Worker // The return status is one of: 605*ec779b8eSAndroid Build Coastguard Worker // NO_ERROR Success, buffer->mFrameCount > 0. 606*ec779b8eSAndroid Build Coastguard Worker // WOULD_BLOCK No frames are available. 607*ec779b8eSAndroid Build Coastguard Worker // NO_INIT Shared memory is corrupt. 608*ec779b8eSAndroid Build Coastguard Worker virtual status_t obtainBuffer(Buffer* buffer, bool ackFlush = false); 609*ec779b8eSAndroid Build Coastguard Worker 610*ec779b8eSAndroid Build Coastguard Worker // Release (some of) the frames last obtained. 611*ec779b8eSAndroid Build Coastguard Worker // On entry, buffer->mFrameCount should have the number of frames to release, 612*ec779b8eSAndroid Build Coastguard Worker // which must (cumulatively) be <= the number of frames last obtained but not yet released. 613*ec779b8eSAndroid Build Coastguard Worker // It is permitted to call releaseBuffer() multiple times to release the frames in chunks. 614*ec779b8eSAndroid Build Coastguard Worker // buffer->mRaw is ignored, but is normally same pointer returned by last obtainBuffer(). 615*ec779b8eSAndroid Build Coastguard Worker // On exit: 616*ec779b8eSAndroid Build Coastguard Worker // buffer->mFrameCount is zero. 617*ec779b8eSAndroid Build Coastguard Worker // buffer->mRaw is NULL. 618*ec779b8eSAndroid Build Coastguard Worker virtual void releaseBuffer(Buffer* buffer); 619*ec779b8eSAndroid Build Coastguard Worker 620*ec779b8eSAndroid Build Coastguard Worker // Return the total number of frames that AudioFlinger has obtained and released 621*ec779b8eSAndroid Build Coastguard Worker virtual int64_t framesReleased() const { return mReleased; } 622*ec779b8eSAndroid Build Coastguard Worker 623*ec779b8eSAndroid Build Coastguard Worker // Expose timestamp to client proxy. Should only be called by a single thread. 624*ec779b8eSAndroid Build Coastguard Worker virtual void setTimestamp(const ExtendedTimestamp ×tamp) { 625*ec779b8eSAndroid Build Coastguard Worker mTimestampMutator.push(timestamp); 626*ec779b8eSAndroid Build Coastguard Worker } 627*ec779b8eSAndroid Build Coastguard Worker 628*ec779b8eSAndroid Build Coastguard Worker virtual ExtendedTimestamp getTimestamp() const { 629*ec779b8eSAndroid Build Coastguard Worker return mTimestampMutator.last(); 630*ec779b8eSAndroid Build Coastguard Worker } 631*ec779b8eSAndroid Build Coastguard Worker 632*ec779b8eSAndroid Build Coastguard Worker // Flushes the shared ring buffer if the client had requested it using mStreaming.mFlush. 633*ec779b8eSAndroid Build Coastguard Worker // If flush occurs then: 634*ec779b8eSAndroid Build Coastguard Worker // cblk->u.mStreaming.mFront, ServerProxy::mFlush and ServerProxy::mFlushed will be modified 635*ec779b8eSAndroid Build Coastguard Worker // client will be notified via Futex 636*ec779b8eSAndroid Build Coastguard Worker virtual void flushBufferIfNeeded(); 637*ec779b8eSAndroid Build Coastguard Worker 638*ec779b8eSAndroid Build Coastguard Worker // Returns the rear position of the AudioTrack shared ring buffer, limited by 639*ec779b8eSAndroid Build Coastguard Worker // the stop frame position level. 640*ec779b8eSAndroid Build Coastguard Worker virtual int32_t getRear() const = 0; 641*ec779b8eSAndroid Build Coastguard Worker 642*ec779b8eSAndroid Build Coastguard Worker // Total count of the number of flushed frames since creation (never reset). 643*ec779b8eSAndroid Build Coastguard Worker virtual int64_t framesFlushed() const { return mFlushed; } 644*ec779b8eSAndroid Build Coastguard Worker 645*ec779b8eSAndroid Build Coastguard Worker // Safe frames ready query with no side effects. 646*ec779b8eSAndroid Build Coastguard Worker virtual size_t framesReadySafe() const = 0; 647*ec779b8eSAndroid Build Coastguard Worker 648*ec779b8eSAndroid Build Coastguard Worker // Get dynamic buffer size from the shared control block. 649*ec779b8eSAndroid Build Coastguard Worker uint32_t getBufferSizeInFrames() const { 650*ec779b8eSAndroid Build Coastguard Worker return android_atomic_acquire_load((int32_t *)&mCblk->mBufferSizeInFrames); 651*ec779b8eSAndroid Build Coastguard Worker } 652*ec779b8eSAndroid Build Coastguard Worker 653*ec779b8eSAndroid Build Coastguard Worker protected: 654*ec779b8eSAndroid Build Coastguard Worker size_t mAvailToClient; // estimated frames available to client prior to releaseBuffer() 655*ec779b8eSAndroid Build Coastguard Worker int32_t mFlush; // our copy of cblk->u.mStreaming.mFlush, for streaming output only 656*ec779b8eSAndroid Build Coastguard Worker int64_t mReleased; // our copy of cblk->mServer, at 64 bit resolution 657*ec779b8eSAndroid Build Coastguard Worker int64_t mFlushed; // flushed frames to account for client-server discrepancy 658*ec779b8eSAndroid Build Coastguard Worker ExtendedTimestampQueue::Mutator mTimestampMutator; 659*ec779b8eSAndroid Build Coastguard Worker }; 660*ec779b8eSAndroid Build Coastguard Worker 661*ec779b8eSAndroid Build Coastguard Worker // Proxy used by AudioFlinger for servicing AudioTrack 662*ec779b8eSAndroid Build Coastguard Worker class AudioTrackServerProxy : public ServerProxy { 663*ec779b8eSAndroid Build Coastguard Worker public: 664*ec779b8eSAndroid Build Coastguard Worker AudioTrackServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, 665*ec779b8eSAndroid Build Coastguard Worker size_t frameSize, bool clientInServer, uint32_t sampleRate) 666*ec779b8eSAndroid Build Coastguard Worker : ServerProxy(cblk, buffers, frameCount, frameSize, true /*isOut*/, clientInServer), 667*ec779b8eSAndroid Build Coastguard Worker mPlaybackRateObserver(&cblk->mPlaybackRateQueue), 668*ec779b8eSAndroid Build Coastguard Worker mUnderrunCount(0), mUnderrunning(false), mDrained(true) { 669*ec779b8eSAndroid Build Coastguard Worker mCblk->mSampleRate = sampleRate; 670*ec779b8eSAndroid Build Coastguard Worker mPlaybackRate = AUDIO_PLAYBACK_RATE_DEFAULT; 671*ec779b8eSAndroid Build Coastguard Worker } 672*ec779b8eSAndroid Build Coastguard Worker protected: 673*ec779b8eSAndroid Build Coastguard Worker virtual ~AudioTrackServerProxy() { } 674*ec779b8eSAndroid Build Coastguard Worker 675*ec779b8eSAndroid Build Coastguard Worker public: 676*ec779b8eSAndroid Build Coastguard Worker // return value of these methods must be validated by the caller 677*ec779b8eSAndroid Build Coastguard Worker uint32_t getSampleRate() const { return mCblk->mSampleRate; } 678*ec779b8eSAndroid Build Coastguard Worker uint16_t getSendLevel_U4_12() const { return mCblk->mSendLevel; } 679*ec779b8eSAndroid Build Coastguard Worker gain_minifloat_packed_t getVolumeLR() const { return mCblk->mVolumeLR; } 680*ec779b8eSAndroid Build Coastguard Worker 681*ec779b8eSAndroid Build Coastguard Worker // estimated total number of filled frames available to server to read, 682*ec779b8eSAndroid Build Coastguard Worker // which may include non-contiguous frames 683*ec779b8eSAndroid Build Coastguard Worker virtual size_t framesReady(); 684*ec779b8eSAndroid Build Coastguard Worker 685*ec779b8eSAndroid Build Coastguard Worker size_t framesReadySafe() const override; // frames available to read by server. 686*ec779b8eSAndroid Build Coastguard Worker 687*ec779b8eSAndroid Build Coastguard Worker // Currently AudioFlinger will call framesReady() for a fast track from two threads: 688*ec779b8eSAndroid Build Coastguard Worker // FastMixer thread, and normal mixer thread. This is dangerous, as the proxy is intended 689*ec779b8eSAndroid Build Coastguard Worker // to be called from at most one thread of server, and one thread of client. 690*ec779b8eSAndroid Build Coastguard Worker // As a temporary workaround, this method informs the proxy implementation that it 691*ec779b8eSAndroid Build Coastguard Worker // should avoid doing a state queue poll from within framesReady(). 692*ec779b8eSAndroid Build Coastguard Worker // FIXME Change AudioFlinger to not call framesReady() from normal mixer thread. 693*ec779b8eSAndroid Build Coastguard Worker virtual void framesReadyIsCalledByMultipleThreads() { } 694*ec779b8eSAndroid Build Coastguard Worker 695*ec779b8eSAndroid Build Coastguard Worker bool setStreamEndDone(); // and return previous value 696*ec779b8eSAndroid Build Coastguard Worker 697*ec779b8eSAndroid Build Coastguard Worker // Add to the tally of underrun frames, and inform client of underrun 698*ec779b8eSAndroid Build Coastguard Worker virtual void tallyUnderrunFrames(uint32_t frameCount); 699*ec779b8eSAndroid Build Coastguard Worker 700*ec779b8eSAndroid Build Coastguard Worker // Return the total number of frames which AudioFlinger desired but were unavailable, 701*ec779b8eSAndroid Build Coastguard Worker // and thus which resulted in an underrun. 702*ec779b8eSAndroid Build Coastguard Worker virtual uint32_t getUnderrunFrames() const { return mCblk->u.mStreaming.mUnderrunFrames; } 703*ec779b8eSAndroid Build Coastguard Worker 704*ec779b8eSAndroid Build Coastguard Worker virtual uint32_t getUnderrunCount() const { return mCblk->u.mStreaming.mUnderrunCount; } 705*ec779b8eSAndroid Build Coastguard Worker 706*ec779b8eSAndroid Build Coastguard Worker // Return the playback speed and pitch read atomically. Not multi-thread safe on server side. 707*ec779b8eSAndroid Build Coastguard Worker AudioPlaybackRate getPlaybackRate(); 708*ec779b8eSAndroid Build Coastguard Worker 709*ec779b8eSAndroid Build Coastguard Worker // Set the internal drain state of the track buffer from the timestamp received. 710*ec779b8eSAndroid Build Coastguard Worker virtual void setDrained(bool drained) { 711*ec779b8eSAndroid Build Coastguard Worker mDrained.store(drained); 712*ec779b8eSAndroid Build Coastguard Worker } 713*ec779b8eSAndroid Build Coastguard Worker 714*ec779b8eSAndroid Build Coastguard Worker // Check if the internal drain state of the track buffer. 715*ec779b8eSAndroid Build Coastguard Worker // This is not a guarantee, but advisory for determining whether the track is 716*ec779b8eSAndroid Build Coastguard Worker // fully played out. 717*ec779b8eSAndroid Build Coastguard Worker virtual bool isDrained() const { 718*ec779b8eSAndroid Build Coastguard Worker return mDrained.load(); 719*ec779b8eSAndroid Build Coastguard Worker } 720*ec779b8eSAndroid Build Coastguard Worker 721*ec779b8eSAndroid Build Coastguard Worker int32_t getRear() const override; 722*ec779b8eSAndroid Build Coastguard Worker 723*ec779b8eSAndroid Build Coastguard Worker // Called on server side track start(). 724*ec779b8eSAndroid Build Coastguard Worker virtual void start(); 725*ec779b8eSAndroid Build Coastguard Worker 726*ec779b8eSAndroid Build Coastguard Worker private: 727*ec779b8eSAndroid Build Coastguard Worker AudioPlaybackRate mPlaybackRate; // last observed playback rate 728*ec779b8eSAndroid Build Coastguard Worker PlaybackRateQueue::Observer mPlaybackRateObserver; 729*ec779b8eSAndroid Build Coastguard Worker 730*ec779b8eSAndroid Build Coastguard Worker // Last client stop-at position when start() was called. Used for streaming AudioTracks. 731*ec779b8eSAndroid Build Coastguard Worker std::atomic<int32_t> mStopLast{0}; 732*ec779b8eSAndroid Build Coastguard Worker 733*ec779b8eSAndroid Build Coastguard Worker // The server keeps a copy here where it is safe from the client. 734*ec779b8eSAndroid Build Coastguard Worker uint32_t mUnderrunCount; // echoed to mCblk 735*ec779b8eSAndroid Build Coastguard Worker bool mUnderrunning; // used to detect edge of underrun 736*ec779b8eSAndroid Build Coastguard Worker 737*ec779b8eSAndroid Build Coastguard Worker std::atomic<bool> mDrained; // is the track buffer drained 738*ec779b8eSAndroid Build Coastguard Worker }; 739*ec779b8eSAndroid Build Coastguard Worker 740*ec779b8eSAndroid Build Coastguard Worker class StaticAudioTrackServerProxy : public AudioTrackServerProxy { 741*ec779b8eSAndroid Build Coastguard Worker public: 742*ec779b8eSAndroid Build Coastguard Worker StaticAudioTrackServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, 743*ec779b8eSAndroid Build Coastguard Worker size_t frameSize, uint32_t sampleRate); 744*ec779b8eSAndroid Build Coastguard Worker protected: 745*ec779b8eSAndroid Build Coastguard Worker virtual ~StaticAudioTrackServerProxy() { } 746*ec779b8eSAndroid Build Coastguard Worker 747*ec779b8eSAndroid Build Coastguard Worker public: 748*ec779b8eSAndroid Build Coastguard Worker virtual size_t framesReady(); 749*ec779b8eSAndroid Build Coastguard Worker virtual size_t framesReadySafe() const override; 750*ec779b8eSAndroid Build Coastguard Worker virtual void framesReadyIsCalledByMultipleThreads(); 751*ec779b8eSAndroid Build Coastguard Worker virtual status_t obtainBuffer(Buffer* buffer, bool ackFlush); 752*ec779b8eSAndroid Build Coastguard Worker virtual void releaseBuffer(Buffer* buffer); 753*ec779b8eSAndroid Build Coastguard Worker virtual void tallyUnderrunFrames(uint32_t frameCount); 754*ec779b8eSAndroid Build Coastguard Worker virtual uint32_t getUnderrunFrames() const { return 0; } 755*ec779b8eSAndroid Build Coastguard Worker 756*ec779b8eSAndroid Build Coastguard Worker int32_t getRear() const override; 757*ec779b8eSAndroid Build Coastguard Worker 758*ec779b8eSAndroid Build Coastguard Worker void start() override { } // ignore for static tracks 759*ec779b8eSAndroid Build Coastguard Worker 760*ec779b8eSAndroid Build Coastguard Worker private: 761*ec779b8eSAndroid Build Coastguard Worker status_t updateStateWithLoop(StaticAudioTrackState *localState, 762*ec779b8eSAndroid Build Coastguard Worker const StaticAudioTrackState &update) const; 763*ec779b8eSAndroid Build Coastguard Worker status_t updateStateWithPosition(StaticAudioTrackState *localState, 764*ec779b8eSAndroid Build Coastguard Worker const StaticAudioTrackState &update) const; 765*ec779b8eSAndroid Build Coastguard Worker ssize_t pollPosition(); // poll for state queue update, and return current position 766*ec779b8eSAndroid Build Coastguard Worker StaticAudioTrackSingleStateQueue::Observer mObserver; 767*ec779b8eSAndroid Build Coastguard Worker StaticAudioTrackPosLoopQueue::Mutator mPosLoopMutator; 768*ec779b8eSAndroid Build Coastguard Worker size_t mFramesReadySafe; // Assuming size_t read/writes are atomic on 32 / 64 bit 769*ec779b8eSAndroid Build Coastguard Worker // processors, this is a thread-safe version of 770*ec779b8eSAndroid Build Coastguard Worker // mFramesReady. 771*ec779b8eSAndroid Build Coastguard Worker int64_t mFramesReady; // The number of frames ready in the static buffer 772*ec779b8eSAndroid Build Coastguard Worker // including loops. This is 64 bits since loop mode 773*ec779b8eSAndroid Build Coastguard Worker // can cause a track to appear to have a large number 774*ec779b8eSAndroid Build Coastguard Worker // of frames. INT64_MAX means an infinite loop. 775*ec779b8eSAndroid Build Coastguard Worker bool mFramesReadyIsCalledByMultipleThreads; 776*ec779b8eSAndroid Build Coastguard Worker StaticAudioTrackState mState; // Server side state. Any updates from client must be 777*ec779b8eSAndroid Build Coastguard Worker // passed by the mObserver SingleStateQueue. 778*ec779b8eSAndroid Build Coastguard Worker }; 779*ec779b8eSAndroid Build Coastguard Worker 780*ec779b8eSAndroid Build Coastguard Worker // Proxy used by AudioFlinger for servicing AudioRecord 781*ec779b8eSAndroid Build Coastguard Worker class AudioRecordServerProxy : public ServerProxy { 782*ec779b8eSAndroid Build Coastguard Worker public: 783*ec779b8eSAndroid Build Coastguard Worker AudioRecordServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, 784*ec779b8eSAndroid Build Coastguard Worker size_t frameSize, bool clientInServer) 785*ec779b8eSAndroid Build Coastguard Worker : ServerProxy(cblk, buffers, frameCount, frameSize, false /*isOut*/, clientInServer) { } 786*ec779b8eSAndroid Build Coastguard Worker 787*ec779b8eSAndroid Build Coastguard Worker int32_t getRear() const override { 788*ec779b8eSAndroid Build Coastguard Worker return mCblk->u.mStreaming.mRear; // For completeness only; mRear written by server. 789*ec779b8eSAndroid Build Coastguard Worker } 790*ec779b8eSAndroid Build Coastguard Worker 791*ec779b8eSAndroid Build Coastguard Worker size_t framesReadySafe() const override; // frames available to read by client. 792*ec779b8eSAndroid Build Coastguard Worker 793*ec779b8eSAndroid Build Coastguard Worker protected: 794*ec779b8eSAndroid Build Coastguard Worker virtual ~AudioRecordServerProxy() { } 795*ec779b8eSAndroid Build Coastguard Worker }; 796*ec779b8eSAndroid Build Coastguard Worker 797*ec779b8eSAndroid Build Coastguard Worker // ---------------------------------------------------------------------------- 798*ec779b8eSAndroid Build Coastguard Worker 799*ec779b8eSAndroid Build Coastguard Worker }; // namespace android 800*ec779b8eSAndroid Build Coastguard Worker 801*ec779b8eSAndroid Build Coastguard Worker #endif // ANDROID_AUDIO_TRACK_SHARED_H 802