1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ANDROID_AUDIO_TRACK_SHARED_H 18 #define ANDROID_AUDIO_TRACK_SHARED_H 19 20 #include <stdint.h> 21 #include <sys/types.h> 22 23 #include <utils/threads.h> 24 #include <utils/Log.h> 25 26 namespace android { 27 28 // ---------------------------------------------------------------------------- 29 30 // Maximum cumulated timeout milliseconds before restarting audioflinger thread 31 #define MAX_STARTUP_TIMEOUT_MS 3000 // Longer timeout period at startup to cope with A2DP 32 // init time 33 #define MAX_RUN_TIMEOUT_MS 1000 34 #define WAIT_PERIOD_MS 10 35 36 #define CBLK_UNDERRUN 0x01 // set: underrun (out) or overrrun (in), clear: no underrun or overrun 37 #define CBLK_FORCEREADY 0x02 // set: track is considered ready immediately by AudioFlinger, 38 // clear: track is ready when buffer full 39 #define CBLK_INVALID 0x04 // track buffer invalidated by AudioFlinger, need to re-create 40 #define CBLK_DISABLED 0x08 // track disabled by AudioFlinger due to underrun, need to re-start 41 42 struct AudioTrackSharedStreaming { 43 // similar to NBAIO MonoPipe 44 volatile int32_t mFront; 45 volatile int32_t mRear; 46 }; 47 48 // future 49 struct AudioTrackSharedStatic { 50 int mReserved; 51 }; 52 53 // ---------------------------------------------------------------------------- 54 55 // Important: do not add any virtual methods, including ~ 56 struct audio_track_cblk_t 57 { 58 friend class Proxy; 59 friend class AudioTrackClientProxy; 60 friend class AudioRecordClientProxy; 61 friend class ServerProxy; 62 63 // The data members are grouped so that members accessed frequently and in the same context 64 // are in the same line of data cache. 65 Mutex lock; // sizeof(int) 66 Condition cv; // sizeof(int) 67 68 // next 4 are offsets within "buffers" 69 volatile uint32_t user; 70 volatile uint32_t server; 71 uint32_t userBase; 72 uint32_t serverBase; 73 74 int mPad1; // unused, but preserves cache line alignment 75 76 size_t frameCount_; // used during creation to pass actual track buffer size 77 // from AudioFlinger to client, and not referenced again 78 // FIXME remove here and replace by createTrack() in/out parameter 79 // renamed to "_" to detect incorrect use 80 81 // Cache line boundary (32 bytes) 82 83 uint32_t loopStart; 84 uint32_t loopEnd; // read-only for server, read/write for client 85 int loopCount; // read/write for client 86 87 // Channel volumes are fixed point U4.12, so 0x1000 means 1.0. 88 // Left channel is in [0:15], right channel is in [16:31]. 89 // Always read and write the combined pair atomically. 90 // For AudioTrack only, not used by AudioRecord. 91 private: 92 uint32_t mVolumeLR; 93 94 uint32_t mSampleRate; // AudioTrack only: client's requested sample rate in Hz 95 // or 0 == default. Write-only client, read-only server. 96 97 uint8_t mPad2; // unused 98 99 public: 100 // read-only for client, server writes once at initialization and is then read-only 101 uint8_t mName; // normal tracks: track name, fast tracks: track index 102 103 // used by client only 104 uint16_t bufferTimeoutMs; // Maximum cumulated timeout before restarting 105 // audioflinger 106 107 uint16_t waitTimeMs; // Cumulated wait time, used by client only 108 private: 109 // client write-only, server read-only 110 uint16_t mSendLevel; // Fixed point U4.12 so 0x1000 means 1.0 111 public: 112 volatile int32_t flags; 113 114 // Cache line boundary (32 bytes) 115 116 #if 0 117 union { 118 AudioTrackSharedStreaming mStreaming; 119 AudioTrackSharedStatic mStatic; 120 int mAlign[8]; 121 } u; 122 123 // Cache line boundary (32 bytes) 124 #endif 125 126 // Since the control block is always located in shared memory, this constructor 127 // is only used for placement new(). It is never used for regular new() or stack. 128 audio_track_cblk_t(); 129 130 private: 131 // if there is a shared buffer, "buffers" is the value of pointer() for the shared 132 // buffer, otherwise "buffers" points immediately after the control block 133 void* buffer(void *buffers, uint32_t frameSize, size_t offset) const; 134 135 bool tryLock(); 136 137 // isOut == true means AudioTrack, isOut == false means AudioRecord 138 bool stepServer(size_t stepCount, size_t frameCount, bool isOut); 139 uint32_t stepUser(size_t stepCount, size_t frameCount, bool isOut); 140 uint32_t framesAvailable(size_t frameCount, bool isOut); 141 uint32_t framesAvailable_l(size_t frameCount, bool isOut); 142 uint32_t framesReady(bool isOut); 143 }; 144 145 // ---------------------------------------------------------------------------- 146 147 // Proxy for shared memory control block, to isolate callers from needing to know the details. 148 // There is exactly one ClientProxy and one ServerProxy per shared memory control block. 149 // The proxies are located in normal memory, and are not multi-thread safe within a given side. 150 class Proxy { 151 protected: 152 Proxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize) 153 : mCblk(cblk), mBuffers(buffers), mFrameCount(frameCount), mFrameSize(frameSize) { } 154 virtual ~Proxy() { } 155 156 public: 157 void* buffer(size_t offset) const { 158 return mCblk->buffer(mBuffers, mFrameSize, offset); 159 } 160 161 protected: 162 // These refer to shared memory, and are virtual addresses with respect to the current process. 163 // They may have different virtual addresses within the other process. 164 audio_track_cblk_t* const mCblk; // the control block 165 void* const mBuffers; // starting address of buffers 166 167 const size_t mFrameCount; // not necessarily a power of 2 168 const size_t mFrameSize; // in bytes 169 #if 0 170 const size_t mFrameCountP2; // mFrameCount rounded to power of 2, streaming mode 171 #endif 172 173 }; 174 175 // ---------------------------------------------------------------------------- 176 177 // Proxy seen by AudioTrack client and AudioRecord client 178 class ClientProxy : public Proxy { 179 protected: 180 ClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize) 181 : Proxy(cblk, buffers, frameCount, frameSize) { } 182 virtual ~ClientProxy() { } 183 }; 184 185 // ---------------------------------------------------------------------------- 186 187 // Proxy used by AudioTrack client, which also includes AudioFlinger::PlaybackThread::OutputTrack 188 class AudioTrackClientProxy : public ClientProxy { 189 public: 190 AudioTrackClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize) 191 : ClientProxy(cblk, buffers, frameCount, frameSize) { } 192 virtual ~AudioTrackClientProxy() { } 193 194 // No barriers on the following operations, so the ordering of loads/stores 195 // with respect to other parameters is UNPREDICTABLE. That's considered safe. 196 197 // caller must limit to 0.0 <= sendLevel <= 1.0 198 void setSendLevel(float sendLevel) { 199 mCblk->mSendLevel = uint16_t(sendLevel * 0x1000); 200 } 201 202 // caller must limit to 0 <= volumeLR <= 0x10001000 203 void setVolumeLR(uint32_t volumeLR) { 204 mCblk->mVolumeLR = volumeLR; 205 } 206 207 void setSampleRate(uint32_t sampleRate) { 208 mCblk->mSampleRate = sampleRate; 209 } 210 211 // called by: 212 // PlaybackThread::OutputTrack::write 213 // AudioTrack::createTrack_l 214 // AudioTrack::releaseBuffer 215 // AudioTrack::reload 216 // AudioTrack::restoreTrack_l (2 places) 217 size_t stepUser(size_t stepCount) { 218 return mCblk->stepUser(stepCount, mFrameCount, true /*isOut*/); 219 } 220 221 // called by AudioTrack::obtainBuffer and AudioTrack::processBuffer 222 size_t framesAvailable() { 223 return mCblk->framesAvailable(mFrameCount, true /*isOut*/); 224 } 225 226 // called by AudioTrack::obtainBuffer and PlaybackThread::OutputTrack::obtainBuffer 227 // FIXME remove this API since it assumes a lock that should be invisible to caller 228 size_t framesAvailable_l() { 229 return mCblk->framesAvailable_l(mFrameCount, true /*isOut*/); 230 } 231 232 }; 233 234 // ---------------------------------------------------------------------------- 235 236 // Proxy used by AudioRecord client 237 class AudioRecordClientProxy : public ClientProxy { 238 public: 239 AudioRecordClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize) 240 : ClientProxy(cblk, buffers, frameCount, frameSize) { } 241 ~AudioRecordClientProxy() { } 242 243 // called by AudioRecord::releaseBuffer 244 size_t stepUser(size_t stepCount) { 245 return mCblk->stepUser(stepCount, mFrameCount, false /*isOut*/); 246 } 247 248 // called by AudioRecord::processBuffer 249 size_t framesAvailable() { 250 return mCblk->framesAvailable(mFrameCount, false /*isOut*/); 251 } 252 253 // called by AudioRecord::obtainBuffer 254 size_t framesReady() { 255 return mCblk->framesReady(false /*isOut*/); 256 } 257 258 }; 259 260 // ---------------------------------------------------------------------------- 261 262 // Proxy used by AudioFlinger server 263 class ServerProxy : public Proxy { 264 public: 265 ServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize, bool isOut) 266 : Proxy(cblk, buffers, frameCount, frameSize), mIsOut(isOut) { } 267 virtual ~ServerProxy() { } 268 269 // for AudioTrack and AudioRecord 270 bool step(size_t stepCount) { return mCblk->stepServer(stepCount, mFrameCount, mIsOut); } 271 272 // return value of these methods must be validated by the caller 273 uint32_t getSampleRate() const { return mCblk->mSampleRate; } 274 uint16_t getSendLevel_U4_12() const { return mCblk->mSendLevel; } 275 uint32_t getVolumeLR() const { return mCblk->mVolumeLR; } 276 277 // for AudioTrack only 278 size_t framesReady() { 279 ALOG_ASSERT(mIsOut); 280 return mCblk->framesReady(true); 281 } 282 283 // for AudioRecord only, called by RecordThread::RecordTrack::getNextBuffer 284 // FIXME remove this API since it assumes a lock that should be invisible to caller 285 size_t framesAvailableIn_l() { 286 ALOG_ASSERT(!mIsOut); 287 return mCblk->framesAvailable_l(mFrameCount, false); 288 } 289 290 private: 291 const bool mIsOut; // true for AudioTrack, false for AudioRecord 292 293 }; 294 295 // ---------------------------------------------------------------------------- 296 297 }; // namespace android 298 299 #endif // ANDROID_AUDIO_TRACK_SHARED_H 300