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