| Eric Laurent | ca7cc82 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1 | /* | 
 | 2 | ** | 
 | 3 | ** Copyright 2012, The Android Open Source Project | 
 | 4 | ** | 
 | 5 | ** Licensed under the Apache License, Version 2.0 (the "License"); | 
 | 6 | ** you may not use this file except in compliance with the License. | 
 | 7 | ** You may obtain a copy of the License at | 
 | 8 | ** | 
 | 9 | **     http://www.apache.org/licenses/LICENSE-2.0 | 
 | 10 | ** | 
 | 11 | ** Unless required by applicable law or agreed to in writing, software | 
 | 12 | ** distributed under the License is distributed on an "AS IS" BASIS, | 
 | 13 | ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | 14 | ** See the License for the specific language governing permissions and | 
 | 15 | ** limitations under the License. | 
 | 16 | */ | 
 | 17 |  | 
 | 18 |  | 
 | 19 | #define LOG_TAG "AudioFlinger" | 
 | 20 | //#define LOG_NDEBUG 0 | 
 | 21 |  | 
 | 22 | #include <math.h> | 
 | 23 | #include <cutils/compiler.h> | 
 | 24 | #include <utils/Log.h> | 
 | 25 |  | 
 | 26 | #include <private/media/AudioTrackShared.h> | 
 | 27 |  | 
 | 28 | #include <common_time/cc_helper.h> | 
 | 29 | #include <common_time/local_clock.h> | 
 | 30 |  | 
 | 31 | #include "AudioMixer.h" | 
 | 32 | #include "AudioFlinger.h" | 
 | 33 | #include "ServiceUtilities.h" | 
 | 34 |  | 
 | 35 | // ---------------------------------------------------------------------------- | 
 | 36 |  | 
 | 37 | // Note: the following macro is used for extremely verbose logging message.  In | 
 | 38 | // order to run with ALOG_ASSERT turned on, we need to have LOG_NDEBUG set to | 
 | 39 | // 0; but one side effect of this is to turn all LOGV's as well.  Some messages | 
 | 40 | // are so verbose that we want to suppress them even when we have ALOG_ASSERT | 
 | 41 | // turned on.  Do not uncomment the #def below unless you really know what you | 
 | 42 | // are doing and want to see all of the extremely verbose messages. | 
 | 43 | //#define VERY_VERY_VERBOSE_LOGGING | 
 | 44 | #ifdef VERY_VERY_VERBOSE_LOGGING | 
 | 45 | #define ALOGVV ALOGV | 
 | 46 | #else | 
 | 47 | #define ALOGVV(a...) do { } while(0) | 
 | 48 | #endif | 
 | 49 |  | 
 | 50 | namespace android { | 
 | 51 |  | 
 | 52 | // ---------------------------------------------------------------------------- | 
 | 53 | //      TrackBase | 
 | 54 | // ---------------------------------------------------------------------------- | 
 | 55 |  | 
 | 56 | // TrackBase constructor must be called with AudioFlinger::mLock held | 
 | 57 | AudioFlinger::ThreadBase::TrackBase::TrackBase( | 
 | 58 |             ThreadBase *thread, | 
 | 59 |             const sp<Client>& client, | 
 | 60 |             uint32_t sampleRate, | 
 | 61 |             audio_format_t format, | 
 | 62 |             audio_channel_mask_t channelMask, | 
 | 63 |             size_t frameCount, | 
 | 64 |             const sp<IMemory>& sharedBuffer, | 
 | 65 |             int sessionId) | 
 | 66 |     :   RefBase(), | 
 | 67 |         mThread(thread), | 
 | 68 |         mClient(client), | 
 | 69 |         mCblk(NULL), | 
 | 70 |         // mBuffer | 
 | 71 |         // mBufferEnd | 
 | 72 |         mStepCount(0), | 
 | 73 |         mState(IDLE), | 
 | 74 |         mSampleRate(sampleRate), | 
 | 75 |         mFormat(format), | 
 | 76 |         mChannelMask(channelMask), | 
 | 77 |         mChannelCount(popcount(channelMask)), | 
 | 78 |         mFrameSize(audio_is_linear_pcm(format) ? | 
 | 79 |                 mChannelCount * audio_bytes_per_sample(format) : sizeof(int8_t)), | 
 | 80 |         mFrameCount(frameCount), | 
 | 81 |         mStepServerFailed(false), | 
 | 82 |         mSessionId(sessionId) | 
 | 83 | { | 
 | 84 |     // client == 0 implies sharedBuffer == 0 | 
 | 85 |     ALOG_ASSERT(!(client == 0 && sharedBuffer != 0)); | 
 | 86 |  | 
 | 87 |     ALOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), | 
 | 88 |             sharedBuffer->size()); | 
 | 89 |  | 
 | 90 |     // ALOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize); | 
 | 91 |     size_t size = sizeof(audio_track_cblk_t); | 
 | 92 |     size_t bufferSize = frameCount * mFrameSize; | 
 | 93 |     if (sharedBuffer == 0) { | 
 | 94 |         size += bufferSize; | 
 | 95 |     } | 
 | 96 |  | 
 | 97 |     if (client != 0) { | 
 | 98 |         mCblkMemory = client->heap()->allocate(size); | 
 | 99 |         if (mCblkMemory != 0) { | 
 | 100 |             mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer()); | 
 | 101 |             // can't assume mCblk != NULL | 
 | 102 |         } else { | 
 | 103 |             ALOGE("not enough memory for AudioTrack size=%u", size); | 
 | 104 |             client->heap()->dump("AudioTrack"); | 
 | 105 |             return; | 
 | 106 |         } | 
 | 107 |     } else { | 
 | 108 |         mCblk = (audio_track_cblk_t *)(new uint8_t[size]); | 
 | 109 |         // assume mCblk != NULL | 
 | 110 |     } | 
 | 111 |  | 
 | 112 |     // construct the shared structure in-place. | 
 | 113 |     if (mCblk != NULL) { | 
 | 114 |         new(mCblk) audio_track_cblk_t(); | 
 | 115 |         // clear all buffers | 
 | 116 |         mCblk->frameCount_ = frameCount; | 
 | 117 |         mCblk->sampleRate = sampleRate; | 
 | 118 | // uncomment the following lines to quickly test 32-bit wraparound | 
 | 119 | //      mCblk->user = 0xffff0000; | 
 | 120 | //      mCblk->server = 0xffff0000; | 
 | 121 | //      mCblk->userBase = 0xffff0000; | 
 | 122 | //      mCblk->serverBase = 0xffff0000; | 
 | 123 |         if (sharedBuffer == 0) { | 
 | 124 |             mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t); | 
 | 125 |             memset(mBuffer, 0, bufferSize); | 
 | 126 |             // Force underrun condition to avoid false underrun callback until first data is | 
 | 127 |             // written to buffer (other flags are cleared) | 
 | 128 |             mCblk->flags = CBLK_UNDERRUN; | 
 | 129 |         } else { | 
 | 130 |             mBuffer = sharedBuffer->pointer(); | 
 | 131 |         } | 
 | 132 |         mBufferEnd = (uint8_t *)mBuffer + bufferSize; | 
 | 133 |     } | 
 | 134 | } | 
 | 135 |  | 
 | 136 | AudioFlinger::ThreadBase::TrackBase::~TrackBase() | 
 | 137 | { | 
 | 138 |     if (mCblk != NULL) { | 
 | 139 |         if (mClient == 0) { | 
 | 140 |             delete mCblk; | 
 | 141 |         } else { | 
 | 142 |             mCblk->~audio_track_cblk_t();   // destroy our shared-structure. | 
 | 143 |         } | 
 | 144 |     } | 
 | 145 |     mCblkMemory.clear();    // free the shared memory before releasing the heap it belongs to | 
 | 146 |     if (mClient != 0) { | 
 | 147 |         // Client destructor must run with AudioFlinger mutex locked | 
 | 148 |         Mutex::Autolock _l(mClient->audioFlinger()->mLock); | 
 | 149 |         // If the client's reference count drops to zero, the associated destructor | 
 | 150 |         // must run with AudioFlinger lock held. Thus the explicit clear() rather than | 
 | 151 |         // relying on the automatic clear() at end of scope. | 
 | 152 |         mClient.clear(); | 
 | 153 |     } | 
 | 154 | } | 
 | 155 |  | 
 | 156 | // AudioBufferProvider interface | 
 | 157 | // getNextBuffer() = 0; | 
 | 158 | // This implementation of releaseBuffer() is used by Track and RecordTrack, but not TimedTrack | 
 | 159 | void AudioFlinger::ThreadBase::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer) | 
 | 160 | { | 
 | 161 |     buffer->raw = NULL; | 
 | 162 |     mStepCount = buffer->frameCount; | 
 | 163 |     // FIXME See note at getNextBuffer() | 
 | 164 |     (void) step();      // ignore return value of step() | 
 | 165 |     buffer->frameCount = 0; | 
 | 166 | } | 
 | 167 |  | 
 | 168 | bool AudioFlinger::ThreadBase::TrackBase::step() { | 
 | 169 |     bool result; | 
 | 170 |     audio_track_cblk_t* cblk = this->cblk(); | 
 | 171 |  | 
 | 172 |     result = cblk->stepServer(mStepCount, mFrameCount, isOut()); | 
 | 173 |     if (!result) { | 
 | 174 |         ALOGV("stepServer failed acquiring cblk mutex"); | 
 | 175 |         mStepServerFailed = true; | 
 | 176 |     } | 
 | 177 |     return result; | 
 | 178 | } | 
 | 179 |  | 
 | 180 | void AudioFlinger::ThreadBase::TrackBase::reset() { | 
 | 181 |     audio_track_cblk_t* cblk = this->cblk(); | 
 | 182 |  | 
 | 183 |     cblk->user = 0; | 
 | 184 |     cblk->server = 0; | 
 | 185 |     cblk->userBase = 0; | 
 | 186 |     cblk->serverBase = 0; | 
 | 187 |     mStepServerFailed = false; | 
 | 188 |     ALOGV("TrackBase::reset"); | 
 | 189 | } | 
 | 190 |  | 
 | 191 | uint32_t AudioFlinger::ThreadBase::TrackBase::sampleRate() const { | 
 | 192 |     return mCblk->sampleRate; | 
 | 193 | } | 
 | 194 |  | 
 | 195 | void* AudioFlinger::ThreadBase::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const { | 
 | 196 |     audio_track_cblk_t* cblk = this->cblk(); | 
 | 197 |     int8_t *bufferStart = (int8_t *)mBuffer + (offset-cblk->serverBase) * mFrameSize; | 
 | 198 |     int8_t *bufferEnd = bufferStart + frames * mFrameSize; | 
 | 199 |  | 
 | 200 |     // Check validity of returned pointer in case the track control block would have been corrupted. | 
 | 201 |     ALOG_ASSERT(!(bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd), | 
 | 202 |             "TrackBase::getBuffer buffer out of range:\n" | 
 | 203 |                 "    start: %p, end %p , mBuffer %p mBufferEnd %p\n" | 
 | 204 |                 "    server %u, serverBase %u, user %u, userBase %u, frameSize %u", | 
 | 205 |                 bufferStart, bufferEnd, mBuffer, mBufferEnd, | 
 | 206 |                 cblk->server, cblk->serverBase, cblk->user, cblk->userBase, mFrameSize); | 
 | 207 |  | 
 | 208 |     return bufferStart; | 
 | 209 | } | 
 | 210 |  | 
 | 211 | status_t AudioFlinger::ThreadBase::TrackBase::setSyncEvent(const sp<SyncEvent>& event) | 
 | 212 | { | 
 | 213 |     mSyncEvents.add(event); | 
 | 214 |     return NO_ERROR; | 
 | 215 | } | 
 | 216 |  | 
 | 217 | // ---------------------------------------------------------------------------- | 
 | 218 | //      Playback | 
 | 219 | // ---------------------------------------------------------------------------- | 
 | 220 |  | 
 | 221 | AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::PlaybackThread::Track>& track) | 
 | 222 |     : BnAudioTrack(), | 
 | 223 |       mTrack(track) | 
 | 224 | { | 
 | 225 | } | 
 | 226 |  | 
 | 227 | AudioFlinger::TrackHandle::~TrackHandle() { | 
 | 228 |     // just stop the track on deletion, associated resources | 
 | 229 |     // will be freed from the main thread once all pending buffers have | 
 | 230 |     // been played. Unless it's not in the active track list, in which | 
 | 231 |     // case we free everything now... | 
 | 232 |     mTrack->destroy(); | 
 | 233 | } | 
 | 234 |  | 
 | 235 | sp<IMemory> AudioFlinger::TrackHandle::getCblk() const { | 
 | 236 |     return mTrack->getCblk(); | 
 | 237 | } | 
 | 238 |  | 
 | 239 | status_t AudioFlinger::TrackHandle::start() { | 
 | 240 |     return mTrack->start(); | 
 | 241 | } | 
 | 242 |  | 
 | 243 | void AudioFlinger::TrackHandle::stop() { | 
 | 244 |     mTrack->stop(); | 
 | 245 | } | 
 | 246 |  | 
 | 247 | void AudioFlinger::TrackHandle::flush() { | 
 | 248 |     mTrack->flush(); | 
 | 249 | } | 
 | 250 |  | 
 | 251 | void AudioFlinger::TrackHandle::mute(bool e) { | 
 | 252 |     mTrack->mute(e); | 
 | 253 | } | 
 | 254 |  | 
 | 255 | void AudioFlinger::TrackHandle::pause() { | 
 | 256 |     mTrack->pause(); | 
 | 257 | } | 
 | 258 |  | 
 | 259 | status_t AudioFlinger::TrackHandle::attachAuxEffect(int EffectId) | 
 | 260 | { | 
 | 261 |     return mTrack->attachAuxEffect(EffectId); | 
 | 262 | } | 
 | 263 |  | 
 | 264 | status_t AudioFlinger::TrackHandle::allocateTimedBuffer(size_t size, | 
 | 265 |                                                          sp<IMemory>* buffer) { | 
 | 266 |     if (!mTrack->isTimedTrack()) | 
 | 267 |         return INVALID_OPERATION; | 
 | 268 |  | 
 | 269 |     PlaybackThread::TimedTrack* tt = | 
 | 270 |             reinterpret_cast<PlaybackThread::TimedTrack*>(mTrack.get()); | 
 | 271 |     return tt->allocateTimedBuffer(size, buffer); | 
 | 272 | } | 
 | 273 |  | 
 | 274 | status_t AudioFlinger::TrackHandle::queueTimedBuffer(const sp<IMemory>& buffer, | 
 | 275 |                                                      int64_t pts) { | 
 | 276 |     if (!mTrack->isTimedTrack()) | 
 | 277 |         return INVALID_OPERATION; | 
 | 278 |  | 
 | 279 |     PlaybackThread::TimedTrack* tt = | 
 | 280 |             reinterpret_cast<PlaybackThread::TimedTrack*>(mTrack.get()); | 
 | 281 |     return tt->queueTimedBuffer(buffer, pts); | 
 | 282 | } | 
 | 283 |  | 
 | 284 | status_t AudioFlinger::TrackHandle::setMediaTimeTransform( | 
 | 285 |     const LinearTransform& xform, int target) { | 
 | 286 |  | 
 | 287 |     if (!mTrack->isTimedTrack()) | 
 | 288 |         return INVALID_OPERATION; | 
 | 289 |  | 
 | 290 |     PlaybackThread::TimedTrack* tt = | 
 | 291 |             reinterpret_cast<PlaybackThread::TimedTrack*>(mTrack.get()); | 
 | 292 |     return tt->setMediaTimeTransform( | 
 | 293 |         xform, static_cast<TimedAudioTrack::TargetTimeline>(target)); | 
 | 294 | } | 
 | 295 |  | 
 | 296 | status_t AudioFlinger::TrackHandle::onTransact( | 
 | 297 |     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) | 
 | 298 | { | 
 | 299 |     return BnAudioTrack::onTransact(code, data, reply, flags); | 
 | 300 | } | 
 | 301 |  | 
 | 302 | // ---------------------------------------------------------------------------- | 
 | 303 |  | 
 | 304 | // Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held | 
 | 305 | AudioFlinger::PlaybackThread::Track::Track( | 
 | 306 |             PlaybackThread *thread, | 
 | 307 |             const sp<Client>& client, | 
 | 308 |             audio_stream_type_t streamType, | 
 | 309 |             uint32_t sampleRate, | 
 | 310 |             audio_format_t format, | 
 | 311 |             audio_channel_mask_t channelMask, | 
 | 312 |             size_t frameCount, | 
 | 313 |             const sp<IMemory>& sharedBuffer, | 
 | 314 |             int sessionId, | 
 | 315 |             IAudioFlinger::track_flags_t flags) | 
 | 316 |     :   TrackBase(thread, client, sampleRate, format, channelMask, frameCount, sharedBuffer, | 
 | 317 |             sessionId), | 
 | 318 |     mMute(false), | 
 | 319 |     mFillingUpStatus(FS_INVALID), | 
 | 320 |     // mRetryCount initialized later when needed | 
 | 321 |     mSharedBuffer(sharedBuffer), | 
 | 322 |     mStreamType(streamType), | 
 | 323 |     mName(-1),  // see note below | 
 | 324 |     mMainBuffer(thread->mixBuffer()), | 
 | 325 |     mAuxBuffer(NULL), | 
 | 326 |     mAuxEffectId(0), mHasVolumeController(false), | 
 | 327 |     mPresentationCompleteFrames(0), | 
 | 328 |     mFlags(flags), | 
 | 329 |     mFastIndex(-1), | 
 | 330 |     mUnderrunCount(0), | 
 | 331 |     mCachedVolume(1.0) | 
 | 332 | { | 
 | 333 |     if (mCblk != NULL) { | 
 | 334 |         // to avoid leaking a track name, do not allocate one unless there is an mCblk | 
 | 335 |         mName = thread->getTrackName_l(channelMask, sessionId); | 
 | 336 |         mCblk->mName = mName; | 
 | 337 |         if (mName < 0) { | 
 | 338 |             ALOGE("no more track names available"); | 
 | 339 |             return; | 
 | 340 |         } | 
 | 341 |         // only allocate a fast track index if we were able to allocate a normal track name | 
 | 342 |         if (flags & IAudioFlinger::TRACK_FAST) { | 
 | 343 |             ALOG_ASSERT(thread->mFastTrackAvailMask != 0); | 
 | 344 |             int i = __builtin_ctz(thread->mFastTrackAvailMask); | 
 | 345 |             ALOG_ASSERT(0 < i && i < (int)FastMixerState::kMaxFastTracks); | 
 | 346 |             // FIXME This is too eager.  We allocate a fast track index before the | 
 | 347 |             //       fast track becomes active.  Since fast tracks are a scarce resource, | 
 | 348 |             //       this means we are potentially denying other more important fast tracks from | 
 | 349 |             //       being created.  It would be better to allocate the index dynamically. | 
 | 350 |             mFastIndex = i; | 
 | 351 |             mCblk->mName = i; | 
 | 352 |             // Read the initial underruns because this field is never cleared by the fast mixer | 
 | 353 |             mObservedUnderruns = thread->getFastTrackUnderruns(i); | 
 | 354 |             thread->mFastTrackAvailMask &= ~(1 << i); | 
 | 355 |         } | 
 | 356 |     } | 
 | 357 |     ALOGV("Track constructor name %d, calling pid %d", mName, | 
 | 358 |             IPCThreadState::self()->getCallingPid()); | 
 | 359 | } | 
 | 360 |  | 
 | 361 | AudioFlinger::PlaybackThread::Track::~Track() | 
 | 362 | { | 
 | 363 |     ALOGV("PlaybackThread::Track destructor"); | 
 | 364 | } | 
 | 365 |  | 
 | 366 | void AudioFlinger::PlaybackThread::Track::destroy() | 
 | 367 | { | 
 | 368 |     // NOTE: destroyTrack_l() can remove a strong reference to this Track | 
 | 369 |     // by removing it from mTracks vector, so there is a risk that this Tracks's | 
 | 370 |     // destructor is called. As the destructor needs to lock mLock, | 
 | 371 |     // we must acquire a strong reference on this Track before locking mLock | 
 | 372 |     // here so that the destructor is called only when exiting this function. | 
 | 373 |     // On the other hand, as long as Track::destroy() is only called by | 
 | 374 |     // TrackHandle destructor, the TrackHandle still holds a strong ref on | 
 | 375 |     // this Track with its member mTrack. | 
 | 376 |     sp<Track> keep(this); | 
 | 377 |     { // scope for mLock | 
 | 378 |         sp<ThreadBase> thread = mThread.promote(); | 
 | 379 |         if (thread != 0) { | 
 | 380 |             if (!isOutputTrack()) { | 
 | 381 |                 if (mState == ACTIVE || mState == RESUMING) { | 
 | 382 |                     AudioSystem::stopOutput(thread->id(), mStreamType, mSessionId); | 
 | 383 |  | 
 | 384 | #ifdef ADD_BATTERY_DATA | 
 | 385 |                     // to track the speaker usage | 
 | 386 |                     addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop); | 
 | 387 | #endif | 
 | 388 |                 } | 
 | 389 |                 AudioSystem::releaseOutput(thread->id()); | 
 | 390 |             } | 
 | 391 |             Mutex::Autolock _l(thread->mLock); | 
 | 392 |             PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); | 
 | 393 |             playbackThread->destroyTrack_l(this); | 
 | 394 |         } | 
 | 395 |     } | 
 | 396 | } | 
 | 397 |  | 
 | 398 | /*static*/ void AudioFlinger::PlaybackThread::Track::appendDumpHeader(String8& result) | 
 | 399 | { | 
 | 400 |     result.append("   Name Client Type Fmt Chn mask   Session StpCnt fCount S M F SRate  " | 
 | 401 |                   "L dB  R dB    Server      User     Main buf    Aux Buf  Flags Underruns\n"); | 
 | 402 | } | 
 | 403 |  | 
 | 404 | void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size) | 
 | 405 | { | 
 | 406 |     uint32_t vlr = mCblk->getVolumeLR(); | 
 | 407 |     if (isFastTrack()) { | 
 | 408 |         sprintf(buffer, "   F %2d", mFastIndex); | 
 | 409 |     } else { | 
 | 410 |         sprintf(buffer, "   %4d", mName - AudioMixer::TRACK0); | 
 | 411 |     } | 
 | 412 |     track_state state = mState; | 
 | 413 |     char stateChar; | 
 | 414 |     switch (state) { | 
 | 415 |     case IDLE: | 
 | 416 |         stateChar = 'I'; | 
 | 417 |         break; | 
 | 418 |     case TERMINATED: | 
 | 419 |         stateChar = 'T'; | 
 | 420 |         break; | 
 | 421 |     case STOPPING_1: | 
 | 422 |         stateChar = 's'; | 
 | 423 |         break; | 
 | 424 |     case STOPPING_2: | 
 | 425 |         stateChar = '5'; | 
 | 426 |         break; | 
 | 427 |     case STOPPED: | 
 | 428 |         stateChar = 'S'; | 
 | 429 |         break; | 
 | 430 |     case RESUMING: | 
 | 431 |         stateChar = 'R'; | 
 | 432 |         break; | 
 | 433 |     case ACTIVE: | 
 | 434 |         stateChar = 'A'; | 
 | 435 |         break; | 
 | 436 |     case PAUSING: | 
 | 437 |         stateChar = 'p'; | 
 | 438 |         break; | 
 | 439 |     case PAUSED: | 
 | 440 |         stateChar = 'P'; | 
 | 441 |         break; | 
 | 442 |     case FLUSHED: | 
 | 443 |         stateChar = 'F'; | 
 | 444 |         break; | 
 | 445 |     default: | 
 | 446 |         stateChar = '?'; | 
 | 447 |         break; | 
 | 448 |     } | 
 | 449 |     char nowInUnderrun; | 
 | 450 |     switch (mObservedUnderruns.mBitFields.mMostRecent) { | 
 | 451 |     case UNDERRUN_FULL: | 
 | 452 |         nowInUnderrun = ' '; | 
 | 453 |         break; | 
 | 454 |     case UNDERRUN_PARTIAL: | 
 | 455 |         nowInUnderrun = '<'; | 
 | 456 |         break; | 
 | 457 |     case UNDERRUN_EMPTY: | 
 | 458 |         nowInUnderrun = '*'; | 
 | 459 |         break; | 
 | 460 |     default: | 
 | 461 |         nowInUnderrun = '?'; | 
 | 462 |         break; | 
 | 463 |     } | 
 | 464 |     snprintf(&buffer[7], size-7, " %6d %4u %3u 0x%08x %7u %6u %6u %1c %1d %1d %5u %5.2g %5.2g  " | 
 | 465 |             "0x%08x 0x%08x 0x%08x 0x%08x %#5x %9u%c\n", | 
 | 466 |             (mClient == 0) ? getpid_cached : mClient->pid(), | 
 | 467 |             mStreamType, | 
 | 468 |             mFormat, | 
 | 469 |             mChannelMask, | 
 | 470 |             mSessionId, | 
 | 471 |             mStepCount, | 
 | 472 |             mFrameCount, | 
 | 473 |             stateChar, | 
 | 474 |             mMute, | 
 | 475 |             mFillingUpStatus, | 
 | 476 |             mCblk->sampleRate, | 
 | 477 |             20.0 * log10((vlr & 0xFFFF) / 4096.0), | 
 | 478 |             20.0 * log10((vlr >> 16) / 4096.0), | 
 | 479 |             mCblk->server, | 
 | 480 |             mCblk->user, | 
 | 481 |             (int)mMainBuffer, | 
 | 482 |             (int)mAuxBuffer, | 
 | 483 |             mCblk->flags, | 
 | 484 |             mUnderrunCount, | 
 | 485 |             nowInUnderrun); | 
 | 486 | } | 
 | 487 |  | 
 | 488 | // AudioBufferProvider interface | 
 | 489 | status_t AudioFlinger::PlaybackThread::Track::getNextBuffer( | 
 | 490 |         AudioBufferProvider::Buffer* buffer, int64_t pts) | 
 | 491 | { | 
 | 492 |     audio_track_cblk_t* cblk = this->cblk(); | 
 | 493 |     uint32_t framesReady; | 
 | 494 |     uint32_t framesReq = buffer->frameCount; | 
 | 495 |  | 
 | 496 |     // Check if last stepServer failed, try to step now | 
 | 497 |     if (mStepServerFailed) { | 
 | 498 |         // FIXME When called by fast mixer, this takes a mutex with tryLock(). | 
 | 499 |         //       Since the fast mixer is higher priority than client callback thread, | 
 | 500 |         //       it does not result in priority inversion for client. | 
 | 501 |         //       But a non-blocking solution would be preferable to avoid | 
 | 502 |         //       fast mixer being unable to tryLock(), and | 
 | 503 |         //       to avoid the extra context switches if the client wakes up, | 
 | 504 |         //       discovers the mutex is locked, then has to wait for fast mixer to unlock. | 
 | 505 |         if (!step())  goto getNextBuffer_exit; | 
 | 506 |         ALOGV("stepServer recovered"); | 
 | 507 |         mStepServerFailed = false; | 
 | 508 |     } | 
 | 509 |  | 
 | 510 |     // FIXME Same as above | 
 | 511 |     framesReady = cblk->framesReadyOut(); | 
 | 512 |  | 
 | 513 |     if (CC_LIKELY(framesReady)) { | 
 | 514 |         uint32_t s = cblk->server; | 
 | 515 |         uint32_t bufferEnd = cblk->serverBase + mFrameCount; | 
 | 516 |  | 
 | 517 |         bufferEnd = (cblk->loopEnd < bufferEnd) ? cblk->loopEnd : bufferEnd; | 
 | 518 |         if (framesReq > framesReady) { | 
 | 519 |             framesReq = framesReady; | 
 | 520 |         } | 
 | 521 |         if (framesReq > bufferEnd - s) { | 
 | 522 |             framesReq = bufferEnd - s; | 
 | 523 |         } | 
 | 524 |  | 
 | 525 |         buffer->raw = getBuffer(s, framesReq); | 
 | 526 |         buffer->frameCount = framesReq; | 
 | 527 |         return NO_ERROR; | 
 | 528 |     } | 
 | 529 |  | 
 | 530 | getNextBuffer_exit: | 
 | 531 |     buffer->raw = NULL; | 
 | 532 |     buffer->frameCount = 0; | 
 | 533 |     ALOGV("getNextBuffer() no more data for track %d on thread %p", mName, mThread.unsafe_get()); | 
 | 534 |     return NOT_ENOUGH_DATA; | 
 | 535 | } | 
 | 536 |  | 
 | 537 | // Note that framesReady() takes a mutex on the control block using tryLock(). | 
 | 538 | // This could result in priority inversion if framesReady() is called by the normal mixer, | 
 | 539 | // as the normal mixer thread runs at lower | 
 | 540 | // priority than the client's callback thread:  there is a short window within framesReady() | 
 | 541 | // during which the normal mixer could be preempted, and the client callback would block. | 
 | 542 | // Another problem can occur if framesReady() is called by the fast mixer: | 
 | 543 | // the tryLock() could block for up to 1 ms, and a sequence of these could delay fast mixer. | 
 | 544 | // FIXME Replace AudioTrackShared control block implementation by a non-blocking FIFO queue. | 
 | 545 | size_t AudioFlinger::PlaybackThread::Track::framesReady() const { | 
 | 546 |     return mCblk->framesReadyOut(); | 
 | 547 | } | 
 | 548 |  | 
 | 549 | // Don't call for fast tracks; the framesReady() could result in priority inversion | 
 | 550 | bool AudioFlinger::PlaybackThread::Track::isReady() const { | 
 | 551 |     if (mFillingUpStatus != FS_FILLING || isStopped() || isPausing()) { | 
 | 552 |         return true; | 
 | 553 |     } | 
 | 554 |  | 
 | 555 |     if (framesReady() >= mFrameCount || | 
 | 556 |             (mCblk->flags & CBLK_FORCEREADY)) { | 
 | 557 |         mFillingUpStatus = FS_FILLED; | 
 | 558 |         android_atomic_and(~CBLK_FORCEREADY, &mCblk->flags); | 
 | 559 |         return true; | 
 | 560 |     } | 
 | 561 |     return false; | 
 | 562 | } | 
 | 563 |  | 
 | 564 | status_t AudioFlinger::PlaybackThread::Track::start(AudioSystem::sync_event_t event, | 
 | 565 |                                                     int triggerSession) | 
 | 566 | { | 
 | 567 |     status_t status = NO_ERROR; | 
 | 568 |     ALOGV("start(%d), calling pid %d session %d", | 
 | 569 |             mName, IPCThreadState::self()->getCallingPid(), mSessionId); | 
 | 570 |  | 
 | 571 |     sp<ThreadBase> thread = mThread.promote(); | 
 | 572 |     if (thread != 0) { | 
 | 573 |         Mutex::Autolock _l(thread->mLock); | 
 | 574 |         track_state state = mState; | 
 | 575 |         // here the track could be either new, or restarted | 
 | 576 |         // in both cases "unstop" the track | 
 | 577 |         if (mState == PAUSED) { | 
 | 578 |             mState = TrackBase::RESUMING; | 
 | 579 |             ALOGV("PAUSED => RESUMING (%d) on thread %p", mName, this); | 
 | 580 |         } else { | 
 | 581 |             mState = TrackBase::ACTIVE; | 
 | 582 |             ALOGV("? => ACTIVE (%d) on thread %p", mName, this); | 
 | 583 |         } | 
 | 584 |  | 
 | 585 |         if (!isOutputTrack() && state != ACTIVE && state != RESUMING) { | 
 | 586 |             thread->mLock.unlock(); | 
 | 587 |             status = AudioSystem::startOutput(thread->id(), mStreamType, mSessionId); | 
 | 588 |             thread->mLock.lock(); | 
 | 589 |  | 
 | 590 | #ifdef ADD_BATTERY_DATA | 
 | 591 |             // to track the speaker usage | 
 | 592 |             if (status == NO_ERROR) { | 
 | 593 |                 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStart); | 
 | 594 |             } | 
 | 595 | #endif | 
 | 596 |         } | 
 | 597 |         if (status == NO_ERROR) { | 
 | 598 |             PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); | 
 | 599 |             playbackThread->addTrack_l(this); | 
 | 600 |         } else { | 
 | 601 |             mState = state; | 
 | 602 |             triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE); | 
 | 603 |         } | 
 | 604 |     } else { | 
 | 605 |         status = BAD_VALUE; | 
 | 606 |     } | 
 | 607 |     return status; | 
 | 608 | } | 
 | 609 |  | 
 | 610 | void AudioFlinger::PlaybackThread::Track::stop() | 
 | 611 | { | 
 | 612 |     ALOGV("stop(%d), calling pid %d", mName, IPCThreadState::self()->getCallingPid()); | 
 | 613 |     sp<ThreadBase> thread = mThread.promote(); | 
 | 614 |     if (thread != 0) { | 
 | 615 |         Mutex::Autolock _l(thread->mLock); | 
 | 616 |         track_state state = mState; | 
 | 617 |         if (state == RESUMING || state == ACTIVE || state == PAUSING || state == PAUSED) { | 
 | 618 |             // If the track is not active (PAUSED and buffers full), flush buffers | 
 | 619 |             PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); | 
 | 620 |             if (playbackThread->mActiveTracks.indexOf(this) < 0) { | 
 | 621 |                 reset(); | 
 | 622 |                 mState = STOPPED; | 
 | 623 |             } else if (!isFastTrack()) { | 
 | 624 |                 mState = STOPPED; | 
 | 625 |             } else { | 
 | 626 |                 // prepareTracks_l() will set state to STOPPING_2 after next underrun, | 
 | 627 |                 // and then to STOPPED and reset() when presentation is complete | 
 | 628 |                 mState = STOPPING_1; | 
 | 629 |             } | 
 | 630 |             ALOGV("not stopping/stopped => stopping/stopped (%d) on thread %p", mName, | 
 | 631 |                     playbackThread); | 
 | 632 |         } | 
 | 633 |         if (!isOutputTrack() && (state == ACTIVE || state == RESUMING)) { | 
 | 634 |             thread->mLock.unlock(); | 
 | 635 |             AudioSystem::stopOutput(thread->id(), mStreamType, mSessionId); | 
 | 636 |             thread->mLock.lock(); | 
 | 637 |  | 
 | 638 | #ifdef ADD_BATTERY_DATA | 
 | 639 |             // to track the speaker usage | 
 | 640 |             addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop); | 
 | 641 | #endif | 
 | 642 |         } | 
 | 643 |     } | 
 | 644 | } | 
 | 645 |  | 
 | 646 | void AudioFlinger::PlaybackThread::Track::pause() | 
 | 647 | { | 
 | 648 |     ALOGV("pause(%d), calling pid %d", mName, IPCThreadState::self()->getCallingPid()); | 
 | 649 |     sp<ThreadBase> thread = mThread.promote(); | 
 | 650 |     if (thread != 0) { | 
 | 651 |         Mutex::Autolock _l(thread->mLock); | 
 | 652 |         if (mState == ACTIVE || mState == RESUMING) { | 
 | 653 |             mState = PAUSING; | 
 | 654 |             ALOGV("ACTIVE/RESUMING => PAUSING (%d) on thread %p", mName, thread.get()); | 
 | 655 |             if (!isOutputTrack()) { | 
 | 656 |                 thread->mLock.unlock(); | 
 | 657 |                 AudioSystem::stopOutput(thread->id(), mStreamType, mSessionId); | 
 | 658 |                 thread->mLock.lock(); | 
 | 659 |  | 
 | 660 | #ifdef ADD_BATTERY_DATA | 
 | 661 |                 // to track the speaker usage | 
 | 662 |                 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop); | 
 | 663 | #endif | 
 | 664 |             } | 
 | 665 |         } | 
 | 666 |     } | 
 | 667 | } | 
 | 668 |  | 
 | 669 | void AudioFlinger::PlaybackThread::Track::flush() | 
 | 670 | { | 
 | 671 |     ALOGV("flush(%d)", mName); | 
 | 672 |     sp<ThreadBase> thread = mThread.promote(); | 
 | 673 |     if (thread != 0) { | 
 | 674 |         Mutex::Autolock _l(thread->mLock); | 
 | 675 |         if (mState != STOPPING_1 && mState != STOPPING_2 && mState != STOPPED && mState != PAUSED && | 
 | 676 |                 mState != PAUSING && mState != IDLE && mState != FLUSHED) { | 
 | 677 |             return; | 
 | 678 |         } | 
 | 679 |         // No point remaining in PAUSED state after a flush => go to | 
 | 680 |         // FLUSHED state | 
 | 681 |         mState = FLUSHED; | 
 | 682 |         // do not reset the track if it is still in the process of being stopped or paused. | 
 | 683 |         // this will be done by prepareTracks_l() when the track is stopped. | 
 | 684 |         // prepareTracks_l() will see mState == FLUSHED, then | 
 | 685 |         // remove from active track list, reset(), and trigger presentation complete | 
 | 686 |         PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); | 
 | 687 |         if (playbackThread->mActiveTracks.indexOf(this) < 0) { | 
 | 688 |             reset(); | 
 | 689 |         } | 
 | 690 |     } | 
 | 691 | } | 
 | 692 |  | 
 | 693 | void AudioFlinger::PlaybackThread::Track::reset() | 
 | 694 | { | 
 | 695 |     // Do not reset twice to avoid discarding data written just after a flush and before | 
 | 696 |     // the audioflinger thread detects the track is stopped. | 
 | 697 |     if (!mResetDone) { | 
 | 698 |         TrackBase::reset(); | 
 | 699 |         // Force underrun condition to avoid false underrun callback until first data is | 
 | 700 |         // written to buffer | 
 | 701 |         android_atomic_and(~CBLK_FORCEREADY, &mCblk->flags); | 
 | 702 |         android_atomic_or(CBLK_UNDERRUN, &mCblk->flags); | 
 | 703 |         mFillingUpStatus = FS_FILLING; | 
 | 704 |         mResetDone = true; | 
 | 705 |         if (mState == FLUSHED) { | 
 | 706 |             mState = IDLE; | 
 | 707 |         } | 
 | 708 |     } | 
 | 709 | } | 
 | 710 |  | 
 | 711 | void AudioFlinger::PlaybackThread::Track::mute(bool muted) | 
 | 712 | { | 
 | 713 |     mMute = muted; | 
 | 714 | } | 
 | 715 |  | 
 | 716 | status_t AudioFlinger::PlaybackThread::Track::attachAuxEffect(int EffectId) | 
 | 717 | { | 
 | 718 |     status_t status = DEAD_OBJECT; | 
 | 719 |     sp<ThreadBase> thread = mThread.promote(); | 
 | 720 |     if (thread != 0) { | 
 | 721 |         PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); | 
 | 722 |         sp<AudioFlinger> af = mClient->audioFlinger(); | 
 | 723 |  | 
 | 724 |         Mutex::Autolock _l(af->mLock); | 
 | 725 |  | 
 | 726 |         sp<PlaybackThread> srcThread = af->getEffectThread_l(AUDIO_SESSION_OUTPUT_MIX, EffectId); | 
 | 727 |  | 
 | 728 |         if (EffectId != 0 && srcThread != 0 && playbackThread != srcThread.get()) { | 
 | 729 |             Mutex::Autolock _dl(playbackThread->mLock); | 
 | 730 |             Mutex::Autolock _sl(srcThread->mLock); | 
 | 731 |             sp<EffectChain> chain = srcThread->getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX); | 
 | 732 |             if (chain == 0) { | 
 | 733 |                 return INVALID_OPERATION; | 
 | 734 |             } | 
 | 735 |  | 
 | 736 |             sp<EffectModule> effect = chain->getEffectFromId_l(EffectId); | 
 | 737 |             if (effect == 0) { | 
 | 738 |                 return INVALID_OPERATION; | 
 | 739 |             } | 
 | 740 |             srcThread->removeEffect_l(effect); | 
 | 741 |             playbackThread->addEffect_l(effect); | 
 | 742 |             // removeEffect_l() has stopped the effect if it was active so it must be restarted | 
 | 743 |             if (effect->state() == EffectModule::ACTIVE || | 
 | 744 |                     effect->state() == EffectModule::STOPPING) { | 
 | 745 |                 effect->start(); | 
 | 746 |             } | 
 | 747 |  | 
 | 748 |             sp<EffectChain> dstChain = effect->chain().promote(); | 
 | 749 |             if (dstChain == 0) { | 
 | 750 |                 srcThread->addEffect_l(effect); | 
 | 751 |                 return INVALID_OPERATION; | 
 | 752 |             } | 
 | 753 |             AudioSystem::unregisterEffect(effect->id()); | 
 | 754 |             AudioSystem::registerEffect(&effect->desc(), | 
 | 755 |                                         srcThread->id(), | 
 | 756 |                                         dstChain->strategy(), | 
 | 757 |                                         AUDIO_SESSION_OUTPUT_MIX, | 
 | 758 |                                         effect->id()); | 
 | 759 |         } | 
 | 760 |         status = playbackThread->attachAuxEffect(this, EffectId); | 
 | 761 |     } | 
 | 762 |     return status; | 
 | 763 | } | 
 | 764 |  | 
 | 765 | void AudioFlinger::PlaybackThread::Track::setAuxBuffer(int EffectId, int32_t *buffer) | 
 | 766 | { | 
 | 767 |     mAuxEffectId = EffectId; | 
 | 768 |     mAuxBuffer = buffer; | 
 | 769 | } | 
 | 770 |  | 
 | 771 | bool AudioFlinger::PlaybackThread::Track::presentationComplete(size_t framesWritten, | 
 | 772 |                                                          size_t audioHalFrames) | 
 | 773 | { | 
 | 774 |     // a track is considered presented when the total number of frames written to audio HAL | 
 | 775 |     // corresponds to the number of frames written when presentationComplete() is called for the | 
 | 776 |     // first time (mPresentationCompleteFrames == 0) plus the buffer filling status at that time. | 
 | 777 |     if (mPresentationCompleteFrames == 0) { | 
 | 778 |         mPresentationCompleteFrames = framesWritten + audioHalFrames; | 
 | 779 |         ALOGV("presentationComplete() reset: mPresentationCompleteFrames %d audioHalFrames %d", | 
 | 780 |                   mPresentationCompleteFrames, audioHalFrames); | 
 | 781 |     } | 
 | 782 |     if (framesWritten >= mPresentationCompleteFrames) { | 
 | 783 |         ALOGV("presentationComplete() session %d complete: framesWritten %d", | 
 | 784 |                   mSessionId, framesWritten); | 
 | 785 |         triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE); | 
 | 786 |         return true; | 
 | 787 |     } | 
 | 788 |     return false; | 
 | 789 | } | 
 | 790 |  | 
 | 791 | void AudioFlinger::PlaybackThread::Track::triggerEvents(AudioSystem::sync_event_t type) | 
 | 792 | { | 
 | 793 |     for (int i = 0; i < (int)mSyncEvents.size(); i++) { | 
 | 794 |         if (mSyncEvents[i]->type() == type) { | 
 | 795 |             mSyncEvents[i]->trigger(); | 
 | 796 |             mSyncEvents.removeAt(i); | 
 | 797 |             i--; | 
 | 798 |         } | 
 | 799 |     } | 
 | 800 | } | 
 | 801 |  | 
 | 802 | // implement VolumeBufferProvider interface | 
 | 803 |  | 
 | 804 | uint32_t AudioFlinger::PlaybackThread::Track::getVolumeLR() | 
 | 805 | { | 
 | 806 |     // called by FastMixer, so not allowed to take any locks, block, or do I/O including logs | 
 | 807 |     ALOG_ASSERT(isFastTrack() && (mCblk != NULL)); | 
 | 808 |     uint32_t vlr = mCblk->getVolumeLR(); | 
 | 809 |     uint32_t vl = vlr & 0xFFFF; | 
 | 810 |     uint32_t vr = vlr >> 16; | 
 | 811 |     // track volumes come from shared memory, so can't be trusted and must be clamped | 
 | 812 |     if (vl > MAX_GAIN_INT) { | 
 | 813 |         vl = MAX_GAIN_INT; | 
 | 814 |     } | 
 | 815 |     if (vr > MAX_GAIN_INT) { | 
 | 816 |         vr = MAX_GAIN_INT; | 
 | 817 |     } | 
 | 818 |     // now apply the cached master volume and stream type volume; | 
 | 819 |     // this is trusted but lacks any synchronization or barrier so may be stale | 
 | 820 |     float v = mCachedVolume; | 
 | 821 |     vl *= v; | 
 | 822 |     vr *= v; | 
 | 823 |     // re-combine into U4.16 | 
 | 824 |     vlr = (vr << 16) | (vl & 0xFFFF); | 
 | 825 |     // FIXME look at mute, pause, and stop flags | 
 | 826 |     return vlr; | 
 | 827 | } | 
 | 828 |  | 
 | 829 | status_t AudioFlinger::PlaybackThread::Track::setSyncEvent(const sp<SyncEvent>& event) | 
 | 830 | { | 
 | 831 |     if (mState == TERMINATED || mState == PAUSED || | 
 | 832 |             ((framesReady() == 0) && ((mSharedBuffer != 0) || | 
 | 833 |                                       (mState == STOPPED)))) { | 
 | 834 |         ALOGW("Track::setSyncEvent() in invalid state %d on session %d %s mode, framesReady %d ", | 
 | 835 |               mState, mSessionId, (mSharedBuffer != 0) ? "static" : "stream", framesReady()); | 
 | 836 |         event->cancel(); | 
 | 837 |         return INVALID_OPERATION; | 
 | 838 |     } | 
 | 839 |     (void) TrackBase::setSyncEvent(event); | 
 | 840 |     return NO_ERROR; | 
 | 841 | } | 
 | 842 |  | 
 | 843 | bool AudioFlinger::PlaybackThread::Track::isOut() const | 
 | 844 | { | 
 | 845 |     return true; | 
 | 846 | } | 
 | 847 |  | 
 | 848 | // ---------------------------------------------------------------------------- | 
 | 849 |  | 
 | 850 | sp<AudioFlinger::PlaybackThread::TimedTrack> | 
 | 851 | AudioFlinger::PlaybackThread::TimedTrack::create( | 
 | 852 |             PlaybackThread *thread, | 
 | 853 |             const sp<Client>& client, | 
 | 854 |             audio_stream_type_t streamType, | 
 | 855 |             uint32_t sampleRate, | 
 | 856 |             audio_format_t format, | 
 | 857 |             audio_channel_mask_t channelMask, | 
 | 858 |             size_t frameCount, | 
 | 859 |             const sp<IMemory>& sharedBuffer, | 
 | 860 |             int sessionId) { | 
 | 861 |     if (!client->reserveTimedTrack()) | 
 | 862 |         return 0; | 
 | 863 |  | 
 | 864 |     return new TimedTrack( | 
 | 865 |         thread, client, streamType, sampleRate, format, channelMask, frameCount, | 
 | 866 |         sharedBuffer, sessionId); | 
 | 867 | } | 
 | 868 |  | 
 | 869 | AudioFlinger::PlaybackThread::TimedTrack::TimedTrack( | 
 | 870 |             PlaybackThread *thread, | 
 | 871 |             const sp<Client>& client, | 
 | 872 |             audio_stream_type_t streamType, | 
 | 873 |             uint32_t sampleRate, | 
 | 874 |             audio_format_t format, | 
 | 875 |             audio_channel_mask_t channelMask, | 
 | 876 |             size_t frameCount, | 
 | 877 |             const sp<IMemory>& sharedBuffer, | 
 | 878 |             int sessionId) | 
 | 879 |     : Track(thread, client, streamType, sampleRate, format, channelMask, | 
 | 880 |             frameCount, sharedBuffer, sessionId, IAudioFlinger::TRACK_TIMED), | 
 | 881 |       mQueueHeadInFlight(false), | 
 | 882 |       mTrimQueueHeadOnRelease(false), | 
 | 883 |       mFramesPendingInQueue(0), | 
 | 884 |       mTimedSilenceBuffer(NULL), | 
 | 885 |       mTimedSilenceBufferSize(0), | 
 | 886 |       mTimedAudioOutputOnTime(false), | 
 | 887 |       mMediaTimeTransformValid(false) | 
 | 888 | { | 
 | 889 |     LocalClock lc; | 
 | 890 |     mLocalTimeFreq = lc.getLocalFreq(); | 
 | 891 |  | 
 | 892 |     mLocalTimeToSampleTransform.a_zero = 0; | 
 | 893 |     mLocalTimeToSampleTransform.b_zero = 0; | 
 | 894 |     mLocalTimeToSampleTransform.a_to_b_numer = sampleRate; | 
 | 895 |     mLocalTimeToSampleTransform.a_to_b_denom = mLocalTimeFreq; | 
 | 896 |     LinearTransform::reduce(&mLocalTimeToSampleTransform.a_to_b_numer, | 
 | 897 |                             &mLocalTimeToSampleTransform.a_to_b_denom); | 
 | 898 |  | 
 | 899 |     mMediaTimeToSampleTransform.a_zero = 0; | 
 | 900 |     mMediaTimeToSampleTransform.b_zero = 0; | 
 | 901 |     mMediaTimeToSampleTransform.a_to_b_numer = sampleRate; | 
 | 902 |     mMediaTimeToSampleTransform.a_to_b_denom = 1000000; | 
 | 903 |     LinearTransform::reduce(&mMediaTimeToSampleTransform.a_to_b_numer, | 
 | 904 |                             &mMediaTimeToSampleTransform.a_to_b_denom); | 
 | 905 | } | 
 | 906 |  | 
 | 907 | AudioFlinger::PlaybackThread::TimedTrack::~TimedTrack() { | 
 | 908 |     mClient->releaseTimedTrack(); | 
 | 909 |     delete [] mTimedSilenceBuffer; | 
 | 910 | } | 
 | 911 |  | 
 | 912 | status_t AudioFlinger::PlaybackThread::TimedTrack::allocateTimedBuffer( | 
 | 913 |     size_t size, sp<IMemory>* buffer) { | 
 | 914 |  | 
 | 915 |     Mutex::Autolock _l(mTimedBufferQueueLock); | 
 | 916 |  | 
 | 917 |     trimTimedBufferQueue_l(); | 
 | 918 |  | 
 | 919 |     // lazily initialize the shared memory heap for timed buffers | 
 | 920 |     if (mTimedMemoryDealer == NULL) { | 
 | 921 |         const int kTimedBufferHeapSize = 512 << 10; | 
 | 922 |  | 
 | 923 |         mTimedMemoryDealer = new MemoryDealer(kTimedBufferHeapSize, | 
 | 924 |                                               "AudioFlingerTimed"); | 
 | 925 |         if (mTimedMemoryDealer == NULL) | 
 | 926 |             return NO_MEMORY; | 
 | 927 |     } | 
 | 928 |  | 
 | 929 |     sp<IMemory> newBuffer = mTimedMemoryDealer->allocate(size); | 
 | 930 |     if (newBuffer == NULL) { | 
 | 931 |         newBuffer = mTimedMemoryDealer->allocate(size); | 
 | 932 |         if (newBuffer == NULL) | 
 | 933 |             return NO_MEMORY; | 
 | 934 |     } | 
 | 935 |  | 
 | 936 |     *buffer = newBuffer; | 
 | 937 |     return NO_ERROR; | 
 | 938 | } | 
 | 939 |  | 
 | 940 | // caller must hold mTimedBufferQueueLock | 
 | 941 | void AudioFlinger::PlaybackThread::TimedTrack::trimTimedBufferQueue_l() { | 
 | 942 |     int64_t mediaTimeNow; | 
 | 943 |     { | 
 | 944 |         Mutex::Autolock mttLock(mMediaTimeTransformLock); | 
 | 945 |         if (!mMediaTimeTransformValid) | 
 | 946 |             return; | 
 | 947 |  | 
 | 948 |         int64_t targetTimeNow; | 
 | 949 |         status_t res = (mMediaTimeTransformTarget == TimedAudioTrack::COMMON_TIME) | 
 | 950 |             ? mCCHelper.getCommonTime(&targetTimeNow) | 
 | 951 |             : mCCHelper.getLocalTime(&targetTimeNow); | 
 | 952 |  | 
 | 953 |         if (OK != res) | 
 | 954 |             return; | 
 | 955 |  | 
 | 956 |         if (!mMediaTimeTransform.doReverseTransform(targetTimeNow, | 
 | 957 |                                                     &mediaTimeNow)) { | 
 | 958 |             return; | 
 | 959 |         } | 
 | 960 |     } | 
 | 961 |  | 
 | 962 |     size_t trimEnd; | 
 | 963 |     for (trimEnd = 0; trimEnd < mTimedBufferQueue.size(); trimEnd++) { | 
 | 964 |         int64_t bufEnd; | 
 | 965 |  | 
 | 966 |         if ((trimEnd + 1) < mTimedBufferQueue.size()) { | 
 | 967 |             // We have a next buffer.  Just use its PTS as the PTS of the frame | 
 | 968 |             // following the last frame in this buffer.  If the stream is sparse | 
 | 969 |             // (ie, there are deliberate gaps left in the stream which should be | 
 | 970 |             // filled with silence by the TimedAudioTrack), then this can result | 
 | 971 |             // in one extra buffer being left un-trimmed when it could have | 
 | 972 |             // been.  In general, this is not typical, and we would rather | 
 | 973 |             // optimized away the TS calculation below for the more common case | 
 | 974 |             // where PTSes are contiguous. | 
 | 975 |             bufEnd = mTimedBufferQueue[trimEnd + 1].pts(); | 
 | 976 |         } else { | 
 | 977 |             // We have no next buffer.  Compute the PTS of the frame following | 
 | 978 |             // the last frame in this buffer by computing the duration of of | 
 | 979 |             // this frame in media time units and adding it to the PTS of the | 
 | 980 |             // buffer. | 
 | 981 |             int64_t frameCount = mTimedBufferQueue[trimEnd].buffer()->size() | 
 | 982 |                                / mFrameSize; | 
 | 983 |  | 
 | 984 |             if (!mMediaTimeToSampleTransform.doReverseTransform(frameCount, | 
 | 985 |                                                                 &bufEnd)) { | 
 | 986 |                 ALOGE("Failed to convert frame count of %lld to media time" | 
 | 987 |                       " duration" " (scale factor %d/%u) in %s", | 
 | 988 |                       frameCount, | 
 | 989 |                       mMediaTimeToSampleTransform.a_to_b_numer, | 
 | 990 |                       mMediaTimeToSampleTransform.a_to_b_denom, | 
 | 991 |                       __PRETTY_FUNCTION__); | 
 | 992 |                 break; | 
 | 993 |             } | 
 | 994 |             bufEnd += mTimedBufferQueue[trimEnd].pts(); | 
 | 995 |         } | 
 | 996 |  | 
 | 997 |         if (bufEnd > mediaTimeNow) | 
 | 998 |             break; | 
 | 999 |  | 
 | 1000 |         // Is the buffer we want to use in the middle of a mix operation right | 
 | 1001 |         // now?  If so, don't actually trim it.  Just wait for the releaseBuffer | 
 | 1002 |         // from the mixer which should be coming back shortly. | 
 | 1003 |         if (!trimEnd && mQueueHeadInFlight) { | 
 | 1004 |             mTrimQueueHeadOnRelease = true; | 
 | 1005 |         } | 
 | 1006 |     } | 
 | 1007 |  | 
 | 1008 |     size_t trimStart = mTrimQueueHeadOnRelease ? 1 : 0; | 
 | 1009 |     if (trimStart < trimEnd) { | 
 | 1010 |         // Update the bookkeeping for framesReady() | 
 | 1011 |         for (size_t i = trimStart; i < trimEnd; ++i) { | 
 | 1012 |             updateFramesPendingAfterTrim_l(mTimedBufferQueue[i], "trim"); | 
 | 1013 |         } | 
 | 1014 |  | 
 | 1015 |         // Now actually remove the buffers from the queue. | 
 | 1016 |         mTimedBufferQueue.removeItemsAt(trimStart, trimEnd); | 
 | 1017 |     } | 
 | 1018 | } | 
 | 1019 |  | 
 | 1020 | void AudioFlinger::PlaybackThread::TimedTrack::trimTimedBufferQueueHead_l( | 
 | 1021 |         const char* logTag) { | 
 | 1022 |     ALOG_ASSERT(mTimedBufferQueue.size() > 0, | 
 | 1023 |                 "%s called (reason \"%s\"), but timed buffer queue has no" | 
 | 1024 |                 " elements to trim.", __FUNCTION__, logTag); | 
 | 1025 |  | 
 | 1026 |     updateFramesPendingAfterTrim_l(mTimedBufferQueue[0], logTag); | 
 | 1027 |     mTimedBufferQueue.removeAt(0); | 
 | 1028 | } | 
 | 1029 |  | 
 | 1030 | void AudioFlinger::PlaybackThread::TimedTrack::updateFramesPendingAfterTrim_l( | 
 | 1031 |         const TimedBuffer& buf, | 
 | 1032 |         const char* logTag) { | 
 | 1033 |     uint32_t bufBytes        = buf.buffer()->size(); | 
 | 1034 |     uint32_t consumedAlready = buf.position(); | 
 | 1035 |  | 
 | 1036 |     ALOG_ASSERT(consumedAlready <= bufBytes, | 
 | 1037 |                 "Bad bookkeeping while updating frames pending.  Timed buffer is" | 
 | 1038 |                 " only %u bytes long, but claims to have consumed %u" | 
 | 1039 |                 " bytes.  (update reason: \"%s\")", | 
 | 1040 |                 bufBytes, consumedAlready, logTag); | 
 | 1041 |  | 
 | 1042 |     uint32_t bufFrames = (bufBytes - consumedAlready) / mFrameSize; | 
 | 1043 |     ALOG_ASSERT(mFramesPendingInQueue >= bufFrames, | 
 | 1044 |                 "Bad bookkeeping while updating frames pending.  Should have at" | 
 | 1045 |                 " least %u queued frames, but we think we have only %u.  (update" | 
 | 1046 |                 " reason: \"%s\")", | 
 | 1047 |                 bufFrames, mFramesPendingInQueue, logTag); | 
 | 1048 |  | 
 | 1049 |     mFramesPendingInQueue -= bufFrames; | 
 | 1050 | } | 
 | 1051 |  | 
 | 1052 | status_t AudioFlinger::PlaybackThread::TimedTrack::queueTimedBuffer( | 
 | 1053 |     const sp<IMemory>& buffer, int64_t pts) { | 
 | 1054 |  | 
 | 1055 |     { | 
 | 1056 |         Mutex::Autolock mttLock(mMediaTimeTransformLock); | 
 | 1057 |         if (!mMediaTimeTransformValid) | 
 | 1058 |             return INVALID_OPERATION; | 
 | 1059 |     } | 
 | 1060 |  | 
 | 1061 |     Mutex::Autolock _l(mTimedBufferQueueLock); | 
 | 1062 |  | 
 | 1063 |     uint32_t bufFrames = buffer->size() / mFrameSize; | 
 | 1064 |     mFramesPendingInQueue += bufFrames; | 
 | 1065 |     mTimedBufferQueue.add(TimedBuffer(buffer, pts)); | 
 | 1066 |  | 
 | 1067 |     return NO_ERROR; | 
 | 1068 | } | 
 | 1069 |  | 
 | 1070 | status_t AudioFlinger::PlaybackThread::TimedTrack::setMediaTimeTransform( | 
 | 1071 |     const LinearTransform& xform, TimedAudioTrack::TargetTimeline target) { | 
 | 1072 |  | 
 | 1073 |     ALOGVV("setMediaTimeTransform az=%lld bz=%lld n=%d d=%u tgt=%d", | 
 | 1074 |            xform.a_zero, xform.b_zero, xform.a_to_b_numer, xform.a_to_b_denom, | 
 | 1075 |            target); | 
 | 1076 |  | 
 | 1077 |     if (!(target == TimedAudioTrack::LOCAL_TIME || | 
 | 1078 |           target == TimedAudioTrack::COMMON_TIME)) { | 
 | 1079 |         return BAD_VALUE; | 
 | 1080 |     } | 
 | 1081 |  | 
 | 1082 |     Mutex::Autolock lock(mMediaTimeTransformLock); | 
 | 1083 |     mMediaTimeTransform = xform; | 
 | 1084 |     mMediaTimeTransformTarget = target; | 
 | 1085 |     mMediaTimeTransformValid = true; | 
 | 1086 |  | 
 | 1087 |     return NO_ERROR; | 
 | 1088 | } | 
 | 1089 |  | 
 | 1090 | #define min(a, b) ((a) < (b) ? (a) : (b)) | 
 | 1091 |  | 
 | 1092 | // implementation of getNextBuffer for tracks whose buffers have timestamps | 
 | 1093 | status_t AudioFlinger::PlaybackThread::TimedTrack::getNextBuffer( | 
 | 1094 |     AudioBufferProvider::Buffer* buffer, int64_t pts) | 
 | 1095 | { | 
 | 1096 |     if (pts == AudioBufferProvider::kInvalidPTS) { | 
 | 1097 |         buffer->raw = NULL; | 
 | 1098 |         buffer->frameCount = 0; | 
 | 1099 |         mTimedAudioOutputOnTime = false; | 
 | 1100 |         return INVALID_OPERATION; | 
 | 1101 |     } | 
 | 1102 |  | 
 | 1103 |     Mutex::Autolock _l(mTimedBufferQueueLock); | 
 | 1104 |  | 
 | 1105 |     ALOG_ASSERT(!mQueueHeadInFlight, | 
 | 1106 |                 "getNextBuffer called without releaseBuffer!"); | 
 | 1107 |  | 
 | 1108 |     while (true) { | 
 | 1109 |  | 
 | 1110 |         // if we have no timed buffers, then fail | 
 | 1111 |         if (mTimedBufferQueue.isEmpty()) { | 
 | 1112 |             buffer->raw = NULL; | 
 | 1113 |             buffer->frameCount = 0; | 
 | 1114 |             return NOT_ENOUGH_DATA; | 
 | 1115 |         } | 
 | 1116 |  | 
 | 1117 |         TimedBuffer& head = mTimedBufferQueue.editItemAt(0); | 
 | 1118 |  | 
 | 1119 |         // calculate the PTS of the head of the timed buffer queue expressed in | 
 | 1120 |         // local time | 
 | 1121 |         int64_t headLocalPTS; | 
 | 1122 |         { | 
 | 1123 |             Mutex::Autolock mttLock(mMediaTimeTransformLock); | 
 | 1124 |  | 
 | 1125 |             ALOG_ASSERT(mMediaTimeTransformValid, "media time transform invalid"); | 
 | 1126 |  | 
 | 1127 |             if (mMediaTimeTransform.a_to_b_denom == 0) { | 
 | 1128 |                 // the transform represents a pause, so yield silence | 
 | 1129 |                 timedYieldSilence_l(buffer->frameCount, buffer); | 
 | 1130 |                 return NO_ERROR; | 
 | 1131 |             } | 
 | 1132 |  | 
 | 1133 |             int64_t transformedPTS; | 
 | 1134 |             if (!mMediaTimeTransform.doForwardTransform(head.pts(), | 
 | 1135 |                                                         &transformedPTS)) { | 
 | 1136 |                 // the transform failed.  this shouldn't happen, but if it does | 
 | 1137 |                 // then just drop this buffer | 
 | 1138 |                 ALOGW("timedGetNextBuffer transform failed"); | 
 | 1139 |                 buffer->raw = NULL; | 
 | 1140 |                 buffer->frameCount = 0; | 
 | 1141 |                 trimTimedBufferQueueHead_l("getNextBuffer; no transform"); | 
 | 1142 |                 return NO_ERROR; | 
 | 1143 |             } | 
 | 1144 |  | 
 | 1145 |             if (mMediaTimeTransformTarget == TimedAudioTrack::COMMON_TIME) { | 
 | 1146 |                 if (OK != mCCHelper.commonTimeToLocalTime(transformedPTS, | 
 | 1147 |                                                           &headLocalPTS)) { | 
 | 1148 |                     buffer->raw = NULL; | 
 | 1149 |                     buffer->frameCount = 0; | 
 | 1150 |                     return INVALID_OPERATION; | 
 | 1151 |                 } | 
 | 1152 |             } else { | 
 | 1153 |                 headLocalPTS = transformedPTS; | 
 | 1154 |             } | 
 | 1155 |         } | 
 | 1156 |  | 
 | 1157 |         // adjust the head buffer's PTS to reflect the portion of the head buffer | 
 | 1158 |         // that has already been consumed | 
 | 1159 |         int64_t effectivePTS = headLocalPTS + | 
 | 1160 |                 ((head.position() / mFrameSize) * mLocalTimeFreq / sampleRate()); | 
 | 1161 |  | 
 | 1162 |         // Calculate the delta in samples between the head of the input buffer | 
 | 1163 |         // queue and the start of the next output buffer that will be written. | 
 | 1164 |         // If the transformation fails because of over or underflow, it means | 
 | 1165 |         // that the sample's position in the output stream is so far out of | 
 | 1166 |         // whack that it should just be dropped. | 
 | 1167 |         int64_t sampleDelta; | 
 | 1168 |         if (llabs(effectivePTS - pts) >= (static_cast<int64_t>(1) << 31)) { | 
 | 1169 |             ALOGV("*** head buffer is too far from PTS: dropped buffer"); | 
 | 1170 |             trimTimedBufferQueueHead_l("getNextBuffer, buf pts too far from" | 
 | 1171 |                                        " mix"); | 
 | 1172 |             continue; | 
 | 1173 |         } | 
 | 1174 |         if (!mLocalTimeToSampleTransform.doForwardTransform( | 
 | 1175 |                 (effectivePTS - pts) << 32, &sampleDelta)) { | 
 | 1176 |             ALOGV("*** too late during sample rate transform: dropped buffer"); | 
 | 1177 |             trimTimedBufferQueueHead_l("getNextBuffer, bad local to sample"); | 
 | 1178 |             continue; | 
 | 1179 |         } | 
 | 1180 |  | 
 | 1181 |         ALOGVV("*** getNextBuffer head.pts=%lld head.pos=%d pts=%lld" | 
 | 1182 |                " sampleDelta=[%d.%08x]", | 
 | 1183 |                head.pts(), head.position(), pts, | 
 | 1184 |                static_cast<int32_t>((sampleDelta >= 0 ? 0 : 1) | 
 | 1185 |                    + (sampleDelta >> 32)), | 
 | 1186 |                static_cast<uint32_t>(sampleDelta & 0xFFFFFFFF)); | 
 | 1187 |  | 
 | 1188 |         // if the delta between the ideal placement for the next input sample and | 
 | 1189 |         // the current output position is within this threshold, then we will | 
 | 1190 |         // concatenate the next input samples to the previous output | 
 | 1191 |         const int64_t kSampleContinuityThreshold = | 
 | 1192 |                 (static_cast<int64_t>(sampleRate()) << 32) / 250; | 
 | 1193 |  | 
 | 1194 |         // if this is the first buffer of audio that we're emitting from this track | 
 | 1195 |         // then it should be almost exactly on time. | 
 | 1196 |         const int64_t kSampleStartupThreshold = 1LL << 32; | 
 | 1197 |  | 
 | 1198 |         if ((mTimedAudioOutputOnTime && llabs(sampleDelta) <= kSampleContinuityThreshold) || | 
 | 1199 |            (!mTimedAudioOutputOnTime && llabs(sampleDelta) <= kSampleStartupThreshold)) { | 
 | 1200 |             // the next input is close enough to being on time, so concatenate it | 
 | 1201 |             // with the last output | 
 | 1202 |             timedYieldSamples_l(buffer); | 
 | 1203 |  | 
 | 1204 |             ALOGVV("*** on time: head.pos=%d frameCount=%u", | 
 | 1205 |                     head.position(), buffer->frameCount); | 
 | 1206 |             return NO_ERROR; | 
 | 1207 |         } | 
 | 1208 |  | 
 | 1209 |         // Looks like our output is not on time.  Reset our on timed status. | 
 | 1210 |         // Next time we mix samples from our input queue, then should be within | 
 | 1211 |         // the StartupThreshold. | 
 | 1212 |         mTimedAudioOutputOnTime = false; | 
 | 1213 |         if (sampleDelta > 0) { | 
 | 1214 |             // the gap between the current output position and the proper start of | 
 | 1215 |             // the next input sample is too big, so fill it with silence | 
 | 1216 |             uint32_t framesUntilNextInput = (sampleDelta + 0x80000000) >> 32; | 
 | 1217 |  | 
 | 1218 |             timedYieldSilence_l(framesUntilNextInput, buffer); | 
 | 1219 |             ALOGV("*** silence: frameCount=%u", buffer->frameCount); | 
 | 1220 |             return NO_ERROR; | 
 | 1221 |         } else { | 
 | 1222 |             // the next input sample is late | 
 | 1223 |             uint32_t lateFrames = static_cast<uint32_t>(-((sampleDelta + 0x80000000) >> 32)); | 
 | 1224 |             size_t onTimeSamplePosition = | 
 | 1225 |                     head.position() + lateFrames * mFrameSize; | 
 | 1226 |  | 
 | 1227 |             if (onTimeSamplePosition > head.buffer()->size()) { | 
 | 1228 |                 // all the remaining samples in the head are too late, so | 
 | 1229 |                 // drop it and move on | 
 | 1230 |                 ALOGV("*** too late: dropped buffer"); | 
 | 1231 |                 trimTimedBufferQueueHead_l("getNextBuffer, dropped late buffer"); | 
 | 1232 |                 continue; | 
 | 1233 |             } else { | 
 | 1234 |                 // skip over the late samples | 
 | 1235 |                 head.setPosition(onTimeSamplePosition); | 
 | 1236 |  | 
 | 1237 |                 // yield the available samples | 
 | 1238 |                 timedYieldSamples_l(buffer); | 
 | 1239 |  | 
 | 1240 |                 ALOGV("*** late: head.pos=%d frameCount=%u", head.position(), buffer->frameCount); | 
 | 1241 |                 return NO_ERROR; | 
 | 1242 |             } | 
 | 1243 |         } | 
 | 1244 |     } | 
 | 1245 | } | 
 | 1246 |  | 
 | 1247 | // Yield samples from the timed buffer queue head up to the given output | 
 | 1248 | // buffer's capacity. | 
 | 1249 | // | 
 | 1250 | // Caller must hold mTimedBufferQueueLock | 
 | 1251 | void AudioFlinger::PlaybackThread::TimedTrack::timedYieldSamples_l( | 
 | 1252 |     AudioBufferProvider::Buffer* buffer) { | 
 | 1253 |  | 
 | 1254 |     const TimedBuffer& head = mTimedBufferQueue[0]; | 
 | 1255 |  | 
 | 1256 |     buffer->raw = (static_cast<uint8_t*>(head.buffer()->pointer()) + | 
 | 1257 |                    head.position()); | 
 | 1258 |  | 
 | 1259 |     uint32_t framesLeftInHead = ((head.buffer()->size() - head.position()) / | 
 | 1260 |                                  mFrameSize); | 
 | 1261 |     size_t framesRequested = buffer->frameCount; | 
 | 1262 |     buffer->frameCount = min(framesLeftInHead, framesRequested); | 
 | 1263 |  | 
 | 1264 |     mQueueHeadInFlight = true; | 
 | 1265 |     mTimedAudioOutputOnTime = true; | 
 | 1266 | } | 
 | 1267 |  | 
 | 1268 | // Yield samples of silence up to the given output buffer's capacity | 
 | 1269 | // | 
 | 1270 | // Caller must hold mTimedBufferQueueLock | 
 | 1271 | void AudioFlinger::PlaybackThread::TimedTrack::timedYieldSilence_l( | 
 | 1272 |     uint32_t numFrames, AudioBufferProvider::Buffer* buffer) { | 
 | 1273 |  | 
 | 1274 |     // lazily allocate a buffer filled with silence | 
 | 1275 |     if (mTimedSilenceBufferSize < numFrames * mFrameSize) { | 
 | 1276 |         delete [] mTimedSilenceBuffer; | 
 | 1277 |         mTimedSilenceBufferSize = numFrames * mFrameSize; | 
 | 1278 |         mTimedSilenceBuffer = new uint8_t[mTimedSilenceBufferSize]; | 
 | 1279 |         memset(mTimedSilenceBuffer, 0, mTimedSilenceBufferSize); | 
 | 1280 |     } | 
 | 1281 |  | 
 | 1282 |     buffer->raw = mTimedSilenceBuffer; | 
 | 1283 |     size_t framesRequested = buffer->frameCount; | 
 | 1284 |     buffer->frameCount = min(numFrames, framesRequested); | 
 | 1285 |  | 
 | 1286 |     mTimedAudioOutputOnTime = false; | 
 | 1287 | } | 
 | 1288 |  | 
 | 1289 | // AudioBufferProvider interface | 
 | 1290 | void AudioFlinger::PlaybackThread::TimedTrack::releaseBuffer( | 
 | 1291 |     AudioBufferProvider::Buffer* buffer) { | 
 | 1292 |  | 
 | 1293 |     Mutex::Autolock _l(mTimedBufferQueueLock); | 
 | 1294 |  | 
 | 1295 |     // If the buffer which was just released is part of the buffer at the head | 
 | 1296 |     // of the queue, be sure to update the amt of the buffer which has been | 
 | 1297 |     // consumed.  If the buffer being returned is not part of the head of the | 
 | 1298 |     // queue, its either because the buffer is part of the silence buffer, or | 
 | 1299 |     // because the head of the timed queue was trimmed after the mixer called | 
 | 1300 |     // getNextBuffer but before the mixer called releaseBuffer. | 
 | 1301 |     if (buffer->raw == mTimedSilenceBuffer) { | 
 | 1302 |         ALOG_ASSERT(!mQueueHeadInFlight, | 
 | 1303 |                     "Queue head in flight during release of silence buffer!"); | 
 | 1304 |         goto done; | 
 | 1305 |     } | 
 | 1306 |  | 
 | 1307 |     ALOG_ASSERT(mQueueHeadInFlight, | 
 | 1308 |                 "TimedTrack::releaseBuffer of non-silence buffer, but no queue" | 
 | 1309 |                 " head in flight."); | 
 | 1310 |  | 
 | 1311 |     if (mTimedBufferQueue.size()) { | 
 | 1312 |         TimedBuffer& head = mTimedBufferQueue.editItemAt(0); | 
 | 1313 |  | 
 | 1314 |         void* start = head.buffer()->pointer(); | 
 | 1315 |         void* end   = reinterpret_cast<void*>( | 
 | 1316 |                         reinterpret_cast<uint8_t*>(head.buffer()->pointer()) | 
 | 1317 |                         + head.buffer()->size()); | 
 | 1318 |  | 
 | 1319 |         ALOG_ASSERT((buffer->raw >= start) && (buffer->raw < end), | 
 | 1320 |                     "released buffer not within the head of the timed buffer" | 
 | 1321 |                     " queue; qHead = [%p, %p], released buffer = %p", | 
 | 1322 |                     start, end, buffer->raw); | 
 | 1323 |  | 
 | 1324 |         head.setPosition(head.position() + | 
 | 1325 |                 (buffer->frameCount * mFrameSize)); | 
 | 1326 |         mQueueHeadInFlight = false; | 
 | 1327 |  | 
 | 1328 |         ALOG_ASSERT(mFramesPendingInQueue >= buffer->frameCount, | 
 | 1329 |                     "Bad bookkeeping during releaseBuffer!  Should have at" | 
 | 1330 |                     " least %u queued frames, but we think we have only %u", | 
 | 1331 |                     buffer->frameCount, mFramesPendingInQueue); | 
 | 1332 |  | 
 | 1333 |         mFramesPendingInQueue -= buffer->frameCount; | 
 | 1334 |  | 
 | 1335 |         if ((static_cast<size_t>(head.position()) >= head.buffer()->size()) | 
 | 1336 |             || mTrimQueueHeadOnRelease) { | 
 | 1337 |             trimTimedBufferQueueHead_l("releaseBuffer"); | 
 | 1338 |             mTrimQueueHeadOnRelease = false; | 
 | 1339 |         } | 
 | 1340 |     } else { | 
 | 1341 |         LOG_FATAL("TimedTrack::releaseBuffer of non-silence buffer with no" | 
 | 1342 |                   " buffers in the timed buffer queue"); | 
 | 1343 |     } | 
 | 1344 |  | 
 | 1345 | done: | 
 | 1346 |     buffer->raw = 0; | 
 | 1347 |     buffer->frameCount = 0; | 
 | 1348 | } | 
 | 1349 |  | 
 | 1350 | size_t AudioFlinger::PlaybackThread::TimedTrack::framesReady() const { | 
 | 1351 |     Mutex::Autolock _l(mTimedBufferQueueLock); | 
 | 1352 |     return mFramesPendingInQueue; | 
 | 1353 | } | 
 | 1354 |  | 
 | 1355 | AudioFlinger::PlaybackThread::TimedTrack::TimedBuffer::TimedBuffer() | 
 | 1356 |         : mPTS(0), mPosition(0) {} | 
 | 1357 |  | 
 | 1358 | AudioFlinger::PlaybackThread::TimedTrack::TimedBuffer::TimedBuffer( | 
 | 1359 |     const sp<IMemory>& buffer, int64_t pts) | 
 | 1360 |         : mBuffer(buffer), mPTS(pts), mPosition(0) {} | 
 | 1361 |  | 
 | 1362 |  | 
 | 1363 | // ---------------------------------------------------------------------------- | 
 | 1364 |  | 
 | 1365 | AudioFlinger::PlaybackThread::OutputTrack::OutputTrack( | 
 | 1366 |             PlaybackThread *playbackThread, | 
 | 1367 |             DuplicatingThread *sourceThread, | 
 | 1368 |             uint32_t sampleRate, | 
 | 1369 |             audio_format_t format, | 
 | 1370 |             audio_channel_mask_t channelMask, | 
 | 1371 |             size_t frameCount) | 
 | 1372 |     :   Track(playbackThread, NULL, AUDIO_STREAM_CNT, sampleRate, format, channelMask, frameCount, | 
 | 1373 |                 NULL, 0, IAudioFlinger::TRACK_DEFAULT), | 
 | 1374 |     mActive(false), mSourceThread(sourceThread), mBuffers(NULL) | 
 | 1375 | { | 
 | 1376 |  | 
 | 1377 |     if (mCblk != NULL) { | 
 | 1378 |         mBuffers = (char*)mCblk + sizeof(audio_track_cblk_t); | 
 | 1379 |         mOutBuffer.frameCount = 0; | 
 | 1380 |         playbackThread->mTracks.add(this); | 
 | 1381 |         ALOGV("OutputTrack constructor mCblk %p, mBuffer %p, mBuffers %p, " \ | 
 | 1382 |                 "mCblk->frameCount %d, mCblk->sampleRate %u, mChannelMask 0x%08x mBufferEnd %p", | 
 | 1383 |                 mCblk, mBuffer, mBuffers, | 
 | 1384 |                 mCblk->frameCount, mCblk->sampleRate, mChannelMask, mBufferEnd); | 
 | 1385 |     } else { | 
 | 1386 |         ALOGW("Error creating output track on thread %p", playbackThread); | 
 | 1387 |     } | 
 | 1388 | } | 
 | 1389 |  | 
 | 1390 | AudioFlinger::PlaybackThread::OutputTrack::~OutputTrack() | 
 | 1391 | { | 
 | 1392 |     clearBufferQueue(); | 
 | 1393 | } | 
 | 1394 |  | 
 | 1395 | status_t AudioFlinger::PlaybackThread::OutputTrack::start(AudioSystem::sync_event_t event, | 
 | 1396 |                                                           int triggerSession) | 
 | 1397 | { | 
 | 1398 |     status_t status = Track::start(event, triggerSession); | 
 | 1399 |     if (status != NO_ERROR) { | 
 | 1400 |         return status; | 
 | 1401 |     } | 
 | 1402 |  | 
 | 1403 |     mActive = true; | 
 | 1404 |     mRetryCount = 127; | 
 | 1405 |     return status; | 
 | 1406 | } | 
 | 1407 |  | 
 | 1408 | void AudioFlinger::PlaybackThread::OutputTrack::stop() | 
 | 1409 | { | 
 | 1410 |     Track::stop(); | 
 | 1411 |     clearBufferQueue(); | 
 | 1412 |     mOutBuffer.frameCount = 0; | 
 | 1413 |     mActive = false; | 
 | 1414 | } | 
 | 1415 |  | 
 | 1416 | bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t frames) | 
 | 1417 | { | 
 | 1418 |     Buffer *pInBuffer; | 
 | 1419 |     Buffer inBuffer; | 
 | 1420 |     uint32_t channelCount = mChannelCount; | 
 | 1421 |     bool outputBufferFull = false; | 
 | 1422 |     inBuffer.frameCount = frames; | 
 | 1423 |     inBuffer.i16 = data; | 
 | 1424 |  | 
 | 1425 |     uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs(); | 
 | 1426 |  | 
 | 1427 |     if (!mActive && frames != 0) { | 
 | 1428 |         start(); | 
 | 1429 |         sp<ThreadBase> thread = mThread.promote(); | 
 | 1430 |         if (thread != 0) { | 
 | 1431 |             MixerThread *mixerThread = (MixerThread *)thread.get(); | 
 | 1432 |             if (mFrameCount > frames) { | 
 | 1433 |                 if (mBufferQueue.size() < kMaxOverFlowBuffers) { | 
 | 1434 |                     uint32_t startFrames = (mFrameCount - frames); | 
 | 1435 |                     pInBuffer = new Buffer; | 
 | 1436 |                     pInBuffer->mBuffer = new int16_t[startFrames * channelCount]; | 
 | 1437 |                     pInBuffer->frameCount = startFrames; | 
 | 1438 |                     pInBuffer->i16 = pInBuffer->mBuffer; | 
 | 1439 |                     memset(pInBuffer->raw, 0, startFrames * channelCount * sizeof(int16_t)); | 
 | 1440 |                     mBufferQueue.add(pInBuffer); | 
 | 1441 |                 } else { | 
 | 1442 |                     ALOGW ("OutputTrack::write() %p no more buffers in queue", this); | 
 | 1443 |                 } | 
 | 1444 |             } | 
 | 1445 |         } | 
 | 1446 |     } | 
 | 1447 |  | 
 | 1448 |     while (waitTimeLeftMs) { | 
 | 1449 |         // First write pending buffers, then new data | 
 | 1450 |         if (mBufferQueue.size()) { | 
 | 1451 |             pInBuffer = mBufferQueue.itemAt(0); | 
 | 1452 |         } else { | 
 | 1453 |             pInBuffer = &inBuffer; | 
 | 1454 |         } | 
 | 1455 |  | 
 | 1456 |         if (pInBuffer->frameCount == 0) { | 
 | 1457 |             break; | 
 | 1458 |         } | 
 | 1459 |  | 
 | 1460 |         if (mOutBuffer.frameCount == 0) { | 
 | 1461 |             mOutBuffer.frameCount = pInBuffer->frameCount; | 
 | 1462 |             nsecs_t startTime = systemTime(); | 
 | 1463 |             if (obtainBuffer(&mOutBuffer, waitTimeLeftMs) == (status_t)NO_MORE_BUFFERS) { | 
 | 1464 |                 ALOGV ("OutputTrack::write() %p thread %p no more output buffers", this, | 
 | 1465 |                         mThread.unsafe_get()); | 
 | 1466 |                 outputBufferFull = true; | 
 | 1467 |                 break; | 
 | 1468 |             } | 
 | 1469 |             uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime); | 
 | 1470 |             if (waitTimeLeftMs >= waitTimeMs) { | 
 | 1471 |                 waitTimeLeftMs -= waitTimeMs; | 
 | 1472 |             } else { | 
 | 1473 |                 waitTimeLeftMs = 0; | 
 | 1474 |             } | 
 | 1475 |         } | 
 | 1476 |  | 
 | 1477 |         uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount : | 
 | 1478 |                 pInBuffer->frameCount; | 
 | 1479 |         memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * channelCount * sizeof(int16_t)); | 
 | 1480 |         mCblk->stepUserOut(outFrames, mFrameCount); | 
 | 1481 |         pInBuffer->frameCount -= outFrames; | 
 | 1482 |         pInBuffer->i16 += outFrames * channelCount; | 
 | 1483 |         mOutBuffer.frameCount -= outFrames; | 
 | 1484 |         mOutBuffer.i16 += outFrames * channelCount; | 
 | 1485 |  | 
 | 1486 |         if (pInBuffer->frameCount == 0) { | 
 | 1487 |             if (mBufferQueue.size()) { | 
 | 1488 |                 mBufferQueue.removeAt(0); | 
 | 1489 |                 delete [] pInBuffer->mBuffer; | 
 | 1490 |                 delete pInBuffer; | 
 | 1491 |                 ALOGV("OutputTrack::write() %p thread %p released overflow buffer %d", this, | 
 | 1492 |                         mThread.unsafe_get(), mBufferQueue.size()); | 
 | 1493 |             } else { | 
 | 1494 |                 break; | 
 | 1495 |             } | 
 | 1496 |         } | 
 | 1497 |     } | 
 | 1498 |  | 
 | 1499 |     // If we could not write all frames, allocate a buffer and queue it for next time. | 
 | 1500 |     if (inBuffer.frameCount) { | 
 | 1501 |         sp<ThreadBase> thread = mThread.promote(); | 
 | 1502 |         if (thread != 0 && !thread->standby()) { | 
 | 1503 |             if (mBufferQueue.size() < kMaxOverFlowBuffers) { | 
 | 1504 |                 pInBuffer = new Buffer; | 
 | 1505 |                 pInBuffer->mBuffer = new int16_t[inBuffer.frameCount * channelCount]; | 
 | 1506 |                 pInBuffer->frameCount = inBuffer.frameCount; | 
 | 1507 |                 pInBuffer->i16 = pInBuffer->mBuffer; | 
 | 1508 |                 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * channelCount * | 
 | 1509 |                         sizeof(int16_t)); | 
 | 1510 |                 mBufferQueue.add(pInBuffer); | 
 | 1511 |                 ALOGV("OutputTrack::write() %p thread %p adding overflow buffer %d", this, | 
 | 1512 |                         mThread.unsafe_get(), mBufferQueue.size()); | 
 | 1513 |             } else { | 
 | 1514 |                 ALOGW("OutputTrack::write() %p thread %p no more overflow buffers", | 
 | 1515 |                         mThread.unsafe_get(), this); | 
 | 1516 |             } | 
 | 1517 |         } | 
 | 1518 |     } | 
 | 1519 |  | 
 | 1520 |     // Calling write() with a 0 length buffer, means that no more data will be written: | 
 | 1521 |     // If no more buffers are pending, fill output track buffer to make sure it is started | 
 | 1522 |     // by output mixer. | 
 | 1523 |     if (frames == 0 && mBufferQueue.size() == 0) { | 
 | 1524 |         if (mCblk->user < mFrameCount) { | 
 | 1525 |             frames = mFrameCount - mCblk->user; | 
 | 1526 |             pInBuffer = new Buffer; | 
 | 1527 |             pInBuffer->mBuffer = new int16_t[frames * channelCount]; | 
 | 1528 |             pInBuffer->frameCount = frames; | 
 | 1529 |             pInBuffer->i16 = pInBuffer->mBuffer; | 
 | 1530 |             memset(pInBuffer->raw, 0, frames * channelCount * sizeof(int16_t)); | 
 | 1531 |             mBufferQueue.add(pInBuffer); | 
 | 1532 |         } else if (mActive) { | 
 | 1533 |             stop(); | 
 | 1534 |         } | 
 | 1535 |     } | 
 | 1536 |  | 
 | 1537 |     return outputBufferFull; | 
 | 1538 | } | 
 | 1539 |  | 
 | 1540 | status_t AudioFlinger::PlaybackThread::OutputTrack::obtainBuffer( | 
 | 1541 |         AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs) | 
 | 1542 | { | 
 | 1543 |     int active; | 
 | 1544 |     status_t result; | 
 | 1545 |     audio_track_cblk_t* cblk = mCblk; | 
 | 1546 |     uint32_t framesReq = buffer->frameCount; | 
 | 1547 |  | 
 | 1548 |     ALOGVV("OutputTrack::obtainBuffer user %d, server %d", cblk->user, cblk->server); | 
 | 1549 |     buffer->frameCount  = 0; | 
 | 1550 |  | 
 | 1551 |     uint32_t framesAvail = cblk->framesAvailableOut(mFrameCount); | 
 | 1552 |  | 
 | 1553 |  | 
 | 1554 |     if (framesAvail == 0) { | 
 | 1555 |         Mutex::Autolock _l(cblk->lock); | 
 | 1556 |         goto start_loop_here; | 
 | 1557 |         while (framesAvail == 0) { | 
 | 1558 |             active = mActive; | 
 | 1559 |             if (CC_UNLIKELY(!active)) { | 
 | 1560 |                 ALOGV("Not active and NO_MORE_BUFFERS"); | 
 | 1561 |                 return NO_MORE_BUFFERS; | 
 | 1562 |             } | 
 | 1563 |             result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs)); | 
 | 1564 |             if (result != NO_ERROR) { | 
 | 1565 |                 return NO_MORE_BUFFERS; | 
 | 1566 |             } | 
 | 1567 |             // read the server count again | 
 | 1568 |         start_loop_here: | 
 | 1569 |             framesAvail = cblk->framesAvailableOut_l(mFrameCount); | 
 | 1570 |         } | 
 | 1571 |     } | 
 | 1572 |  | 
 | 1573 | //    if (framesAvail < framesReq) { | 
 | 1574 | //        return NO_MORE_BUFFERS; | 
 | 1575 | //    } | 
 | 1576 |  | 
 | 1577 |     if (framesReq > framesAvail) { | 
 | 1578 |         framesReq = framesAvail; | 
 | 1579 |     } | 
 | 1580 |  | 
 | 1581 |     uint32_t u = cblk->user; | 
 | 1582 |     uint32_t bufferEnd = cblk->userBase + mFrameCount; | 
 | 1583 |  | 
 | 1584 |     if (framesReq > bufferEnd - u) { | 
 | 1585 |         framesReq = bufferEnd - u; | 
 | 1586 |     } | 
 | 1587 |  | 
 | 1588 |     buffer->frameCount  = framesReq; | 
 | 1589 |     buffer->raw         = cblk->buffer(mBuffers, mFrameSize, u); | 
 | 1590 |     return NO_ERROR; | 
 | 1591 | } | 
 | 1592 |  | 
 | 1593 |  | 
 | 1594 | void AudioFlinger::PlaybackThread::OutputTrack::clearBufferQueue() | 
 | 1595 | { | 
 | 1596 |     size_t size = mBufferQueue.size(); | 
 | 1597 |  | 
 | 1598 |     for (size_t i = 0; i < size; i++) { | 
 | 1599 |         Buffer *pBuffer = mBufferQueue.itemAt(i); | 
 | 1600 |         delete [] pBuffer->mBuffer; | 
 | 1601 |         delete pBuffer; | 
 | 1602 |     } | 
 | 1603 |     mBufferQueue.clear(); | 
 | 1604 | } | 
 | 1605 |  | 
 | 1606 |  | 
 | 1607 | // ---------------------------------------------------------------------------- | 
 | 1608 | //      Record | 
 | 1609 | // ---------------------------------------------------------------------------- | 
 | 1610 |  | 
 | 1611 | AudioFlinger::RecordHandle::RecordHandle( | 
 | 1612 |         const sp<AudioFlinger::RecordThread::RecordTrack>& recordTrack) | 
 | 1613 |     : BnAudioRecord(), | 
 | 1614 |     mRecordTrack(recordTrack) | 
 | 1615 | { | 
 | 1616 | } | 
 | 1617 |  | 
 | 1618 | AudioFlinger::RecordHandle::~RecordHandle() { | 
 | 1619 |     stop_nonvirtual(); | 
 | 1620 |     mRecordTrack->destroy(); | 
 | 1621 | } | 
 | 1622 |  | 
 | 1623 | sp<IMemory> AudioFlinger::RecordHandle::getCblk() const { | 
 | 1624 |     return mRecordTrack->getCblk(); | 
 | 1625 | } | 
 | 1626 |  | 
 | 1627 | status_t AudioFlinger::RecordHandle::start(int /*AudioSystem::sync_event_t*/ event, | 
 | 1628 |         int triggerSession) { | 
 | 1629 |     ALOGV("RecordHandle::start()"); | 
 | 1630 |     return mRecordTrack->start((AudioSystem::sync_event_t)event, triggerSession); | 
 | 1631 | } | 
 | 1632 |  | 
 | 1633 | void AudioFlinger::RecordHandle::stop() { | 
 | 1634 |     stop_nonvirtual(); | 
 | 1635 | } | 
 | 1636 |  | 
 | 1637 | void AudioFlinger::RecordHandle::stop_nonvirtual() { | 
 | 1638 |     ALOGV("RecordHandle::stop()"); | 
 | 1639 |     mRecordTrack->stop(); | 
 | 1640 | } | 
 | 1641 |  | 
 | 1642 | status_t AudioFlinger::RecordHandle::onTransact( | 
 | 1643 |     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) | 
 | 1644 | { | 
 | 1645 |     return BnAudioRecord::onTransact(code, data, reply, flags); | 
 | 1646 | } | 
 | 1647 |  | 
 | 1648 | // ---------------------------------------------------------------------------- | 
 | 1649 |  | 
 | 1650 | // RecordTrack constructor must be called with AudioFlinger::mLock held | 
 | 1651 | AudioFlinger::RecordThread::RecordTrack::RecordTrack( | 
 | 1652 |             RecordThread *thread, | 
 | 1653 |             const sp<Client>& client, | 
 | 1654 |             uint32_t sampleRate, | 
 | 1655 |             audio_format_t format, | 
 | 1656 |             audio_channel_mask_t channelMask, | 
 | 1657 |             size_t frameCount, | 
 | 1658 |             int sessionId) | 
 | 1659 |     :   TrackBase(thread, client, sampleRate, format, | 
 | 1660 |                   channelMask, frameCount, 0 /*sharedBuffer*/, sessionId), | 
 | 1661 |         mOverflow(false) | 
 | 1662 | { | 
 | 1663 |     ALOGV("RecordTrack constructor, size %d", (int)mBufferEnd - (int)mBuffer); | 
 | 1664 | } | 
 | 1665 |  | 
 | 1666 | AudioFlinger::RecordThread::RecordTrack::~RecordTrack() | 
 | 1667 | { | 
 | 1668 |     ALOGV("%s", __func__); | 
 | 1669 | } | 
 | 1670 |  | 
 | 1671 | // AudioBufferProvider interface | 
 | 1672 | status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer, | 
 | 1673 |         int64_t pts) | 
 | 1674 | { | 
 | 1675 |     audio_track_cblk_t* cblk = this->cblk(); | 
 | 1676 |     uint32_t framesAvail; | 
 | 1677 |     uint32_t framesReq = buffer->frameCount; | 
 | 1678 |  | 
 | 1679 |     // Check if last stepServer failed, try to step now | 
 | 1680 |     if (mStepServerFailed) { | 
 | 1681 |         if (!step()) { | 
 | 1682 |             goto getNextBuffer_exit; | 
 | 1683 |         } | 
 | 1684 |         ALOGV("stepServer recovered"); | 
 | 1685 |         mStepServerFailed = false; | 
 | 1686 |     } | 
 | 1687 |  | 
 | 1688 |     // FIXME lock is not actually held, so overrun is possible | 
 | 1689 |     framesAvail = cblk->framesAvailableIn_l(mFrameCount); | 
 | 1690 |  | 
 | 1691 |     if (CC_LIKELY(framesAvail)) { | 
 | 1692 |         uint32_t s = cblk->server; | 
 | 1693 |         uint32_t bufferEnd = cblk->serverBase + mFrameCount; | 
 | 1694 |  | 
 | 1695 |         if (framesReq > framesAvail) { | 
 | 1696 |             framesReq = framesAvail; | 
 | 1697 |         } | 
 | 1698 |         if (framesReq > bufferEnd - s) { | 
 | 1699 |             framesReq = bufferEnd - s; | 
 | 1700 |         } | 
 | 1701 |  | 
 | 1702 |         buffer->raw = getBuffer(s, framesReq); | 
 | 1703 |         buffer->frameCount = framesReq; | 
 | 1704 |         return NO_ERROR; | 
 | 1705 |     } | 
 | 1706 |  | 
 | 1707 | getNextBuffer_exit: | 
 | 1708 |     buffer->raw = NULL; | 
 | 1709 |     buffer->frameCount = 0; | 
 | 1710 |     return NOT_ENOUGH_DATA; | 
 | 1711 | } | 
 | 1712 |  | 
 | 1713 | status_t AudioFlinger::RecordThread::RecordTrack::start(AudioSystem::sync_event_t event, | 
 | 1714 |                                                         int triggerSession) | 
 | 1715 | { | 
 | 1716 |     sp<ThreadBase> thread = mThread.promote(); | 
 | 1717 |     if (thread != 0) { | 
 | 1718 |         RecordThread *recordThread = (RecordThread *)thread.get(); | 
 | 1719 |         return recordThread->start(this, event, triggerSession); | 
 | 1720 |     } else { | 
 | 1721 |         return BAD_VALUE; | 
 | 1722 |     } | 
 | 1723 | } | 
 | 1724 |  | 
 | 1725 | void AudioFlinger::RecordThread::RecordTrack::stop() | 
 | 1726 | { | 
 | 1727 |     sp<ThreadBase> thread = mThread.promote(); | 
 | 1728 |     if (thread != 0) { | 
 | 1729 |         RecordThread *recordThread = (RecordThread *)thread.get(); | 
 | 1730 |         recordThread->mLock.lock(); | 
 | 1731 |         bool doStop = recordThread->stop_l(this); | 
 | 1732 |         if (doStop) { | 
 | 1733 |             TrackBase::reset(); | 
 | 1734 |             // Force overrun condition to avoid false overrun callback until first data is | 
 | 1735 |             // read from buffer | 
 | 1736 |             android_atomic_or(CBLK_UNDERRUN, &mCblk->flags); | 
 | 1737 |         } | 
 | 1738 |         recordThread->mLock.unlock(); | 
 | 1739 |         if (doStop) { | 
 | 1740 |             AudioSystem::stopInput(recordThread->id()); | 
 | 1741 |         } | 
 | 1742 |     } | 
 | 1743 | } | 
 | 1744 |  | 
 | 1745 | void AudioFlinger::RecordThread::RecordTrack::destroy() | 
 | 1746 | { | 
 | 1747 |     // see comments at AudioFlinger::PlaybackThread::Track::destroy() | 
 | 1748 |     sp<RecordTrack> keep(this); | 
 | 1749 |     { | 
 | 1750 |         sp<ThreadBase> thread = mThread.promote(); | 
 | 1751 |         if (thread != 0) { | 
 | 1752 |             if (mState == ACTIVE || mState == RESUMING) { | 
 | 1753 |                 AudioSystem::stopInput(thread->id()); | 
 | 1754 |             } | 
 | 1755 |             AudioSystem::releaseInput(thread->id()); | 
 | 1756 |             Mutex::Autolock _l(thread->mLock); | 
 | 1757 |             RecordThread *recordThread = (RecordThread *) thread.get(); | 
 | 1758 |             recordThread->destroyTrack_l(this); | 
 | 1759 |         } | 
 | 1760 |     } | 
 | 1761 | } | 
 | 1762 |  | 
 | 1763 |  | 
 | 1764 | /*static*/ void AudioFlinger::RecordThread::RecordTrack::appendDumpHeader(String8& result) | 
 | 1765 | { | 
 | 1766 |     result.append("   Clien Fmt Chn mask   Session Step S SRate  Serv     User   FrameCount\n"); | 
 | 1767 | } | 
 | 1768 |  | 
 | 1769 | void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size) | 
 | 1770 | { | 
 | 1771 |     snprintf(buffer, size, "   %05d %03u 0x%08x %05d   %04u %01d %05u  %08x %08x %05d\n", | 
 | 1772 |             (mClient == 0) ? getpid_cached : mClient->pid(), | 
 | 1773 |             mFormat, | 
 | 1774 |             mChannelMask, | 
 | 1775 |             mSessionId, | 
 | 1776 |             mStepCount, | 
 | 1777 |             mState, | 
 | 1778 |             mCblk->sampleRate, | 
 | 1779 |             mCblk->server, | 
 | 1780 |             mCblk->user, | 
 | 1781 |             mFrameCount); | 
 | 1782 | } | 
 | 1783 |  | 
 | 1784 | bool AudioFlinger::RecordThread::RecordTrack::isOut() const | 
 | 1785 | { | 
 | 1786 |     return false; | 
 | 1787 | } | 
 | 1788 |  | 
 | 1789 | }; // namespace android |