Tracks.cpp revision 30d48d9542fb3f85889108c1ee2daff98a4860e7
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 "Configuration.h"
23#include <linux/futex.h>
24#include <math.h>
25#include <sys/syscall.h>
26#include <utils/Log.h>
27
28#include <private/media/AudioTrackShared.h>
29
30#include "AudioFlinger.h"
31#include "ServiceUtilities.h"
32
33#include <media/nbaio/Pipe.h>
34#include <media/nbaio/PipeReader.h>
35#include <media/RecordBufferConverter.h>
36#include <audio_utils/minifloat.h>
37
38// ----------------------------------------------------------------------------
39
40// Note: the following macro is used for extremely verbose logging message.  In
41// order to run with ALOG_ASSERT turned on, we need to have LOG_NDEBUG set to
42// 0; but one side effect of this is to turn all LOGV's as well.  Some messages
43// are so verbose that we want to suppress them even when we have ALOG_ASSERT
44// turned on.  Do not uncomment the #def below unless you really know what you
45// are doing and want to see all of the extremely verbose messages.
46//#define VERY_VERY_VERBOSE_LOGGING
47#ifdef VERY_VERY_VERBOSE_LOGGING
48#define ALOGVV ALOGV
49#else
50#define ALOGVV(a...) do { } while(0)
51#endif
52
53// TODO move to a common header  (Also shared with AudioTrack.cpp)
54#define NANOS_PER_SECOND    1000000000
55#define TIME_TO_NANOS(time) ((uint64_t)(time).tv_sec * NANOS_PER_SECOND + (time).tv_nsec)
56
57namespace android {
58
59// ----------------------------------------------------------------------------
60//      TrackBase
61// ----------------------------------------------------------------------------
62
63static volatile int32_t nextTrackId = 55;
64
65// TrackBase constructor must be called with AudioFlinger::mLock held
66AudioFlinger::ThreadBase::TrackBase::TrackBase(
67            ThreadBase *thread,
68            const sp<Client>& client,
69            uint32_t sampleRate,
70            audio_format_t format,
71            audio_channel_mask_t channelMask,
72            size_t frameCount,
73            void *buffer,
74            audio_session_t sessionId,
75            uid_t clientUid,
76            bool isOut,
77            alloc_type alloc,
78            track_type type,
79            audio_port_handle_t portId)
80    :   RefBase(),
81        mThread(thread),
82        mClient(client),
83        mCblk(NULL),
84        // mBuffer
85        mState(IDLE),
86        mSampleRate(sampleRate),
87        mFormat(format),
88        mChannelMask(channelMask),
89        mChannelCount(isOut ?
90                audio_channel_count_from_out_mask(channelMask) :
91                audio_channel_count_from_in_mask(channelMask)),
92        mFrameSize(audio_has_proportional_frames(format) ?
93                mChannelCount * audio_bytes_per_sample(format) : sizeof(int8_t)),
94        mFrameCount(frameCount),
95        mSessionId(sessionId),
96        mIsOut(isOut),
97        mId(android_atomic_inc(&nextTrackId)),
98        mTerminated(false),
99        mType(type),
100        mThreadIoHandle(thread->id()),
101        mPortId(portId),
102        mIsInvalid(false)
103{
104    const uid_t callingUid = IPCThreadState::self()->getCallingUid();
105    if (!isTrustedCallingUid(callingUid) || clientUid == AUDIO_UID_INVALID) {
106        ALOGW_IF(clientUid != AUDIO_UID_INVALID && clientUid != callingUid,
107                "%s uid %d tried to pass itself off as %d", __FUNCTION__, callingUid, clientUid);
108        clientUid = callingUid;
109    }
110    // clientUid contains the uid of the app that is responsible for this track, so we can blame
111    // battery usage on it.
112    mUid = clientUid;
113
114    // ALOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
115    size_t size = sizeof(audio_track_cblk_t);
116    size_t bufferSize = (buffer == NULL ? roundup(frameCount) : frameCount) * mFrameSize;
117    if (buffer == NULL && alloc == ALLOC_CBLK) {
118        size += bufferSize;
119    }
120
121    if (client != 0) {
122        mCblkMemory = client->heap()->allocate(size);
123        if (mCblkMemory == 0 ||
124                (mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer())) == NULL) {
125            ALOGE("not enough memory for AudioTrack size=%zu", size);
126            client->heap()->dump("AudioTrack");
127            mCblkMemory.clear();
128            return;
129        }
130    } else {
131        // this syntax avoids calling the audio_track_cblk_t constructor twice
132        mCblk = (audio_track_cblk_t *) new uint8_t[size];
133        // assume mCblk != NULL
134    }
135
136    // construct the shared structure in-place.
137    if (mCblk != NULL) {
138        new(mCblk) audio_track_cblk_t();
139        switch (alloc) {
140        case ALLOC_READONLY: {
141            const sp<MemoryDealer> roHeap(thread->readOnlyHeap());
142            if (roHeap == 0 ||
143                    (mBufferMemory = roHeap->allocate(bufferSize)) == 0 ||
144                    (mBuffer = mBufferMemory->pointer()) == NULL) {
145                ALOGE("not enough memory for read-only buffer size=%zu", bufferSize);
146                if (roHeap != 0) {
147                    roHeap->dump("buffer");
148                }
149                mCblkMemory.clear();
150                mBufferMemory.clear();
151                return;
152            }
153            memset(mBuffer, 0, bufferSize);
154            } break;
155        case ALLOC_PIPE:
156            mBufferMemory = thread->pipeMemory();
157            // mBuffer is the virtual address as seen from current process (mediaserver),
158            // and should normally be coming from mBufferMemory->pointer().
159            // However in this case the TrackBase does not reference the buffer directly.
160            // It should references the buffer via the pipe.
161            // Therefore, to detect incorrect usage of the buffer, we set mBuffer to NULL.
162            mBuffer = NULL;
163            break;
164        case ALLOC_CBLK:
165            // clear all buffers
166            if (buffer == NULL) {
167                mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
168                memset(mBuffer, 0, bufferSize);
169            } else {
170                mBuffer = buffer;
171#if 0
172                mCblk->mFlags = CBLK_FORCEREADY;    // FIXME hack, need to fix the track ready logic
173#endif
174            }
175            break;
176        case ALLOC_LOCAL:
177            mBuffer = calloc(1, bufferSize);
178            break;
179        case ALLOC_NONE:
180            mBuffer = buffer;
181            break;
182        }
183
184#ifdef TEE_SINK
185        if (mTeeSinkTrackEnabled) {
186            NBAIO_Format pipeFormat = Format_from_SR_C(mSampleRate, mChannelCount, mFormat);
187            if (Format_isValid(pipeFormat)) {
188                Pipe *pipe = new Pipe(mTeeSinkTrackFrames, pipeFormat);
189                size_t numCounterOffers = 0;
190                const NBAIO_Format offers[1] = {pipeFormat};
191                ssize_t index = pipe->negotiate(offers, 1, NULL, numCounterOffers);
192                ALOG_ASSERT(index == 0);
193                PipeReader *pipeReader = new PipeReader(*pipe);
194                numCounterOffers = 0;
195                index = pipeReader->negotiate(offers, 1, NULL, numCounterOffers);
196                ALOG_ASSERT(index == 0);
197                mTeeSink = pipe;
198                mTeeSource = pipeReader;
199            }
200        }
201#endif
202
203    }
204}
205
206status_t AudioFlinger::ThreadBase::TrackBase::initCheck() const
207{
208    status_t status;
209    if (mType == TYPE_OUTPUT || mType == TYPE_PATCH) {
210        status = cblk() != NULL ? NO_ERROR : NO_MEMORY;
211    } else {
212        status = getCblk() != 0 ? NO_ERROR : NO_MEMORY;
213    }
214    return status;
215}
216
217AudioFlinger::ThreadBase::TrackBase::~TrackBase()
218{
219#ifdef TEE_SINK
220    dumpTee(-1, mTeeSource, mId);
221#endif
222    // delete the proxy before deleting the shared memory it refers to, to avoid dangling reference
223    mServerProxy.clear();
224    if (mCblk != NULL) {
225        if (mClient == 0) {
226            delete mCblk;
227        } else {
228            mCblk->~audio_track_cblk_t();   // destroy our shared-structure.
229        }
230    }
231    mCblkMemory.clear();    // free the shared memory before releasing the heap it belongs to
232    if (mClient != 0) {
233        // Client destructor must run with AudioFlinger client mutex locked
234        Mutex::Autolock _l(mClient->audioFlinger()->mClientLock);
235        // If the client's reference count drops to zero, the associated destructor
236        // must run with AudioFlinger lock held. Thus the explicit clear() rather than
237        // relying on the automatic clear() at end of scope.
238        mClient.clear();
239    }
240    // flush the binder command buffer
241    IPCThreadState::self()->flushCommands();
242}
243
244// AudioBufferProvider interface
245// getNextBuffer() = 0;
246// This implementation of releaseBuffer() is used by Track and RecordTrack
247void AudioFlinger::ThreadBase::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
248{
249#ifdef TEE_SINK
250    if (mTeeSink != 0) {
251        (void) mTeeSink->write(buffer->raw, buffer->frameCount);
252    }
253#endif
254
255    ServerProxy::Buffer buf;
256    buf.mFrameCount = buffer->frameCount;
257    buf.mRaw = buffer->raw;
258    buffer->frameCount = 0;
259    buffer->raw = NULL;
260    mServerProxy->releaseBuffer(&buf);
261}
262
263status_t AudioFlinger::ThreadBase::TrackBase::setSyncEvent(const sp<SyncEvent>& event)
264{
265    mSyncEvents.add(event);
266    return NO_ERROR;
267}
268
269// ----------------------------------------------------------------------------
270//      Playback
271// ----------------------------------------------------------------------------
272
273AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::PlaybackThread::Track>& track)
274    : BnAudioTrack(),
275      mTrack(track)
276{
277}
278
279AudioFlinger::TrackHandle::~TrackHandle() {
280    // just stop the track on deletion, associated resources
281    // will be freed from the main thread once all pending buffers have
282    // been played. Unless it's not in the active track list, in which
283    // case we free everything now...
284    mTrack->destroy();
285}
286
287sp<IMemory> AudioFlinger::TrackHandle::getCblk() const {
288    return mTrack->getCblk();
289}
290
291status_t AudioFlinger::TrackHandle::start() {
292    return mTrack->start();
293}
294
295void AudioFlinger::TrackHandle::stop() {
296    mTrack->stop();
297}
298
299void AudioFlinger::TrackHandle::flush() {
300    mTrack->flush();
301}
302
303void AudioFlinger::TrackHandle::pause() {
304    mTrack->pause();
305}
306
307status_t AudioFlinger::TrackHandle::attachAuxEffect(int EffectId)
308{
309    return mTrack->attachAuxEffect(EffectId);
310}
311
312status_t AudioFlinger::TrackHandle::setParameters(const String8& keyValuePairs) {
313    return mTrack->setParameters(keyValuePairs);
314}
315
316VolumeShaper::Status AudioFlinger::TrackHandle::applyVolumeShaper(
317        const sp<VolumeShaper::Configuration>& configuration,
318        const sp<VolumeShaper::Operation>& operation) {
319    return mTrack->applyVolumeShaper(configuration, operation);
320}
321
322sp<VolumeShaper::State> AudioFlinger::TrackHandle::getVolumeShaperState(int id) {
323    return mTrack->getVolumeShaperState(id);
324}
325
326status_t AudioFlinger::TrackHandle::getTimestamp(AudioTimestamp& timestamp)
327{
328    return mTrack->getTimestamp(timestamp);
329}
330
331
332void AudioFlinger::TrackHandle::signal()
333{
334    return mTrack->signal();
335}
336
337status_t AudioFlinger::TrackHandle::onTransact(
338    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
339{
340    return BnAudioTrack::onTransact(code, data, reply, flags);
341}
342
343// ----------------------------------------------------------------------------
344
345// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
346AudioFlinger::PlaybackThread::Track::Track(
347            PlaybackThread *thread,
348            const sp<Client>& client,
349            audio_stream_type_t streamType,
350            uint32_t sampleRate,
351            audio_format_t format,
352            audio_channel_mask_t channelMask,
353            size_t frameCount,
354            void *buffer,
355            const sp<IMemory>& sharedBuffer,
356            audio_session_t sessionId,
357            uid_t uid,
358            audio_output_flags_t flags,
359            track_type type,
360            audio_port_handle_t portId)
361    :   TrackBase(thread, client, sampleRate, format, channelMask, frameCount,
362                  (sharedBuffer != 0) ? sharedBuffer->pointer() : buffer,
363                  sessionId, uid, true /*isOut*/,
364                  (type == TYPE_PATCH) ? ( buffer == NULL ? ALLOC_LOCAL : ALLOC_NONE) : ALLOC_CBLK,
365                  type, portId),
366    mFillingUpStatus(FS_INVALID),
367    // mRetryCount initialized later when needed
368    mSharedBuffer(sharedBuffer),
369    mStreamType(streamType),
370    mName(-1),  // see note below
371    mMainBuffer(thread->mixBuffer()),
372    mAuxBuffer(NULL),
373    mAuxEffectId(0), mHasVolumeController(false),
374    mPresentationCompleteFrames(0),
375    mFrameMap(16 /* sink-frame-to-track-frame map memory */),
376    mVolumeHandler(new VolumeHandler(sampleRate)),
377    // mSinkTimestamp
378    mFastIndex(-1),
379    mCachedVolume(1.0),
380    mResumeToStopping(false),
381    mFlushHwPending(false),
382    mFlags(flags)
383{
384    // client == 0 implies sharedBuffer == 0
385    ALOG_ASSERT(!(client == 0 && sharedBuffer != 0));
386
387    ALOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %zu", sharedBuffer->pointer(),
388            sharedBuffer->size());
389
390    if (mCblk == NULL) {
391        return;
392    }
393
394    if (sharedBuffer == 0) {
395        mAudioTrackServerProxy = new AudioTrackServerProxy(mCblk, mBuffer, frameCount,
396                mFrameSize, !isExternalTrack(), sampleRate);
397    } else {
398        mAudioTrackServerProxy = new StaticAudioTrackServerProxy(mCblk, mBuffer, frameCount,
399                mFrameSize);
400    }
401    mServerProxy = mAudioTrackServerProxy;
402
403    mName = thread->getTrackName_l(channelMask, format, sessionId, uid);
404    if (mName < 0) {
405        ALOGE("no more track names available");
406        return;
407    }
408    // only allocate a fast track index if we were able to allocate a normal track name
409    if (flags & AUDIO_OUTPUT_FLAG_FAST) {
410        // FIXME: Not calling framesReadyIsCalledByMultipleThreads() exposes a potential
411        // race with setSyncEvent(). However, if we call it, we cannot properly start
412        // static fast tracks (SoundPool) immediately after stopping.
413        //mAudioTrackServerProxy->framesReadyIsCalledByMultipleThreads();
414        ALOG_ASSERT(thread->mFastTrackAvailMask != 0);
415        int i = __builtin_ctz(thread->mFastTrackAvailMask);
416        ALOG_ASSERT(0 < i && i < (int)FastMixerState::sMaxFastTracks);
417        // FIXME This is too eager.  We allocate a fast track index before the
418        //       fast track becomes active.  Since fast tracks are a scarce resource,
419        //       this means we are potentially denying other more important fast tracks from
420        //       being created.  It would be better to allocate the index dynamically.
421        mFastIndex = i;
422        thread->mFastTrackAvailMask &= ~(1 << i);
423    }
424}
425
426AudioFlinger::PlaybackThread::Track::~Track()
427{
428    ALOGV("PlaybackThread::Track destructor");
429
430    // The destructor would clear mSharedBuffer,
431    // but it will not push the decremented reference count,
432    // leaving the client's IMemory dangling indefinitely.
433    // This prevents that leak.
434    if (mSharedBuffer != 0) {
435        mSharedBuffer.clear();
436    }
437}
438
439status_t AudioFlinger::PlaybackThread::Track::initCheck() const
440{
441    status_t status = TrackBase::initCheck();
442    if (status == NO_ERROR && mName < 0) {
443        status = NO_MEMORY;
444    }
445    return status;
446}
447
448void AudioFlinger::PlaybackThread::Track::destroy()
449{
450    // NOTE: destroyTrack_l() can remove a strong reference to this Track
451    // by removing it from mTracks vector, so there is a risk that this Tracks's
452    // destructor is called. As the destructor needs to lock mLock,
453    // we must acquire a strong reference on this Track before locking mLock
454    // here so that the destructor is called only when exiting this function.
455    // On the other hand, as long as Track::destroy() is only called by
456    // TrackHandle destructor, the TrackHandle still holds a strong ref on
457    // this Track with its member mTrack.
458    sp<Track> keep(this);
459    { // scope for mLock
460        bool wasActive = false;
461        sp<ThreadBase> thread = mThread.promote();
462        if (thread != 0) {
463            Mutex::Autolock _l(thread->mLock);
464            PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
465            wasActive = playbackThread->destroyTrack_l(this);
466        }
467        if (isExternalTrack() && !wasActive) {
468            AudioSystem::releaseOutput(mThreadIoHandle, mStreamType, mSessionId);
469        }
470    }
471}
472
473/*static*/ void AudioFlinger::PlaybackThread::Track::appendDumpHeader(String8& result)
474{
475    result.append("    Name Active Client Type      Fmt Chn mask Session fCount S F SRate  "
476                  "L dB  R dB    Server Main buf  Aux buf Flags UndFrmCnt  Flushed\n");
477}
478
479void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size, bool active)
480{
481    gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
482    if (isFastTrack()) {
483        sprintf(buffer, "    F %2d", mFastIndex);
484    } else if (mName >= AudioMixer::TRACK0) {
485        sprintf(buffer, "    %4d", mName - AudioMixer::TRACK0);
486    } else {
487        sprintf(buffer, "    none");
488    }
489    track_state state = mState;
490    char stateChar;
491    if (isTerminated()) {
492        stateChar = 'T';
493    } else {
494        switch (state) {
495        case IDLE:
496            stateChar = 'I';
497            break;
498        case STOPPING_1:
499            stateChar = 's';
500            break;
501        case STOPPING_2:
502            stateChar = '5';
503            break;
504        case STOPPED:
505            stateChar = 'S';
506            break;
507        case RESUMING:
508            stateChar = 'R';
509            break;
510        case ACTIVE:
511            stateChar = 'A';
512            break;
513        case PAUSING:
514            stateChar = 'p';
515            break;
516        case PAUSED:
517            stateChar = 'P';
518            break;
519        case FLUSHED:
520            stateChar = 'F';
521            break;
522        default:
523            stateChar = '?';
524            break;
525        }
526    }
527    char nowInUnderrun;
528    switch (mObservedUnderruns.mBitFields.mMostRecent) {
529    case UNDERRUN_FULL:
530        nowInUnderrun = ' ';
531        break;
532    case UNDERRUN_PARTIAL:
533        nowInUnderrun = '<';
534        break;
535    case UNDERRUN_EMPTY:
536        nowInUnderrun = '*';
537        break;
538    default:
539        nowInUnderrun = '?';
540        break;
541    }
542    snprintf(&buffer[8], size-8, " %6s %6u %4u %08X %08X %7u %6zu %1c %1d %5u %5.2g %5.2g  "
543                                 "%08X %08zX %08zX 0x%03X %9u%c %7u\n",
544            active ? "yes" : "no",
545            (mClient == 0) ? getpid_cached : mClient->pid(),
546            mStreamType,
547            mFormat,
548            mChannelMask,
549            mSessionId,
550            mFrameCount,
551            stateChar,
552            mFillingUpStatus,
553            mAudioTrackServerProxy->getSampleRate(),
554            20.0 * log10(float_from_gain(gain_minifloat_unpack_left(vlr))),
555            20.0 * log10(float_from_gain(gain_minifloat_unpack_right(vlr))),
556            mCblk->mServer,
557            (size_t)mMainBuffer, // use %zX as %p appends 0x
558            (size_t)mAuxBuffer,  // use %zX as %p appends 0x
559            mCblk->mFlags,
560            mAudioTrackServerProxy->getUnderrunFrames(),
561            nowInUnderrun,
562            (unsigned)mAudioTrackServerProxy->framesFlushed() % 10000000); // 7 digits
563}
564
565uint32_t AudioFlinger::PlaybackThread::Track::sampleRate() const {
566    return mAudioTrackServerProxy->getSampleRate();
567}
568
569// AudioBufferProvider interface
570status_t AudioFlinger::PlaybackThread::Track::getNextBuffer(
571        AudioBufferProvider::Buffer* buffer)
572{
573    ServerProxy::Buffer buf;
574    size_t desiredFrames = buffer->frameCount;
575    buf.mFrameCount = desiredFrames;
576    status_t status = mServerProxy->obtainBuffer(&buf);
577    buffer->frameCount = buf.mFrameCount;
578    buffer->raw = buf.mRaw;
579    if (buf.mFrameCount == 0) {
580        mAudioTrackServerProxy->tallyUnderrunFrames(desiredFrames);
581    } else {
582        mAudioTrackServerProxy->tallyUnderrunFrames(0);
583    }
584
585    return status;
586}
587
588// releaseBuffer() is not overridden
589
590// ExtendedAudioBufferProvider interface
591
592// framesReady() may return an approximation of the number of frames if called
593// from a different thread than the one calling Proxy->obtainBuffer() and
594// Proxy->releaseBuffer(). Also note there is no mutual exclusion in the
595// AudioTrackServerProxy so be especially careful calling with FastTracks.
596size_t AudioFlinger::PlaybackThread::Track::framesReady() const {
597    if (mSharedBuffer != 0 && (isStopped() || isStopping())) {
598        // Static tracks return zero frames immediately upon stopping (for FastTracks).
599        // The remainder of the buffer is not drained.
600        return 0;
601    }
602    return mAudioTrackServerProxy->framesReady();
603}
604
605int64_t AudioFlinger::PlaybackThread::Track::framesReleased() const
606{
607    return mAudioTrackServerProxy->framesReleased();
608}
609
610void AudioFlinger::PlaybackThread::Track::onTimestamp(const ExtendedTimestamp &timestamp)
611{
612    // This call comes from a FastTrack and should be kept lockless.
613    // The server side frames are already translated to client frames.
614    mAudioTrackServerProxy->setTimestamp(timestamp);
615
616    // We do not set drained here, as FastTrack timestamp may not go to very last frame.
617}
618
619// Don't call for fast tracks; the framesReady() could result in priority inversion
620bool AudioFlinger::PlaybackThread::Track::isReady() const {
621    if (mFillingUpStatus != FS_FILLING || isStopped() || isPausing()) {
622        return true;
623    }
624
625    if (isStopping()) {
626        if (framesReady() > 0) {
627            mFillingUpStatus = FS_FILLED;
628        }
629        return true;
630    }
631
632    if (framesReady() >= mServerProxy->getBufferSizeInFrames() ||
633            (mCblk->mFlags & CBLK_FORCEREADY)) {
634        mFillingUpStatus = FS_FILLED;
635        android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
636        return true;
637    }
638    return false;
639}
640
641status_t AudioFlinger::PlaybackThread::Track::start(AudioSystem::sync_event_t event __unused,
642                                                    audio_session_t triggerSession __unused)
643{
644    status_t status = NO_ERROR;
645    ALOGV("start(%d), calling pid %d session %d",
646            mName, IPCThreadState::self()->getCallingPid(), mSessionId);
647
648    sp<ThreadBase> thread = mThread.promote();
649    if (thread != 0) {
650        if (isOffloaded()) {
651            Mutex::Autolock _laf(thread->mAudioFlinger->mLock);
652            Mutex::Autolock _lth(thread->mLock);
653            sp<EffectChain> ec = thread->getEffectChain_l(mSessionId);
654            if (thread->mAudioFlinger->isNonOffloadableGlobalEffectEnabled_l() ||
655                    (ec != 0 && ec->isNonOffloadableEnabled())) {
656                invalidate();
657                return PERMISSION_DENIED;
658            }
659        }
660        Mutex::Autolock _lth(thread->mLock);
661        track_state state = mState;
662        // here the track could be either new, or restarted
663        // in both cases "unstop" the track
664
665        // initial state-stopping. next state-pausing.
666        // What if resume is called ?
667
668        if (state == PAUSED || state == PAUSING) {
669            if (mResumeToStopping) {
670                // happened we need to resume to STOPPING_1
671                mState = TrackBase::STOPPING_1;
672                ALOGV("PAUSED => STOPPING_1 (%d) on thread %p", mName, this);
673            } else {
674                mState = TrackBase::RESUMING;
675                ALOGV("PAUSED => RESUMING (%d) on thread %p", mName, this);
676            }
677        } else {
678            mState = TrackBase::ACTIVE;
679            ALOGV("? => ACTIVE (%d) on thread %p", mName, this);
680        }
681
682        // states to reset position info for non-offloaded/direct tracks
683        if (!isOffloaded() && !isDirect()
684                && (state == IDLE || state == STOPPED || state == FLUSHED)) {
685            mFrameMap.reset();
686        }
687        PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
688        if (isFastTrack()) {
689            // refresh fast track underruns on start because that field is never cleared
690            // by the fast mixer; furthermore, the same track can be recycled, i.e. start
691            // after stop.
692            mObservedUnderruns = playbackThread->getFastTrackUnderruns(mFastIndex);
693        }
694        status = playbackThread->addTrack_l(this);
695        if (status == INVALID_OPERATION || status == PERMISSION_DENIED) {
696            triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
697            //  restore previous state if start was rejected by policy manager
698            if (status == PERMISSION_DENIED) {
699                mState = state;
700            }
701        }
702        // track was already in the active list, not a problem
703        if (status == ALREADY_EXISTS) {
704            status = NO_ERROR;
705        } else {
706            // Acknowledge any pending flush(), so that subsequent new data isn't discarded.
707            // It is usually unsafe to access the server proxy from a binder thread.
708            // But in this case we know the mixer thread (whether normal mixer or fast mixer)
709            // isn't looking at this track yet:  we still hold the normal mixer thread lock,
710            // and for fast tracks the track is not yet in the fast mixer thread's active set.
711            // For static tracks, this is used to acknowledge change in position or loop.
712            ServerProxy::Buffer buffer;
713            buffer.mFrameCount = 1;
714            (void) mAudioTrackServerProxy->obtainBuffer(&buffer, true /*ackFlush*/);
715        }
716    } else {
717        status = BAD_VALUE;
718    }
719    return status;
720}
721
722void AudioFlinger::PlaybackThread::Track::stop()
723{
724    ALOGV("stop(%d), calling pid %d", mName, IPCThreadState::self()->getCallingPid());
725    sp<ThreadBase> thread = mThread.promote();
726    if (thread != 0) {
727        Mutex::Autolock _l(thread->mLock);
728        track_state state = mState;
729        if (state == RESUMING || state == ACTIVE || state == PAUSING || state == PAUSED) {
730            // If the track is not active (PAUSED and buffers full), flush buffers
731            PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
732            if (playbackThread->mActiveTracks.indexOf(this) < 0) {
733                reset();
734                mState = STOPPED;
735            } else if (!isFastTrack() && !isOffloaded() && !isDirect()) {
736                mState = STOPPED;
737            } else {
738                // For fast tracks prepareTracks_l() will set state to STOPPING_2
739                // presentation is complete
740                // For an offloaded track this starts a drain and state will
741                // move to STOPPING_2 when drain completes and then STOPPED
742                mState = STOPPING_1;
743                if (isOffloaded()) {
744                    mRetryCount = PlaybackThread::kMaxTrackStopRetriesOffload;
745                }
746            }
747            playbackThread->broadcast_l();
748            ALOGV("not stopping/stopped => stopping/stopped (%d) on thread %p", mName,
749                    playbackThread);
750        }
751    }
752}
753
754void AudioFlinger::PlaybackThread::Track::pause()
755{
756    ALOGV("pause(%d), calling pid %d", mName, IPCThreadState::self()->getCallingPid());
757    sp<ThreadBase> thread = mThread.promote();
758    if (thread != 0) {
759        Mutex::Autolock _l(thread->mLock);
760        PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
761        switch (mState) {
762        case STOPPING_1:
763        case STOPPING_2:
764            if (!isOffloaded()) {
765                /* nothing to do if track is not offloaded */
766                break;
767            }
768
769            // Offloaded track was draining, we need to carry on draining when resumed
770            mResumeToStopping = true;
771            // fall through...
772        case ACTIVE:
773        case RESUMING:
774            mState = PAUSING;
775            ALOGV("ACTIVE/RESUMING => PAUSING (%d) on thread %p", mName, thread.get());
776            playbackThread->broadcast_l();
777            break;
778
779        default:
780            break;
781        }
782    }
783}
784
785void AudioFlinger::PlaybackThread::Track::flush()
786{
787    ALOGV("flush(%d)", mName);
788    sp<ThreadBase> thread = mThread.promote();
789    if (thread != 0) {
790        Mutex::Autolock _l(thread->mLock);
791        PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
792
793        // Flush the ring buffer now if the track is not active in the PlaybackThread.
794        // Otherwise the flush would not be done until the track is resumed.
795        // Requires FastTrack removal be BLOCK_UNTIL_ACKED
796        if (playbackThread->mActiveTracks.indexOf(this) < 0) {
797            (void)mServerProxy->flushBufferIfNeeded();
798        }
799
800        if (isOffloaded()) {
801            // If offloaded we allow flush during any state except terminated
802            // and keep the track active to avoid problems if user is seeking
803            // rapidly and underlying hardware has a significant delay handling
804            // a pause
805            if (isTerminated()) {
806                return;
807            }
808
809            ALOGV("flush: offload flush");
810            reset();
811
812            if (mState == STOPPING_1 || mState == STOPPING_2) {
813                ALOGV("flushed in STOPPING_1 or 2 state, change state to ACTIVE");
814                mState = ACTIVE;
815            }
816
817            mFlushHwPending = true;
818            mResumeToStopping = false;
819        } else {
820            if (mState != STOPPING_1 && mState != STOPPING_2 && mState != STOPPED &&
821                    mState != PAUSED && mState != PAUSING && mState != IDLE && mState != FLUSHED) {
822                return;
823            }
824            // No point remaining in PAUSED state after a flush => go to
825            // FLUSHED state
826            mState = FLUSHED;
827            // do not reset the track if it is still in the process of being stopped or paused.
828            // this will be done by prepareTracks_l() when the track is stopped.
829            // prepareTracks_l() will see mState == FLUSHED, then
830            // remove from active track list, reset(), and trigger presentation complete
831            if (isDirect()) {
832                mFlushHwPending = true;
833            }
834            if (playbackThread->mActiveTracks.indexOf(this) < 0) {
835                reset();
836            }
837        }
838        // Prevent flush being lost if the track is flushed and then resumed
839        // before mixer thread can run. This is important when offloading
840        // because the hardware buffer could hold a large amount of audio
841        playbackThread->broadcast_l();
842    }
843}
844
845// must be called with thread lock held
846void AudioFlinger::PlaybackThread::Track::flushAck()
847{
848    if (!isOffloaded() && !isDirect())
849        return;
850
851    // Clear the client ring buffer so that the app can prime the buffer while paused.
852    // Otherwise it might not get cleared until playback is resumed and obtainBuffer() is called.
853    mServerProxy->flushBufferIfNeeded();
854
855    mFlushHwPending = false;
856}
857
858void AudioFlinger::PlaybackThread::Track::reset()
859{
860    // Do not reset twice to avoid discarding data written just after a flush and before
861    // the audioflinger thread detects the track is stopped.
862    if (!mResetDone) {
863        // Force underrun condition to avoid false underrun callback until first data is
864        // written to buffer
865        android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
866        mFillingUpStatus = FS_FILLING;
867        mResetDone = true;
868        if (mState == FLUSHED) {
869            mState = IDLE;
870        }
871    }
872}
873
874status_t AudioFlinger::PlaybackThread::Track::setParameters(const String8& keyValuePairs)
875{
876    sp<ThreadBase> thread = mThread.promote();
877    if (thread == 0) {
878        ALOGE("thread is dead");
879        return FAILED_TRANSACTION;
880    } else if ((thread->type() == ThreadBase::DIRECT) ||
881                    (thread->type() == ThreadBase::OFFLOAD)) {
882        return thread->setParameters(keyValuePairs);
883    } else {
884        return PERMISSION_DENIED;
885    }
886}
887
888VolumeShaper::Status AudioFlinger::PlaybackThread::Track::applyVolumeShaper(
889        const sp<VolumeShaper::Configuration>& configuration,
890        const sp<VolumeShaper::Operation>& operation)
891{
892    // Note: We don't check if Thread exists.
893
894    // mVolumeHandler is thread-safe.
895    return mVolumeHandler->applyVolumeShaper(configuration, operation);
896}
897
898sp<VolumeShaper::State> AudioFlinger::PlaybackThread::Track::getVolumeShaperState(int id)
899{
900    // Note: We don't check if Thread exists.
901
902    // mVolumeHandler is thread safe.
903    return mVolumeHandler->getVolumeShaperState(id);
904}
905
906status_t AudioFlinger::PlaybackThread::Track::getTimestamp(AudioTimestamp& timestamp)
907{
908    if (!isOffloaded() && !isDirect()) {
909        return INVALID_OPERATION; // normal tracks handled through SSQ
910    }
911    sp<ThreadBase> thread = mThread.promote();
912    if (thread == 0) {
913        return INVALID_OPERATION;
914    }
915
916    Mutex::Autolock _l(thread->mLock);
917    PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
918    return playbackThread->getTimestamp_l(timestamp);
919}
920
921status_t AudioFlinger::PlaybackThread::Track::attachAuxEffect(int EffectId)
922{
923    status_t status = DEAD_OBJECT;
924    sp<ThreadBase> thread = mThread.promote();
925    if (thread != 0) {
926        PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
927        sp<AudioFlinger> af = mClient->audioFlinger();
928
929        Mutex::Autolock _l(af->mLock);
930
931        sp<PlaybackThread> srcThread = af->getEffectThread_l(AUDIO_SESSION_OUTPUT_MIX, EffectId);
932
933        if (EffectId != 0 && srcThread != 0 && playbackThread != srcThread.get()) {
934            Mutex::Autolock _dl(playbackThread->mLock);
935            Mutex::Autolock _sl(srcThread->mLock);
936            sp<EffectChain> chain = srcThread->getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
937            if (chain == 0) {
938                return INVALID_OPERATION;
939            }
940
941            sp<EffectModule> effect = chain->getEffectFromId_l(EffectId);
942            if (effect == 0) {
943                return INVALID_OPERATION;
944            }
945            srcThread->removeEffect_l(effect);
946            status = playbackThread->addEffect_l(effect);
947            if (status != NO_ERROR) {
948                srcThread->addEffect_l(effect);
949                return INVALID_OPERATION;
950            }
951            // removeEffect_l() has stopped the effect if it was active so it must be restarted
952            if (effect->state() == EffectModule::ACTIVE ||
953                    effect->state() == EffectModule::STOPPING) {
954                effect->start();
955            }
956
957            sp<EffectChain> dstChain = effect->chain().promote();
958            if (dstChain == 0) {
959                srcThread->addEffect_l(effect);
960                return INVALID_OPERATION;
961            }
962            AudioSystem::unregisterEffect(effect->id());
963            AudioSystem::registerEffect(&effect->desc(),
964                                        srcThread->id(),
965                                        dstChain->strategy(),
966                                        AUDIO_SESSION_OUTPUT_MIX,
967                                        effect->id());
968            AudioSystem::setEffectEnabled(effect->id(), effect->isEnabled());
969        }
970        status = playbackThread->attachAuxEffect(this, EffectId);
971    }
972    return status;
973}
974
975void AudioFlinger::PlaybackThread::Track::setAuxBuffer(int EffectId, int32_t *buffer)
976{
977    mAuxEffectId = EffectId;
978    mAuxBuffer = buffer;
979}
980
981bool AudioFlinger::PlaybackThread::Track::presentationComplete(
982        int64_t framesWritten, size_t audioHalFrames)
983{
984    // TODO: improve this based on FrameMap if it exists, to ensure full drain.
985    // This assists in proper timestamp computation as well as wakelock management.
986
987    // a track is considered presented when the total number of frames written to audio HAL
988    // corresponds to the number of frames written when presentationComplete() is called for the
989    // first time (mPresentationCompleteFrames == 0) plus the buffer filling status at that time.
990    // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
991    // to detect when all frames have been played. In this case framesWritten isn't
992    // useful because it doesn't always reflect whether there is data in the h/w
993    // buffers, particularly if a track has been paused and resumed during draining
994    ALOGV("presentationComplete() mPresentationCompleteFrames %lld framesWritten %lld",
995            (long long)mPresentationCompleteFrames, (long long)framesWritten);
996    if (mPresentationCompleteFrames == 0) {
997        mPresentationCompleteFrames = framesWritten + audioHalFrames;
998        ALOGV("presentationComplete() reset: mPresentationCompleteFrames %lld audioHalFrames %zu",
999                (long long)mPresentationCompleteFrames, audioHalFrames);
1000    }
1001
1002    bool complete;
1003    if (isOffloaded()) {
1004        complete = true;
1005    } else if (isDirect() || isFastTrack()) { // these do not go through linear map
1006        complete = framesWritten >= (int64_t) mPresentationCompleteFrames;
1007    } else {  // Normal tracks, OutputTracks, and PatchTracks
1008        complete = framesWritten >= (int64_t) mPresentationCompleteFrames
1009                && mAudioTrackServerProxy->isDrained();
1010    }
1011
1012    if (complete) {
1013        triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
1014        mAudioTrackServerProxy->setStreamEndDone();
1015        return true;
1016    }
1017    return false;
1018}
1019
1020void AudioFlinger::PlaybackThread::Track::triggerEvents(AudioSystem::sync_event_t type)
1021{
1022    for (size_t i = 0; i < mSyncEvents.size(); i++) {
1023        if (mSyncEvents[i]->type() == type) {
1024            mSyncEvents[i]->trigger();
1025            mSyncEvents.removeAt(i);
1026            i--;
1027        }
1028    }
1029}
1030
1031// implement VolumeBufferProvider interface
1032
1033gain_minifloat_packed_t AudioFlinger::PlaybackThread::Track::getVolumeLR()
1034{
1035    // called by FastMixer, so not allowed to take any locks, block, or do I/O including logs
1036    ALOG_ASSERT(isFastTrack() && (mCblk != NULL));
1037    gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
1038    float vl = float_from_gain(gain_minifloat_unpack_left(vlr));
1039    float vr = float_from_gain(gain_minifloat_unpack_right(vlr));
1040    // track volumes come from shared memory, so can't be trusted and must be clamped
1041    if (vl > GAIN_FLOAT_UNITY) {
1042        vl = GAIN_FLOAT_UNITY;
1043    }
1044    if (vr > GAIN_FLOAT_UNITY) {
1045        vr = GAIN_FLOAT_UNITY;
1046    }
1047    // now apply the cached master volume and stream type volume;
1048    // this is trusted but lacks any synchronization or barrier so may be stale
1049    float v = mCachedVolume;
1050    vl *= v;
1051    vr *= v;
1052    // re-combine into packed minifloat
1053    vlr = gain_minifloat_pack(gain_from_float(vl), gain_from_float(vr));
1054    // FIXME look at mute, pause, and stop flags
1055    return vlr;
1056}
1057
1058status_t AudioFlinger::PlaybackThread::Track::setSyncEvent(const sp<SyncEvent>& event)
1059{
1060    if (isTerminated() || mState == PAUSED ||
1061            ((framesReady() == 0) && ((mSharedBuffer != 0) ||
1062                                      (mState == STOPPED)))) {
1063        ALOGW("Track::setSyncEvent() in invalid state %d on session %d %s mode, framesReady %zu",
1064              mState, mSessionId, (mSharedBuffer != 0) ? "static" : "stream", framesReady());
1065        event->cancel();
1066        return INVALID_OPERATION;
1067    }
1068    (void) TrackBase::setSyncEvent(event);
1069    return NO_ERROR;
1070}
1071
1072void AudioFlinger::PlaybackThread::Track::invalidate()
1073{
1074    TrackBase::invalidate();
1075    signalClientFlag(CBLK_INVALID);
1076}
1077
1078void AudioFlinger::PlaybackThread::Track::disable()
1079{
1080    signalClientFlag(CBLK_DISABLED);
1081}
1082
1083void AudioFlinger::PlaybackThread::Track::signalClientFlag(int32_t flag)
1084{
1085    // FIXME should use proxy, and needs work
1086    audio_track_cblk_t* cblk = mCblk;
1087    android_atomic_or(flag, &cblk->mFlags);
1088    android_atomic_release_store(0x40000000, &cblk->mFutex);
1089    // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
1090    (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
1091}
1092
1093void AudioFlinger::PlaybackThread::Track::signal()
1094{
1095    sp<ThreadBase> thread = mThread.promote();
1096    if (thread != 0) {
1097        PlaybackThread *t = (PlaybackThread *)thread.get();
1098        Mutex::Autolock _l(t->mLock);
1099        t->broadcast_l();
1100    }
1101}
1102
1103//To be called with thread lock held
1104bool AudioFlinger::PlaybackThread::Track::isResumePending() {
1105
1106    if (mState == RESUMING)
1107        return true;
1108    /* Resume is pending if track was stopping before pause was called */
1109    if (mState == STOPPING_1 &&
1110        mResumeToStopping)
1111        return true;
1112
1113    return false;
1114}
1115
1116//To be called with thread lock held
1117void AudioFlinger::PlaybackThread::Track::resumeAck() {
1118
1119
1120    if (mState == RESUMING)
1121        mState = ACTIVE;
1122
1123    // Other possibility of  pending resume is stopping_1 state
1124    // Do not update the state from stopping as this prevents
1125    // drain being called.
1126    if (mState == STOPPING_1) {
1127        mResumeToStopping = false;
1128    }
1129}
1130
1131//To be called with thread lock held
1132void AudioFlinger::PlaybackThread::Track::updateTrackFrameInfo(
1133        int64_t trackFramesReleased, int64_t sinkFramesWritten,
1134        const ExtendedTimestamp &timeStamp) {
1135    //update frame map
1136    mFrameMap.push(trackFramesReleased, sinkFramesWritten);
1137
1138    // adjust server times and set drained state.
1139    //
1140    // Our timestamps are only updated when the track is on the Thread active list.
1141    // We need to ensure that tracks are not removed before full drain.
1142    ExtendedTimestamp local = timeStamp;
1143    bool checked = false;
1144    for (int i = ExtendedTimestamp::LOCATION_MAX - 1;
1145            i >= ExtendedTimestamp::LOCATION_SERVER; --i) {
1146        // Lookup the track frame corresponding to the sink frame position.
1147        if (local.mTimeNs[i] > 0) {
1148            local.mPosition[i] = mFrameMap.findX(local.mPosition[i]);
1149            // check drain state from the latest stage in the pipeline.
1150            if (!checked && i <= ExtendedTimestamp::LOCATION_KERNEL) {
1151                mAudioTrackServerProxy->setDrained(
1152                        local.mPosition[i] >= mAudioTrackServerProxy->framesReleased());
1153                checked = true;
1154            }
1155        }
1156    }
1157    if (!checked) { // no server info, assume drained.
1158        mAudioTrackServerProxy->setDrained(true);
1159    }
1160    // Set correction for flushed frames that are not accounted for in released.
1161    local.mFlushed = mAudioTrackServerProxy->framesFlushed();
1162    mServerProxy->setTimestamp(local);
1163}
1164
1165// ----------------------------------------------------------------------------
1166
1167AudioFlinger::PlaybackThread::OutputTrack::OutputTrack(
1168            PlaybackThread *playbackThread,
1169            DuplicatingThread *sourceThread,
1170            uint32_t sampleRate,
1171            audio_format_t format,
1172            audio_channel_mask_t channelMask,
1173            size_t frameCount,
1174            uid_t uid)
1175    :   Track(playbackThread, NULL, AUDIO_STREAM_PATCH,
1176              sampleRate, format, channelMask, frameCount,
1177              NULL, 0, AUDIO_SESSION_NONE, uid, AUDIO_OUTPUT_FLAG_NONE,
1178              TYPE_OUTPUT),
1179    mActive(false), mSourceThread(sourceThread)
1180{
1181
1182    if (mCblk != NULL) {
1183        mOutBuffer.frameCount = 0;
1184        playbackThread->mTracks.add(this);
1185        ALOGV("OutputTrack constructor mCblk %p, mBuffer %p, "
1186                "frameCount %zu, mChannelMask 0x%08x",
1187                mCblk, mBuffer,
1188                frameCount, mChannelMask);
1189        // since client and server are in the same process,
1190        // the buffer has the same virtual address on both sides
1191        mClientProxy = new AudioTrackClientProxy(mCblk, mBuffer, mFrameCount, mFrameSize,
1192                true /*clientInServer*/);
1193        mClientProxy->setVolumeLR(GAIN_MINIFLOAT_PACKED_UNITY);
1194        mClientProxy->setSendLevel(0.0);
1195        mClientProxy->setSampleRate(sampleRate);
1196    } else {
1197        ALOGW("Error creating output track on thread %p", playbackThread);
1198    }
1199}
1200
1201AudioFlinger::PlaybackThread::OutputTrack::~OutputTrack()
1202{
1203    clearBufferQueue();
1204    // superclass destructor will now delete the server proxy and shared memory both refer to
1205}
1206
1207status_t AudioFlinger::PlaybackThread::OutputTrack::start(AudioSystem::sync_event_t event,
1208                                                          audio_session_t triggerSession)
1209{
1210    status_t status = Track::start(event, triggerSession);
1211    if (status != NO_ERROR) {
1212        return status;
1213    }
1214
1215    mActive = true;
1216    mRetryCount = 127;
1217    return status;
1218}
1219
1220void AudioFlinger::PlaybackThread::OutputTrack::stop()
1221{
1222    Track::stop();
1223    clearBufferQueue();
1224    mOutBuffer.frameCount = 0;
1225    mActive = false;
1226}
1227
1228bool AudioFlinger::PlaybackThread::OutputTrack::write(void* data, uint32_t frames)
1229{
1230    Buffer *pInBuffer;
1231    Buffer inBuffer;
1232    bool outputBufferFull = false;
1233    inBuffer.frameCount = frames;
1234    inBuffer.raw = data;
1235
1236    uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
1237
1238    if (!mActive && frames != 0) {
1239        (void) start();
1240    }
1241
1242    while (waitTimeLeftMs) {
1243        // First write pending buffers, then new data
1244        if (mBufferQueue.size()) {
1245            pInBuffer = mBufferQueue.itemAt(0);
1246        } else {
1247            pInBuffer = &inBuffer;
1248        }
1249
1250        if (pInBuffer->frameCount == 0) {
1251            break;
1252        }
1253
1254        if (mOutBuffer.frameCount == 0) {
1255            mOutBuffer.frameCount = pInBuffer->frameCount;
1256            nsecs_t startTime = systemTime();
1257            status_t status = obtainBuffer(&mOutBuffer, waitTimeLeftMs);
1258            if (status != NO_ERROR && status != NOT_ENOUGH_DATA) {
1259                ALOGV("OutputTrack::write() %p thread %p no more output buffers; status %d", this,
1260                        mThread.unsafe_get(), status);
1261                outputBufferFull = true;
1262                break;
1263            }
1264            uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
1265            if (waitTimeLeftMs >= waitTimeMs) {
1266                waitTimeLeftMs -= waitTimeMs;
1267            } else {
1268                waitTimeLeftMs = 0;
1269            }
1270            if (status == NOT_ENOUGH_DATA) {
1271                restartIfDisabled();
1272                continue;
1273            }
1274        }
1275
1276        uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount :
1277                pInBuffer->frameCount;
1278        memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * mFrameSize);
1279        Proxy::Buffer buf;
1280        buf.mFrameCount = outFrames;
1281        buf.mRaw = NULL;
1282        mClientProxy->releaseBuffer(&buf);
1283        restartIfDisabled();
1284        pInBuffer->frameCount -= outFrames;
1285        pInBuffer->raw = (int8_t *)pInBuffer->raw + outFrames * mFrameSize;
1286        mOutBuffer.frameCount -= outFrames;
1287        mOutBuffer.raw = (int8_t *)mOutBuffer.raw + outFrames * mFrameSize;
1288
1289        if (pInBuffer->frameCount == 0) {
1290            if (mBufferQueue.size()) {
1291                mBufferQueue.removeAt(0);
1292                free(pInBuffer->mBuffer);
1293                delete pInBuffer;
1294                ALOGV("OutputTrack::write() %p thread %p released overflow buffer %zu", this,
1295                        mThread.unsafe_get(), mBufferQueue.size());
1296            } else {
1297                break;
1298            }
1299        }
1300    }
1301
1302    // If we could not write all frames, allocate a buffer and queue it for next time.
1303    if (inBuffer.frameCount) {
1304        sp<ThreadBase> thread = mThread.promote();
1305        if (thread != 0 && !thread->standby()) {
1306            if (mBufferQueue.size() < kMaxOverFlowBuffers) {
1307                pInBuffer = new Buffer;
1308                pInBuffer->mBuffer = malloc(inBuffer.frameCount * mFrameSize);
1309                pInBuffer->frameCount = inBuffer.frameCount;
1310                pInBuffer->raw = pInBuffer->mBuffer;
1311                memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * mFrameSize);
1312                mBufferQueue.add(pInBuffer);
1313                ALOGV("OutputTrack::write() %p thread %p adding overflow buffer %zu", this,
1314                        mThread.unsafe_get(), mBufferQueue.size());
1315            } else {
1316                ALOGW("OutputTrack::write() %p thread %p no more overflow buffers",
1317                        mThread.unsafe_get(), this);
1318            }
1319        }
1320    }
1321
1322    // Calling write() with a 0 length buffer means that no more data will be written:
1323    // We rely on stop() to set the appropriate flags to allow the remaining frames to play out.
1324    if (frames == 0 && mBufferQueue.size() == 0 && mActive) {
1325        stop();
1326    }
1327
1328    return outputBufferFull;
1329}
1330
1331status_t AudioFlinger::PlaybackThread::OutputTrack::obtainBuffer(
1332        AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
1333{
1334    ClientProxy::Buffer buf;
1335    buf.mFrameCount = buffer->frameCount;
1336    struct timespec timeout;
1337    timeout.tv_sec = waitTimeMs / 1000;
1338    timeout.tv_nsec = (int) (waitTimeMs % 1000) * 1000000;
1339    status_t status = mClientProxy->obtainBuffer(&buf, &timeout);
1340    buffer->frameCount = buf.mFrameCount;
1341    buffer->raw = buf.mRaw;
1342    return status;
1343}
1344
1345void AudioFlinger::PlaybackThread::OutputTrack::clearBufferQueue()
1346{
1347    size_t size = mBufferQueue.size();
1348
1349    for (size_t i = 0; i < size; i++) {
1350        Buffer *pBuffer = mBufferQueue.itemAt(i);
1351        free(pBuffer->mBuffer);
1352        delete pBuffer;
1353    }
1354    mBufferQueue.clear();
1355}
1356
1357void AudioFlinger::PlaybackThread::OutputTrack::restartIfDisabled()
1358{
1359    int32_t flags = android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
1360    if (mActive && (flags & CBLK_DISABLED)) {
1361        start();
1362    }
1363}
1364
1365AudioFlinger::PlaybackThread::PatchTrack::PatchTrack(PlaybackThread *playbackThread,
1366                                                     audio_stream_type_t streamType,
1367                                                     uint32_t sampleRate,
1368                                                     audio_channel_mask_t channelMask,
1369                                                     audio_format_t format,
1370                                                     size_t frameCount,
1371                                                     void *buffer,
1372                                                     audio_output_flags_t flags)
1373    :   Track(playbackThread, NULL, streamType,
1374              sampleRate, format, channelMask, frameCount,
1375              buffer, 0, AUDIO_SESSION_NONE, getuid(), flags, TYPE_PATCH),
1376              mProxy(new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, true, true))
1377{
1378    uint64_t mixBufferNs = ((uint64_t)2 * playbackThread->frameCount() * 1000000000) /
1379                                                                    playbackThread->sampleRate();
1380    mPeerTimeout.tv_sec = mixBufferNs / 1000000000;
1381    mPeerTimeout.tv_nsec = (int) (mixBufferNs % 1000000000);
1382
1383    ALOGV("PatchTrack %p sampleRate %d mPeerTimeout %d.%03d sec",
1384                                      this, sampleRate,
1385                                      (int)mPeerTimeout.tv_sec,
1386                                      (int)(mPeerTimeout.tv_nsec / 1000000));
1387}
1388
1389AudioFlinger::PlaybackThread::PatchTrack::~PatchTrack()
1390{
1391}
1392
1393status_t AudioFlinger::PlaybackThread::PatchTrack::start(AudioSystem::sync_event_t event,
1394                                                          audio_session_t triggerSession)
1395{
1396    status_t status = Track::start(event, triggerSession);
1397    if (status != NO_ERROR) {
1398        return status;
1399    }
1400    android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
1401    return status;
1402}
1403
1404// AudioBufferProvider interface
1405status_t AudioFlinger::PlaybackThread::PatchTrack::getNextBuffer(
1406        AudioBufferProvider::Buffer* buffer)
1407{
1408    ALOG_ASSERT(mPeerProxy != 0, "PatchTrack::getNextBuffer() called without peer proxy");
1409    Proxy::Buffer buf;
1410    buf.mFrameCount = buffer->frameCount;
1411    status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
1412    ALOGV_IF(status != NO_ERROR, "PatchTrack() %p getNextBuffer status %d", this, status);
1413    buffer->frameCount = buf.mFrameCount;
1414    if (buf.mFrameCount == 0) {
1415        return WOULD_BLOCK;
1416    }
1417    status = Track::getNextBuffer(buffer);
1418    return status;
1419}
1420
1421void AudioFlinger::PlaybackThread::PatchTrack::releaseBuffer(AudioBufferProvider::Buffer* buffer)
1422{
1423    ALOG_ASSERT(mPeerProxy != 0, "PatchTrack::releaseBuffer() called without peer proxy");
1424    Proxy::Buffer buf;
1425    buf.mFrameCount = buffer->frameCount;
1426    buf.mRaw = buffer->raw;
1427    mPeerProxy->releaseBuffer(&buf);
1428    TrackBase::releaseBuffer(buffer);
1429}
1430
1431status_t AudioFlinger::PlaybackThread::PatchTrack::obtainBuffer(Proxy::Buffer* buffer,
1432                                                                const struct timespec *timeOut)
1433{
1434    status_t status = NO_ERROR;
1435    static const int32_t kMaxTries = 5;
1436    int32_t tryCounter = kMaxTries;
1437    do {
1438        if (status == NOT_ENOUGH_DATA) {
1439            restartIfDisabled();
1440        }
1441        status = mProxy->obtainBuffer(buffer, timeOut);
1442    } while ((status == NOT_ENOUGH_DATA) && (tryCounter-- > 0));
1443    return status;
1444}
1445
1446void AudioFlinger::PlaybackThread::PatchTrack::releaseBuffer(Proxy::Buffer* buffer)
1447{
1448    mProxy->releaseBuffer(buffer);
1449    restartIfDisabled();
1450    android_atomic_or(CBLK_FORCEREADY, &mCblk->mFlags);
1451}
1452
1453void AudioFlinger::PlaybackThread::PatchTrack::restartIfDisabled()
1454{
1455    if (android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags) & CBLK_DISABLED) {
1456        ALOGW("PatchTrack::releaseBuffer() disabled due to previous underrun, restarting");
1457        start();
1458    }
1459}
1460
1461// ----------------------------------------------------------------------------
1462//      Record
1463// ----------------------------------------------------------------------------
1464
1465AudioFlinger::RecordHandle::RecordHandle(
1466        const sp<AudioFlinger::RecordThread::RecordTrack>& recordTrack)
1467    : BnAudioRecord(),
1468    mRecordTrack(recordTrack)
1469{
1470}
1471
1472AudioFlinger::RecordHandle::~RecordHandle() {
1473    stop_nonvirtual();
1474    mRecordTrack->destroy();
1475}
1476
1477status_t AudioFlinger::RecordHandle::start(int /*AudioSystem::sync_event_t*/ event,
1478        audio_session_t triggerSession) {
1479    ALOGV("RecordHandle::start()");
1480    return mRecordTrack->start((AudioSystem::sync_event_t)event, triggerSession);
1481}
1482
1483void AudioFlinger::RecordHandle::stop() {
1484    stop_nonvirtual();
1485}
1486
1487void AudioFlinger::RecordHandle::stop_nonvirtual() {
1488    ALOGV("RecordHandle::stop()");
1489    mRecordTrack->stop();
1490}
1491
1492status_t AudioFlinger::RecordHandle::onTransact(
1493    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1494{
1495    return BnAudioRecord::onTransact(code, data, reply, flags);
1496}
1497
1498// ----------------------------------------------------------------------------
1499
1500// RecordTrack constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
1501AudioFlinger::RecordThread::RecordTrack::RecordTrack(
1502            RecordThread *thread,
1503            const sp<Client>& client,
1504            uint32_t sampleRate,
1505            audio_format_t format,
1506            audio_channel_mask_t channelMask,
1507            size_t frameCount,
1508            void *buffer,
1509            audio_session_t sessionId,
1510            uid_t uid,
1511            audio_input_flags_t flags,
1512            track_type type,
1513            audio_port_handle_t portId)
1514    :   TrackBase(thread, client, sampleRate, format,
1515                  channelMask, frameCount, buffer, sessionId, uid, false /*isOut*/,
1516                  (type == TYPE_DEFAULT) ?
1517                          ((flags & AUDIO_INPUT_FLAG_FAST) ? ALLOC_PIPE : ALLOC_CBLK) :
1518                          ((buffer == NULL) ? ALLOC_LOCAL : ALLOC_NONE),
1519                  type, portId),
1520        mOverflow(false),
1521        mFramesToDrop(0),
1522        mResamplerBufferProvider(NULL), // initialize in case of early constructor exit
1523        mRecordBufferConverter(NULL),
1524        mFlags(flags)
1525{
1526    if (mCblk == NULL) {
1527        return;
1528    }
1529
1530    mRecordBufferConverter = new RecordBufferConverter(
1531            thread->mChannelMask, thread->mFormat, thread->mSampleRate,
1532            channelMask, format, sampleRate);
1533    // Check if the RecordBufferConverter construction was successful.
1534    // If not, don't continue with construction.
1535    //
1536    // NOTE: It would be extremely rare that the record track cannot be created
1537    // for the current device, but a pending or future device change would make
1538    // the record track configuration valid.
1539    if (mRecordBufferConverter->initCheck() != NO_ERROR) {
1540        ALOGE("RecordTrack unable to create record buffer converter");
1541        return;
1542    }
1543
1544    mServerProxy = new AudioRecordServerProxy(mCblk, mBuffer, frameCount,
1545            mFrameSize, !isExternalTrack());
1546
1547    mResamplerBufferProvider = new ResamplerBufferProvider(this);
1548
1549    if (flags & AUDIO_INPUT_FLAG_FAST) {
1550        ALOG_ASSERT(thread->mFastTrackAvail);
1551        thread->mFastTrackAvail = false;
1552    }
1553}
1554
1555AudioFlinger::RecordThread::RecordTrack::~RecordTrack()
1556{
1557    ALOGV("%s", __func__);
1558    delete mRecordBufferConverter;
1559    delete mResamplerBufferProvider;
1560}
1561
1562status_t AudioFlinger::RecordThread::RecordTrack::initCheck() const
1563{
1564    status_t status = TrackBase::initCheck();
1565    if (status == NO_ERROR && mServerProxy == 0) {
1566        status = BAD_VALUE;
1567    }
1568    return status;
1569}
1570
1571// AudioBufferProvider interface
1572status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
1573{
1574    ServerProxy::Buffer buf;
1575    buf.mFrameCount = buffer->frameCount;
1576    status_t status = mServerProxy->obtainBuffer(&buf);
1577    buffer->frameCount = buf.mFrameCount;
1578    buffer->raw = buf.mRaw;
1579    if (buf.mFrameCount == 0) {
1580        // FIXME also wake futex so that overrun is noticed more quickly
1581        (void) android_atomic_or(CBLK_OVERRUN, &mCblk->mFlags);
1582    }
1583    return status;
1584}
1585
1586status_t AudioFlinger::RecordThread::RecordTrack::start(AudioSystem::sync_event_t event,
1587                                                        audio_session_t triggerSession)
1588{
1589    sp<ThreadBase> thread = mThread.promote();
1590    if (thread != 0) {
1591        RecordThread *recordThread = (RecordThread *)thread.get();
1592        return recordThread->start(this, event, triggerSession);
1593    } else {
1594        return BAD_VALUE;
1595    }
1596}
1597
1598void AudioFlinger::RecordThread::RecordTrack::stop()
1599{
1600    sp<ThreadBase> thread = mThread.promote();
1601    if (thread != 0) {
1602        RecordThread *recordThread = (RecordThread *)thread.get();
1603        if (recordThread->stop(this) && isExternalTrack()) {
1604            AudioSystem::stopInput(mThreadIoHandle, mSessionId);
1605        }
1606    }
1607}
1608
1609void AudioFlinger::RecordThread::RecordTrack::destroy()
1610{
1611    // see comments at AudioFlinger::PlaybackThread::Track::destroy()
1612    sp<RecordTrack> keep(this);
1613    {
1614        if (isExternalTrack()) {
1615            if (mState == ACTIVE || mState == RESUMING) {
1616                AudioSystem::stopInput(mThreadIoHandle, mSessionId);
1617            }
1618            AudioSystem::releaseInput(mThreadIoHandle, mSessionId);
1619        }
1620        sp<ThreadBase> thread = mThread.promote();
1621        if (thread != 0) {
1622            Mutex::Autolock _l(thread->mLock);
1623            RecordThread *recordThread = (RecordThread *) thread.get();
1624            recordThread->destroyTrack_l(this);
1625        }
1626    }
1627}
1628
1629void AudioFlinger::RecordThread::RecordTrack::invalidate()
1630{
1631    TrackBase::invalidate();
1632    // FIXME should use proxy, and needs work
1633    audio_track_cblk_t* cblk = mCblk;
1634    android_atomic_or(CBLK_INVALID, &cblk->mFlags);
1635    android_atomic_release_store(0x40000000, &cblk->mFutex);
1636    // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
1637    (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
1638}
1639
1640
1641/*static*/ void AudioFlinger::RecordThread::RecordTrack::appendDumpHeader(String8& result)
1642{
1643    result.append("    Active Client Fmt Chn mask Session S   Server fCount SRate\n");
1644}
1645
1646void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size, bool active)
1647{
1648    snprintf(buffer, size, "    %6s %6u %3u %08X %7u %1d %08X %6zu %5u\n",
1649            active ? "yes" : "no",
1650            (mClient == 0) ? getpid_cached : mClient->pid(),
1651            mFormat,
1652            mChannelMask,
1653            mSessionId,
1654            mState,
1655            mCblk->mServer,
1656            mFrameCount,
1657            mSampleRate);
1658
1659}
1660
1661void AudioFlinger::RecordThread::RecordTrack::handleSyncStartEvent(const sp<SyncEvent>& event)
1662{
1663    if (event == mSyncStartEvent) {
1664        ssize_t framesToDrop = 0;
1665        sp<ThreadBase> threadBase = mThread.promote();
1666        if (threadBase != 0) {
1667            // TODO: use actual buffer filling status instead of 2 buffers when info is available
1668            // from audio HAL
1669            framesToDrop = threadBase->mFrameCount * 2;
1670        }
1671        mFramesToDrop = framesToDrop;
1672    }
1673}
1674
1675void AudioFlinger::RecordThread::RecordTrack::clearSyncStartEvent()
1676{
1677    if (mSyncStartEvent != 0) {
1678        mSyncStartEvent->cancel();
1679        mSyncStartEvent.clear();
1680    }
1681    mFramesToDrop = 0;
1682}
1683
1684void AudioFlinger::RecordThread::RecordTrack::updateTrackFrameInfo(
1685        int64_t trackFramesReleased, int64_t sourceFramesRead,
1686        uint32_t halSampleRate, const ExtendedTimestamp &timestamp)
1687{
1688    ExtendedTimestamp local = timestamp;
1689
1690    // Convert HAL frames to server-side track frames at track sample rate.
1691    // We use trackFramesReleased and sourceFramesRead as an anchor point.
1692    for (int i = ExtendedTimestamp::LOCATION_SERVER; i < ExtendedTimestamp::LOCATION_MAX; ++i) {
1693        if (local.mTimeNs[i] != 0) {
1694            const int64_t relativeServerFrames = local.mPosition[i] - sourceFramesRead;
1695            const int64_t relativeTrackFrames = relativeServerFrames
1696                    * mSampleRate / halSampleRate; // TODO: potential computation overflow
1697            local.mPosition[i] = relativeTrackFrames + trackFramesReleased;
1698        }
1699    }
1700    mServerProxy->setTimestamp(local);
1701}
1702
1703AudioFlinger::RecordThread::PatchRecord::PatchRecord(RecordThread *recordThread,
1704                                                     uint32_t sampleRate,
1705                                                     audio_channel_mask_t channelMask,
1706                                                     audio_format_t format,
1707                                                     size_t frameCount,
1708                                                     void *buffer,
1709                                                     audio_input_flags_t flags)
1710    :   RecordTrack(recordThread, NULL, sampleRate, format, channelMask, frameCount,
1711                buffer, AUDIO_SESSION_NONE, getuid(), flags, TYPE_PATCH),
1712                mProxy(new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, false, true))
1713{
1714    uint64_t mixBufferNs = ((uint64_t)2 * recordThread->frameCount() * 1000000000) /
1715                                                                recordThread->sampleRate();
1716    mPeerTimeout.tv_sec = mixBufferNs / 1000000000;
1717    mPeerTimeout.tv_nsec = (int) (mixBufferNs % 1000000000);
1718
1719    ALOGV("PatchRecord %p sampleRate %d mPeerTimeout %d.%03d sec",
1720                                      this, sampleRate,
1721                                      (int)mPeerTimeout.tv_sec,
1722                                      (int)(mPeerTimeout.tv_nsec / 1000000));
1723}
1724
1725AudioFlinger::RecordThread::PatchRecord::~PatchRecord()
1726{
1727}
1728
1729// AudioBufferProvider interface
1730status_t AudioFlinger::RecordThread::PatchRecord::getNextBuffer(
1731                                                  AudioBufferProvider::Buffer* buffer)
1732{
1733    ALOG_ASSERT(mPeerProxy != 0, "PatchRecord::getNextBuffer() called without peer proxy");
1734    Proxy::Buffer buf;
1735    buf.mFrameCount = buffer->frameCount;
1736    status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
1737    ALOGV_IF(status != NO_ERROR,
1738             "PatchRecord() %p mPeerProxy->obtainBuffer status %d", this, status);
1739    buffer->frameCount = buf.mFrameCount;
1740    if (buf.mFrameCount == 0) {
1741        return WOULD_BLOCK;
1742    }
1743    status = RecordTrack::getNextBuffer(buffer);
1744    return status;
1745}
1746
1747void AudioFlinger::RecordThread::PatchRecord::releaseBuffer(AudioBufferProvider::Buffer* buffer)
1748{
1749    ALOG_ASSERT(mPeerProxy != 0, "PatchRecord::releaseBuffer() called without peer proxy");
1750    Proxy::Buffer buf;
1751    buf.mFrameCount = buffer->frameCount;
1752    buf.mRaw = buffer->raw;
1753    mPeerProxy->releaseBuffer(&buf);
1754    TrackBase::releaseBuffer(buffer);
1755}
1756
1757status_t AudioFlinger::RecordThread::PatchRecord::obtainBuffer(Proxy::Buffer* buffer,
1758                                                               const struct timespec *timeOut)
1759{
1760    return mProxy->obtainBuffer(buffer, timeOut);
1761}
1762
1763void AudioFlinger::RecordThread::PatchRecord::releaseBuffer(Proxy::Buffer* buffer)
1764{
1765    mProxy->releaseBuffer(buffer);
1766}
1767
1768
1769
1770AudioFlinger::MmapThread::MmapTrack::MmapTrack(ThreadBase *thread,
1771        uint32_t sampleRate,
1772        audio_format_t format,
1773        audio_channel_mask_t channelMask,
1774        audio_session_t sessionId,
1775        uid_t uid,
1776        audio_port_handle_t portId)
1777    :   TrackBase(thread, NULL, sampleRate, format,
1778                  channelMask, 0, NULL, sessionId, uid, false,
1779                  ALLOC_NONE,
1780                  TYPE_DEFAULT, portId)
1781{
1782}
1783
1784AudioFlinger::MmapThread::MmapTrack::~MmapTrack()
1785{
1786}
1787
1788status_t AudioFlinger::MmapThread::MmapTrack::initCheck() const
1789{
1790    return NO_ERROR;
1791}
1792
1793status_t AudioFlinger::MmapThread::MmapTrack::start(AudioSystem::sync_event_t event __unused,
1794                                                        audio_session_t triggerSession __unused)
1795{
1796    return NO_ERROR;
1797}
1798
1799void AudioFlinger::MmapThread::MmapTrack::stop()
1800{
1801}
1802
1803// AudioBufferProvider interface
1804status_t AudioFlinger::MmapThread::MmapTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
1805{
1806    buffer->frameCount = 0;
1807    buffer->raw = nullptr;
1808    return INVALID_OPERATION;
1809}
1810
1811// ExtendedAudioBufferProvider interface
1812size_t AudioFlinger::MmapThread::MmapTrack::framesReady() const {
1813    return 0;
1814}
1815
1816int64_t AudioFlinger::MmapThread::MmapTrack::framesReleased() const
1817{
1818    return 0;
1819}
1820
1821void AudioFlinger::MmapThread::MmapTrack::onTimestamp(const ExtendedTimestamp &timestamp __unused)
1822{
1823}
1824
1825/*static*/ void AudioFlinger::MmapThread::MmapTrack::appendDumpHeader(String8& result)
1826{
1827    result.append("    Client Fmt Chn mask  SRate\n");
1828}
1829
1830void AudioFlinger::MmapThread::MmapTrack::dump(char* buffer, size_t size)
1831{
1832    snprintf(buffer, size, "            %6u %3u    %08X %5u\n",
1833            mUid,
1834            mFormat,
1835            mChannelMask,
1836            mSampleRate);
1837
1838}
1839
1840} // namespace android
1841