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