xref: /aosp_15_r20/frameworks/av/include/private/media/AudioTrackShared.h (revision ec779b8e0859a360c3d303172224686826e6e0e1)
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 &timestamp) {
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