blob: d8f34230bdbb5e3d60f5af0a58313b47afd48a98 [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
Glenn Kasten153b9fe2013-07-15 11:23:36 -070022#include "Configuration.h"
Eric Laurent81784c32012-11-19 14:55:58 -080023#include <math.h>
Eric Laurent81784c32012-11-19 14:55:58 -080024#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
Glenn Kastenda6ef132013-01-10 12:31:01 -080035#include <media/nbaio/Pipe.h>
36#include <media/nbaio/PipeReader.h>
37
Eric Laurent81784c32012-11-19 14:55:58 -080038// ----------------------------------------------------------------------------
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
53namespace android {
54
55// ----------------------------------------------------------------------------
56// TrackBase
57// ----------------------------------------------------------------------------
58
Glenn Kastenda6ef132013-01-10 12:31:01 -080059static volatile int32_t nextTrackId = 55;
60
Eric Laurent81784c32012-11-19 14:55:58 -080061// TrackBase constructor must be called with AudioFlinger::mLock held
62AudioFlinger::ThreadBase::TrackBase::TrackBase(
63 ThreadBase *thread,
64 const sp<Client>& client,
65 uint32_t sampleRate,
66 audio_format_t format,
67 audio_channel_mask_t channelMask,
68 size_t frameCount,
69 const sp<IMemory>& sharedBuffer,
Glenn Kastene3aa6592012-12-04 12:22:46 -080070 int sessionId,
Marco Nelissen462fd2f2013-01-14 14:12:05 -080071 int clientUid,
Glenn Kastend776ac62014-05-07 09:16:09 -070072 bool isOut,
73 bool useReadOnlyHeap)
Eric Laurent81784c32012-11-19 14:55:58 -080074 : RefBase(),
75 mThread(thread),
76 mClient(client),
77 mCblk(NULL),
78 // mBuffer
Eric Laurent81784c32012-11-19 14:55:58 -080079 mState(IDLE),
80 mSampleRate(sampleRate),
81 mFormat(format),
82 mChannelMask(channelMask),
83 mChannelCount(popcount(channelMask)),
84 mFrameSize(audio_is_linear_pcm(format) ?
85 mChannelCount * audio_bytes_per_sample(format) : sizeof(int8_t)),
86 mFrameCount(frameCount),
Glenn Kastene3aa6592012-12-04 12:22:46 -080087 mSessionId(sessionId),
88 mIsOut(isOut),
Glenn Kastenda6ef132013-01-10 12:31:01 -080089 mServerProxy(NULL),
Eric Laurentbfb1b832013-01-07 09:53:42 -080090 mId(android_atomic_inc(&nextTrackId)),
91 mTerminated(false)
Eric Laurent81784c32012-11-19 14:55:58 -080092{
Marco Nelissen462fd2f2013-01-14 14:12:05 -080093 // if the caller is us, trust the specified uid
94 if (IPCThreadState::self()->getCallingPid() != getpid_cached || clientUid == -1) {
95 int newclientUid = IPCThreadState::self()->getCallingUid();
96 if (clientUid != -1 && clientUid != newclientUid) {
97 ALOGW("uid %d tried to pass itself off as %d", newclientUid, clientUid);
98 }
99 clientUid = newclientUid;
100 }
101 // clientUid contains the uid of the app that is responsible for this track, so we can blame
102 // battery usage on it.
103 mUid = clientUid;
104
Eric Laurent81784c32012-11-19 14:55:58 -0800105 // client == 0 implies sharedBuffer == 0
106 ALOG_ASSERT(!(client == 0 && sharedBuffer != 0));
107
108 ALOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(),
109 sharedBuffer->size());
110
111 // ALOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
112 size_t size = sizeof(audio_track_cblk_t);
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800113 size_t bufferSize = (sharedBuffer == 0 ? roundup(frameCount) : frameCount) * mFrameSize;
Glenn Kastend776ac62014-05-07 09:16:09 -0700114 if (sharedBuffer == 0 && !useReadOnlyHeap) {
Eric Laurent81784c32012-11-19 14:55:58 -0800115 size += bufferSize;
116 }
117
118 if (client != 0) {
119 mCblkMemory = client->heap()->allocate(size);
Glenn Kasten663c2242013-09-24 11:52:37 -0700120 if (mCblkMemory == 0 ||
121 (mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer())) == NULL) {
Eric Laurent81784c32012-11-19 14:55:58 -0800122 ALOGE("not enough memory for AudioTrack size=%u", size);
123 client->heap()->dump("AudioTrack");
Glenn Kasten663c2242013-09-24 11:52:37 -0700124 mCblkMemory.clear();
Eric Laurent81784c32012-11-19 14:55:58 -0800125 return;
126 }
127 } else {
Glenn Kastene3aa6592012-12-04 12:22:46 -0800128 // this syntax avoids calling the audio_track_cblk_t constructor twice
129 mCblk = (audio_track_cblk_t *) new uint8_t[size];
Eric Laurent81784c32012-11-19 14:55:58 -0800130 // assume mCblk != NULL
131 }
132
133 // construct the shared structure in-place.
134 if (mCblk != NULL) {
135 new(mCblk) audio_track_cblk_t();
Glenn Kastend776ac62014-05-07 09:16:09 -0700136 if (useReadOnlyHeap) {
137 const sp<MemoryDealer> roHeap(thread->readOnlyHeap());
138 if (roHeap == 0 ||
139 (mBufferMemory = roHeap->allocate(bufferSize)) == 0 ||
140 (mBuffer = mBufferMemory->pointer()) == NULL) {
141 ALOGE("not enough memory for read-only buffer size=%zu", bufferSize);
142 if (roHeap != 0) {
143 roHeap->dump("buffer");
144 }
145 mCblkMemory.clear();
146 mBufferMemory.clear();
147 return;
148 }
Eric Laurent81784c32012-11-19 14:55:58 -0800149 memset(mBuffer, 0, bufferSize);
Eric Laurent81784c32012-11-19 14:55:58 -0800150 } else {
Glenn Kastend776ac62014-05-07 09:16:09 -0700151 // clear all buffers
152 if (sharedBuffer == 0) {
153 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
154 memset(mBuffer, 0, bufferSize);
155 } else {
156 mBuffer = sharedBuffer->pointer();
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800157#if 0
Glenn Kastend776ac62014-05-07 09:16:09 -0700158 mCblk->mFlags = CBLK_FORCEREADY; // FIXME hack, need to fix the track ready logic
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800159#endif
Glenn Kastend776ac62014-05-07 09:16:09 -0700160 }
Eric Laurent81784c32012-11-19 14:55:58 -0800161 }
Glenn Kastenda6ef132013-01-10 12:31:01 -0800162
Glenn Kasten46909e72013-02-26 09:20:22 -0800163#ifdef TEE_SINK
Glenn Kastenda6ef132013-01-10 12:31:01 -0800164 if (mTeeSinkTrackEnabled) {
Glenn Kasten46909e72013-02-26 09:20:22 -0800165 NBAIO_Format pipeFormat = Format_from_SR_C(mSampleRate, mChannelCount);
Glenn Kasten6e0d67d2014-01-31 09:41:08 -0800166 if (Format_isValid(pipeFormat)) {
Glenn Kasten46909e72013-02-26 09:20:22 -0800167 Pipe *pipe = new Pipe(mTeeSinkTrackFrames, pipeFormat);
168 size_t numCounterOffers = 0;
169 const NBAIO_Format offers[1] = {pipeFormat};
170 ssize_t index = pipe->negotiate(offers, 1, NULL, numCounterOffers);
171 ALOG_ASSERT(index == 0);
172 PipeReader *pipeReader = new PipeReader(*pipe);
173 numCounterOffers = 0;
174 index = pipeReader->negotiate(offers, 1, NULL, numCounterOffers);
175 ALOG_ASSERT(index == 0);
176 mTeeSink = pipe;
177 mTeeSource = pipeReader;
178 }
Glenn Kastenda6ef132013-01-10 12:31:01 -0800179 }
Glenn Kasten46909e72013-02-26 09:20:22 -0800180#endif
Glenn Kastenda6ef132013-01-10 12:31:01 -0800181
Eric Laurent81784c32012-11-19 14:55:58 -0800182 }
183}
184
185AudioFlinger::ThreadBase::TrackBase::~TrackBase()
186{
Glenn Kasten46909e72013-02-26 09:20:22 -0800187#ifdef TEE_SINK
Glenn Kastenda6ef132013-01-10 12:31:01 -0800188 dumpTee(-1, mTeeSource, mId);
Glenn Kasten46909e72013-02-26 09:20:22 -0800189#endif
Glenn Kastene3aa6592012-12-04 12:22:46 -0800190 // delete the proxy before deleting the shared memory it refers to, to avoid dangling reference
191 delete mServerProxy;
Eric Laurent81784c32012-11-19 14:55:58 -0800192 if (mCblk != NULL) {
193 if (mClient == 0) {
194 delete mCblk;
195 } else {
196 mCblk->~audio_track_cblk_t(); // destroy our shared-structure.
197 }
198 }
199 mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
200 if (mClient != 0) {
201 // Client destructor must run with AudioFlinger mutex locked
202 Mutex::Autolock _l(mClient->audioFlinger()->mLock);
203 // If the client's reference count drops to zero, the associated destructor
204 // must run with AudioFlinger lock held. Thus the explicit clear() rather than
205 // relying on the automatic clear() at end of scope.
206 mClient.clear();
207 }
208}
209
210// AudioBufferProvider interface
211// getNextBuffer() = 0;
212// This implementation of releaseBuffer() is used by Track and RecordTrack, but not TimedTrack
213void AudioFlinger::ThreadBase::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
214{
Glenn Kasten46909e72013-02-26 09:20:22 -0800215#ifdef TEE_SINK
Glenn Kastenda6ef132013-01-10 12:31:01 -0800216 if (mTeeSink != 0) {
217 (void) mTeeSink->write(buffer->raw, buffer->frameCount);
218 }
Glenn Kasten46909e72013-02-26 09:20:22 -0800219#endif
Glenn Kastenda6ef132013-01-10 12:31:01 -0800220
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800221 ServerProxy::Buffer buf;
222 buf.mFrameCount = buffer->frameCount;
223 buf.mRaw = buffer->raw;
Eric Laurent81784c32012-11-19 14:55:58 -0800224 buffer->frameCount = 0;
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800225 buffer->raw = NULL;
226 mServerProxy->releaseBuffer(&buf);
Eric Laurent81784c32012-11-19 14:55:58 -0800227}
228
Eric Laurent81784c32012-11-19 14:55:58 -0800229status_t AudioFlinger::ThreadBase::TrackBase::setSyncEvent(const sp<SyncEvent>& event)
230{
231 mSyncEvents.add(event);
232 return NO_ERROR;
233}
234
235// ----------------------------------------------------------------------------
236// Playback
237// ----------------------------------------------------------------------------
238
239AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::PlaybackThread::Track>& track)
240 : BnAudioTrack(),
241 mTrack(track)
242{
243}
244
245AudioFlinger::TrackHandle::~TrackHandle() {
246 // just stop the track on deletion, associated resources
247 // will be freed from the main thread once all pending buffers have
248 // been played. Unless it's not in the active track list, in which
249 // case we free everything now...
250 mTrack->destroy();
251}
252
253sp<IMemory> AudioFlinger::TrackHandle::getCblk() const {
254 return mTrack->getCblk();
255}
256
257status_t AudioFlinger::TrackHandle::start() {
258 return mTrack->start();
259}
260
261void AudioFlinger::TrackHandle::stop() {
262 mTrack->stop();
263}
264
265void AudioFlinger::TrackHandle::flush() {
266 mTrack->flush();
267}
268
Eric Laurent81784c32012-11-19 14:55:58 -0800269void AudioFlinger::TrackHandle::pause() {
270 mTrack->pause();
271}
272
273status_t AudioFlinger::TrackHandle::attachAuxEffect(int EffectId)
274{
275 return mTrack->attachAuxEffect(EffectId);
276}
277
278status_t AudioFlinger::TrackHandle::allocateTimedBuffer(size_t size,
279 sp<IMemory>* buffer) {
280 if (!mTrack->isTimedTrack())
281 return INVALID_OPERATION;
282
283 PlaybackThread::TimedTrack* tt =
284 reinterpret_cast<PlaybackThread::TimedTrack*>(mTrack.get());
285 return tt->allocateTimedBuffer(size, buffer);
286}
287
288status_t AudioFlinger::TrackHandle::queueTimedBuffer(const sp<IMemory>& buffer,
289 int64_t pts) {
290 if (!mTrack->isTimedTrack())
291 return INVALID_OPERATION;
292
Glenn Kasten663c2242013-09-24 11:52:37 -0700293 if (buffer == 0 || buffer->pointer() == NULL) {
294 ALOGE("queueTimedBuffer() buffer is 0 or has NULL pointer()");
295 return BAD_VALUE;
296 }
297
Eric Laurent81784c32012-11-19 14:55:58 -0800298 PlaybackThread::TimedTrack* tt =
299 reinterpret_cast<PlaybackThread::TimedTrack*>(mTrack.get());
300 return tt->queueTimedBuffer(buffer, pts);
301}
302
303status_t AudioFlinger::TrackHandle::setMediaTimeTransform(
304 const LinearTransform& xform, int target) {
305
306 if (!mTrack->isTimedTrack())
307 return INVALID_OPERATION;
308
309 PlaybackThread::TimedTrack* tt =
310 reinterpret_cast<PlaybackThread::TimedTrack*>(mTrack.get());
311 return tt->setMediaTimeTransform(
312 xform, static_cast<TimedAudioTrack::TargetTimeline>(target));
313}
314
Glenn Kasten3dcd00d2013-07-17 10:10:23 -0700315status_t AudioFlinger::TrackHandle::setParameters(const String8& keyValuePairs) {
316 return mTrack->setParameters(keyValuePairs);
317}
318
Glenn Kasten53cec222013-08-29 09:01:02 -0700319status_t AudioFlinger::TrackHandle::getTimestamp(AudioTimestamp& timestamp)
320{
Glenn Kasten573d80a2013-08-26 09:36:23 -0700321 return mTrack->getTimestamp(timestamp);
Glenn Kasten53cec222013-08-29 09:01:02 -0700322}
323
Eric Laurent59fe0102013-09-27 18:48:26 -0700324
325void AudioFlinger::TrackHandle::signal()
326{
327 return mTrack->signal();
328}
329
Eric Laurent81784c32012-11-19 14:55:58 -0800330status_t AudioFlinger::TrackHandle::onTransact(
331 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
332{
333 return BnAudioTrack::onTransact(code, data, reply, flags);
334}
335
336// ----------------------------------------------------------------------------
337
338// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
339AudioFlinger::PlaybackThread::Track::Track(
340 PlaybackThread *thread,
341 const sp<Client>& client,
342 audio_stream_type_t streamType,
343 uint32_t sampleRate,
344 audio_format_t format,
345 audio_channel_mask_t channelMask,
346 size_t frameCount,
347 const sp<IMemory>& sharedBuffer,
348 int sessionId,
Marco Nelissen462fd2f2013-01-14 14:12:05 -0800349 int uid,
Eric Laurent81784c32012-11-19 14:55:58 -0800350 IAudioFlinger::track_flags_t flags)
351 : TrackBase(thread, client, sampleRate, format, channelMask, frameCount, sharedBuffer,
Marco Nelissen462fd2f2013-01-14 14:12:05 -0800352 sessionId, uid, true /*isOut*/),
Eric Laurent81784c32012-11-19 14:55:58 -0800353 mFillingUpStatus(FS_INVALID),
354 // mRetryCount initialized later when needed
355 mSharedBuffer(sharedBuffer),
356 mStreamType(streamType),
357 mName(-1), // see note below
358 mMainBuffer(thread->mixBuffer()),
359 mAuxBuffer(NULL),
360 mAuxEffectId(0), mHasVolumeController(false),
361 mPresentationCompleteFrames(0),
362 mFlags(flags),
363 mFastIndex(-1),
Glenn Kasten5736c352012-12-04 12:12:34 -0800364 mCachedVolume(1.0),
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800365 mIsInvalid(false),
Eric Laurentbfb1b832013-01-07 09:53:42 -0800366 mAudioTrackServerProxy(NULL),
Haynes Mathew George7844f672014-01-15 12:32:55 -0800367 mResumeToStopping(false),
368 mFlushHwPending(false)
Eric Laurent81784c32012-11-19 14:55:58 -0800369{
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700370 if (mCblk == NULL) {
371 return;
Eric Laurent81784c32012-11-19 14:55:58 -0800372 }
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700373
374 if (sharedBuffer == 0) {
375 mAudioTrackServerProxy = new AudioTrackServerProxy(mCblk, mBuffer, frameCount,
376 mFrameSize);
377 } else {
378 mAudioTrackServerProxy = new StaticAudioTrackServerProxy(mCblk, mBuffer, frameCount,
379 mFrameSize);
380 }
381 mServerProxy = mAudioTrackServerProxy;
382
383 mName = thread->getTrackName_l(channelMask, sessionId);
384 if (mName < 0) {
385 ALOGE("no more track names available");
386 return;
387 }
388 // only allocate a fast track index if we were able to allocate a normal track name
389 if (flags & IAudioFlinger::TRACK_FAST) {
390 mAudioTrackServerProxy->framesReadyIsCalledByMultipleThreads();
391 ALOG_ASSERT(thread->mFastTrackAvailMask != 0);
392 int i = __builtin_ctz(thread->mFastTrackAvailMask);
393 ALOG_ASSERT(0 < i && i < (int)FastMixerState::kMaxFastTracks);
394 // FIXME This is too eager. We allocate a fast track index before the
395 // fast track becomes active. Since fast tracks are a scarce resource,
396 // this means we are potentially denying other more important fast tracks from
397 // being created. It would be better to allocate the index dynamically.
398 mFastIndex = i;
399 // Read the initial underruns because this field is never cleared by the fast mixer
400 mObservedUnderruns = thread->getFastTrackUnderruns(i);
401 thread->mFastTrackAvailMask &= ~(1 << i);
402 }
Eric Laurent81784c32012-11-19 14:55:58 -0800403}
404
405AudioFlinger::PlaybackThread::Track::~Track()
406{
407 ALOGV("PlaybackThread::Track destructor");
Glenn Kasten0c72b242013-09-11 09:14:16 -0700408
409 // The destructor would clear mSharedBuffer,
410 // but it will not push the decremented reference count,
411 // leaving the client's IMemory dangling indefinitely.
412 // This prevents that leak.
413 if (mSharedBuffer != 0) {
414 mSharedBuffer.clear();
415 // flush the binder command buffer
416 IPCThreadState::self()->flushCommands();
417 }
Eric Laurent81784c32012-11-19 14:55:58 -0800418}
419
Glenn Kasten03003332013-08-06 15:40:54 -0700420status_t AudioFlinger::PlaybackThread::Track::initCheck() const
421{
422 status_t status = TrackBase::initCheck();
423 if (status == NO_ERROR && mName < 0) {
424 status = NO_MEMORY;
425 }
426 return status;
427}
428
Eric Laurent81784c32012-11-19 14:55:58 -0800429void AudioFlinger::PlaybackThread::Track::destroy()
430{
431 // NOTE: destroyTrack_l() can remove a strong reference to this Track
432 // by removing it from mTracks vector, so there is a risk that this Tracks's
433 // destructor is called. As the destructor needs to lock mLock,
434 // we must acquire a strong reference on this Track before locking mLock
435 // here so that the destructor is called only when exiting this function.
436 // On the other hand, as long as Track::destroy() is only called by
437 // TrackHandle destructor, the TrackHandle still holds a strong ref on
438 // this Track with its member mTrack.
439 sp<Track> keep(this);
440 { // scope for mLock
441 sp<ThreadBase> thread = mThread.promote();
442 if (thread != 0) {
Eric Laurent81784c32012-11-19 14:55:58 -0800443 Mutex::Autolock _l(thread->mLock);
444 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
Eric Laurentbfb1b832013-01-07 09:53:42 -0800445 bool wasActive = playbackThread->destroyTrack_l(this);
446 if (!isOutputTrack() && !wasActive) {
447 AudioSystem::releaseOutput(thread->id());
448 }
Eric Laurent81784c32012-11-19 14:55:58 -0800449 }
450 }
451}
452
453/*static*/ void AudioFlinger::PlaybackThread::Track::appendDumpHeader(String8& result)
454{
Marco Nelissenb2208842014-02-07 14:00:50 -0800455 result.append(" Name Active Client Type Fmt Chn mask Session fCount S F SRate "
Glenn Kasten82aaf942013-07-17 16:05:07 -0700456 "L dB R dB Server Main buf Aux Buf Flags UndFrmCnt\n");
Eric Laurent81784c32012-11-19 14:55:58 -0800457}
458
Marco Nelissenb2208842014-02-07 14:00:50 -0800459void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size, bool active)
Eric Laurent81784c32012-11-19 14:55:58 -0800460{
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800461 uint32_t vlr = mAudioTrackServerProxy->getVolumeLR();
Eric Laurent81784c32012-11-19 14:55:58 -0800462 if (isFastTrack()) {
Marco Nelissenb2208842014-02-07 14:00:50 -0800463 sprintf(buffer, " F %2d", mFastIndex);
464 } else if (mName >= AudioMixer::TRACK0) {
465 sprintf(buffer, " %4d", mName - AudioMixer::TRACK0);
Eric Laurent81784c32012-11-19 14:55:58 -0800466 } else {
Marco Nelissenb2208842014-02-07 14:00:50 -0800467 sprintf(buffer, " none");
Eric Laurent81784c32012-11-19 14:55:58 -0800468 }
469 track_state state = mState;
470 char stateChar;
Eric Laurentbfb1b832013-01-07 09:53:42 -0800471 if (isTerminated()) {
Eric Laurent81784c32012-11-19 14:55:58 -0800472 stateChar = 'T';
Eric Laurentbfb1b832013-01-07 09:53:42 -0800473 } else {
474 switch (state) {
475 case IDLE:
476 stateChar = 'I';
477 break;
478 case STOPPING_1:
479 stateChar = 's';
480 break;
481 case STOPPING_2:
482 stateChar = '5';
483 break;
484 case STOPPED:
485 stateChar = 'S';
486 break;
487 case RESUMING:
488 stateChar = 'R';
489 break;
490 case ACTIVE:
491 stateChar = 'A';
492 break;
493 case PAUSING:
494 stateChar = 'p';
495 break;
496 case PAUSED:
497 stateChar = 'P';
498 break;
499 case FLUSHED:
500 stateChar = 'F';
501 break;
502 default:
503 stateChar = '?';
504 break;
505 }
Eric Laurent81784c32012-11-19 14:55:58 -0800506 }
507 char nowInUnderrun;
508 switch (mObservedUnderruns.mBitFields.mMostRecent) {
509 case UNDERRUN_FULL:
510 nowInUnderrun = ' ';
511 break;
512 case UNDERRUN_PARTIAL:
513 nowInUnderrun = '<';
514 break;
515 case UNDERRUN_EMPTY:
516 nowInUnderrun = '*';
517 break;
518 default:
519 nowInUnderrun = '?';
520 break;
521 }
Narayan Kamath1d6fa7a2014-02-11 13:47:53 +0000522 snprintf(&buffer[8], size-8, " %6s %6u %4u %08X %08X %7u %6zu %1c %1d %5u %5.2g %5.2g "
Kévin PETIT377b2ec2014-02-03 12:35:36 +0000523 "%08X %p %p 0x%03X %9u%c\n",
Marco Nelissenb2208842014-02-07 14:00:50 -0800524 active ? "yes" : "no",
Eric Laurent81784c32012-11-19 14:55:58 -0800525 (mClient == 0) ? getpid_cached : mClient->pid(),
526 mStreamType,
527 mFormat,
528 mChannelMask,
529 mSessionId,
Eric Laurent81784c32012-11-19 14:55:58 -0800530 mFrameCount,
531 stateChar,
Eric Laurent81784c32012-11-19 14:55:58 -0800532 mFillingUpStatus,
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800533 mAudioTrackServerProxy->getSampleRate(),
Eric Laurent81784c32012-11-19 14:55:58 -0800534 20.0 * log10((vlr & 0xFFFF) / 4096.0),
535 20.0 * log10((vlr >> 16) / 4096.0),
Glenn Kastenf20e1d82013-07-12 09:45:18 -0700536 mCblk->mServer,
Kévin PETIT377b2ec2014-02-03 12:35:36 +0000537 mMainBuffer,
538 mAuxBuffer,
Glenn Kasten96f60d82013-07-12 10:21:18 -0700539 mCblk->mFlags,
Glenn Kasten82aaf942013-07-17 16:05:07 -0700540 mAudioTrackServerProxy->getUnderrunFrames(),
Eric Laurent81784c32012-11-19 14:55:58 -0800541 nowInUnderrun);
542}
543
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800544uint32_t AudioFlinger::PlaybackThread::Track::sampleRate() const {
545 return mAudioTrackServerProxy->getSampleRate();
546}
547
Eric Laurent81784c32012-11-19 14:55:58 -0800548// AudioBufferProvider interface
549status_t AudioFlinger::PlaybackThread::Track::getNextBuffer(
Glenn Kasten0f11b512014-01-31 16:18:54 -0800550 AudioBufferProvider::Buffer* buffer, int64_t pts __unused)
Eric Laurent81784c32012-11-19 14:55:58 -0800551{
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800552 ServerProxy::Buffer buf;
553 size_t desiredFrames = buffer->frameCount;
554 buf.mFrameCount = desiredFrames;
555 status_t status = mServerProxy->obtainBuffer(&buf);
556 buffer->frameCount = buf.mFrameCount;
557 buffer->raw = buf.mRaw;
558 if (buf.mFrameCount == 0) {
Glenn Kasten82aaf942013-07-17 16:05:07 -0700559 mAudioTrackServerProxy->tallyUnderrunFrames(desiredFrames);
Eric Laurent81784c32012-11-19 14:55:58 -0800560 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800561 return status;
Eric Laurent81784c32012-11-19 14:55:58 -0800562}
563
Glenn Kasten6466c9e2013-08-23 10:54:07 -0700564// releaseBuffer() is not overridden
565
566// ExtendedAudioBufferProvider interface
567
Eric Laurent81784c32012-11-19 14:55:58 -0800568// Note that framesReady() takes a mutex on the control block using tryLock().
569// This could result in priority inversion if framesReady() is called by the normal mixer,
570// as the normal mixer thread runs at lower
571// priority than the client's callback thread: there is a short window within framesReady()
572// during which the normal mixer could be preempted, and the client callback would block.
573// Another problem can occur if framesReady() is called by the fast mixer:
574// the tryLock() could block for up to 1 ms, and a sequence of these could delay fast mixer.
575// FIXME Replace AudioTrackShared control block implementation by a non-blocking FIFO queue.
576size_t AudioFlinger::PlaybackThread::Track::framesReady() const {
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800577 return mAudioTrackServerProxy->framesReady();
Eric Laurent81784c32012-11-19 14:55:58 -0800578}
579
Glenn Kasten6466c9e2013-08-23 10:54:07 -0700580size_t AudioFlinger::PlaybackThread::Track::framesReleased() const
581{
582 return mAudioTrackServerProxy->framesReleased();
583}
584
Eric Laurent81784c32012-11-19 14:55:58 -0800585// Don't call for fast tracks; the framesReady() could result in priority inversion
586bool AudioFlinger::PlaybackThread::Track::isReady() const {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -0800587 if (mFillingUpStatus != FS_FILLING || isStopped() || isPausing()) {
588 return true;
589 }
590
Eric Laurent16498512014-03-17 17:22:08 -0700591 if (isStopping()) {
592 if (framesReady() > 0) {
593 mFillingUpStatus = FS_FILLED;
594 }
Eric Laurent81784c32012-11-19 14:55:58 -0800595 return true;
596 }
597
598 if (framesReady() >= mFrameCount ||
Glenn Kasten96f60d82013-07-12 10:21:18 -0700599 (mCblk->mFlags & CBLK_FORCEREADY)) {
Eric Laurent81784c32012-11-19 14:55:58 -0800600 mFillingUpStatus = FS_FILLED;
Glenn Kasten96f60d82013-07-12 10:21:18 -0700601 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -0800602 return true;
603 }
604 return false;
605}
606
Glenn Kasten0f11b512014-01-31 16:18:54 -0800607status_t AudioFlinger::PlaybackThread::Track::start(AudioSystem::sync_event_t event __unused,
608 int triggerSession __unused)
Eric Laurent81784c32012-11-19 14:55:58 -0800609{
610 status_t status = NO_ERROR;
611 ALOGV("start(%d), calling pid %d session %d",
612 mName, IPCThreadState::self()->getCallingPid(), mSessionId);
613
614 sp<ThreadBase> thread = mThread.promote();
615 if (thread != 0) {
Eric Laurent813e2a72013-08-31 12:59:48 -0700616 if (isOffloaded()) {
617 Mutex::Autolock _laf(thread->mAudioFlinger->mLock);
618 Mutex::Autolock _lth(thread->mLock);
619 sp<EffectChain> ec = thread->getEffectChain_l(mSessionId);
Eric Laurent5baf2af2013-09-12 17:37:00 -0700620 if (thread->mAudioFlinger->isNonOffloadableGlobalEffectEnabled_l() ||
621 (ec != 0 && ec->isNonOffloadableEnabled())) {
Eric Laurent813e2a72013-08-31 12:59:48 -0700622 invalidate();
623 return PERMISSION_DENIED;
624 }
625 }
626 Mutex::Autolock _lth(thread->mLock);
Eric Laurent81784c32012-11-19 14:55:58 -0800627 track_state state = mState;
628 // here the track could be either new, or restarted
629 // in both cases "unstop" the track
Eric Laurentbfb1b832013-01-07 09:53:42 -0800630
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -0800631 // initial state-stopping. next state-pausing.
632 // What if resume is called ?
633
634 if (state == PAUSED || state == PAUSING) {
Eric Laurentbfb1b832013-01-07 09:53:42 -0800635 if (mResumeToStopping) {
636 // happened we need to resume to STOPPING_1
637 mState = TrackBase::STOPPING_1;
638 ALOGV("PAUSED => STOPPING_1 (%d) on thread %p", mName, this);
639 } else {
640 mState = TrackBase::RESUMING;
641 ALOGV("PAUSED => RESUMING (%d) on thread %p", mName, this);
642 }
Eric Laurent81784c32012-11-19 14:55:58 -0800643 } else {
644 mState = TrackBase::ACTIVE;
645 ALOGV("? => ACTIVE (%d) on thread %p", mName, this);
646 }
647
Eric Laurentbfb1b832013-01-07 09:53:42 -0800648 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
649 status = playbackThread->addTrack_l(this);
650 if (status == INVALID_OPERATION || status == PERMISSION_DENIED) {
Eric Laurent81784c32012-11-19 14:55:58 -0800651 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
Eric Laurentbfb1b832013-01-07 09:53:42 -0800652 // restore previous state if start was rejected by policy manager
653 if (status == PERMISSION_DENIED) {
654 mState = state;
655 }
656 }
657 // track was already in the active list, not a problem
658 if (status == ALREADY_EXISTS) {
659 status = NO_ERROR;
Glenn Kasten12022ff2013-10-17 11:32:39 -0700660 } else {
661 // Acknowledge any pending flush(), so that subsequent new data isn't discarded.
662 // It is usually unsafe to access the server proxy from a binder thread.
663 // But in this case we know the mixer thread (whether normal mixer or fast mixer)
664 // isn't looking at this track yet: we still hold the normal mixer thread lock,
665 // and for fast tracks the track is not yet in the fast mixer thread's active set.
666 ServerProxy::Buffer buffer;
667 buffer.mFrameCount = 1;
Glenn Kasten2e422c42013-10-18 13:00:29 -0700668 (void) mAudioTrackServerProxy->obtainBuffer(&buffer, true /*ackFlush*/);
Eric Laurent81784c32012-11-19 14:55:58 -0800669 }
670 } else {
671 status = BAD_VALUE;
672 }
673 return status;
674}
675
676void AudioFlinger::PlaybackThread::Track::stop()
677{
678 ALOGV("stop(%d), calling pid %d", mName, IPCThreadState::self()->getCallingPid());
679 sp<ThreadBase> thread = mThread.promote();
680 if (thread != 0) {
681 Mutex::Autolock _l(thread->mLock);
682 track_state state = mState;
683 if (state == RESUMING || state == ACTIVE || state == PAUSING || state == PAUSED) {
684 // If the track is not active (PAUSED and buffers full), flush buffers
685 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
686 if (playbackThread->mActiveTracks.indexOf(this) < 0) {
687 reset();
688 mState = STOPPED;
Eric Laurentbfb1b832013-01-07 09:53:42 -0800689 } else if (!isFastTrack() && !isOffloaded()) {
Eric Laurent81784c32012-11-19 14:55:58 -0800690 mState = STOPPED;
691 } else {
Eric Laurentbfb1b832013-01-07 09:53:42 -0800692 // For fast tracks prepareTracks_l() will set state to STOPPING_2
693 // presentation is complete
694 // For an offloaded track this starts a drain and state will
695 // move to STOPPING_2 when drain completes and then STOPPED
Eric Laurent81784c32012-11-19 14:55:58 -0800696 mState = STOPPING_1;
697 }
698 ALOGV("not stopping/stopped => stopping/stopped (%d) on thread %p", mName,
699 playbackThread);
700 }
Eric Laurent81784c32012-11-19 14:55:58 -0800701 }
702}
703
704void AudioFlinger::PlaybackThread::Track::pause()
705{
706 ALOGV("pause(%d), calling pid %d", mName, IPCThreadState::self()->getCallingPid());
707 sp<ThreadBase> thread = mThread.promote();
708 if (thread != 0) {
709 Mutex::Autolock _l(thread->mLock);
Eric Laurentbfb1b832013-01-07 09:53:42 -0800710 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
711 switch (mState) {
712 case STOPPING_1:
713 case STOPPING_2:
714 if (!isOffloaded()) {
715 /* nothing to do if track is not offloaded */
716 break;
717 }
718
719 // Offloaded track was draining, we need to carry on draining when resumed
720 mResumeToStopping = true;
721 // fall through...
722 case ACTIVE:
723 case RESUMING:
Eric Laurent81784c32012-11-19 14:55:58 -0800724 mState = PAUSING;
725 ALOGV("ACTIVE/RESUMING => PAUSING (%d) on thread %p", mName, thread.get());
Eric Laurentede6c3b2013-09-19 14:37:46 -0700726 playbackThread->broadcast_l();
Eric Laurentbfb1b832013-01-07 09:53:42 -0800727 break;
Eric Laurent81784c32012-11-19 14:55:58 -0800728
Eric Laurentbfb1b832013-01-07 09:53:42 -0800729 default:
730 break;
Eric Laurent81784c32012-11-19 14:55:58 -0800731 }
732 }
733}
734
735void AudioFlinger::PlaybackThread::Track::flush()
736{
737 ALOGV("flush(%d)", mName);
738 sp<ThreadBase> thread = mThread.promote();
739 if (thread != 0) {
740 Mutex::Autolock _l(thread->mLock);
Eric Laurent81784c32012-11-19 14:55:58 -0800741 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
Eric Laurentbfb1b832013-01-07 09:53:42 -0800742
743 if (isOffloaded()) {
744 // If offloaded we allow flush during any state except terminated
745 // and keep the track active to avoid problems if user is seeking
746 // rapidly and underlying hardware has a significant delay handling
747 // a pause
748 if (isTerminated()) {
749 return;
750 }
751
752 ALOGV("flush: offload flush");
Eric Laurent81784c32012-11-19 14:55:58 -0800753 reset();
Eric Laurentbfb1b832013-01-07 09:53:42 -0800754
755 if (mState == STOPPING_1 || mState == STOPPING_2) {
756 ALOGV("flushed in STOPPING_1 or 2 state, change state to ACTIVE");
757 mState = ACTIVE;
758 }
759
760 if (mState == ACTIVE) {
761 ALOGV("flush called in active state, resetting buffer time out retry count");
762 mRetryCount = PlaybackThread::kMaxTrackRetriesOffload;
763 }
764
Haynes Mathew George7844f672014-01-15 12:32:55 -0800765 mFlushHwPending = true;
Eric Laurentbfb1b832013-01-07 09:53:42 -0800766 mResumeToStopping = false;
767 } else {
768 if (mState != STOPPING_1 && mState != STOPPING_2 && mState != STOPPED &&
769 mState != PAUSED && mState != PAUSING && mState != IDLE && mState != FLUSHED) {
770 return;
771 }
772 // No point remaining in PAUSED state after a flush => go to
773 // FLUSHED state
774 mState = FLUSHED;
775 // do not reset the track if it is still in the process of being stopped or paused.
776 // this will be done by prepareTracks_l() when the track is stopped.
777 // prepareTracks_l() will see mState == FLUSHED, then
778 // remove from active track list, reset(), and trigger presentation complete
779 if (playbackThread->mActiveTracks.indexOf(this) < 0) {
780 reset();
781 }
Eric Laurent81784c32012-11-19 14:55:58 -0800782 }
Eric Laurentbfb1b832013-01-07 09:53:42 -0800783 // Prevent flush being lost if the track is flushed and then resumed
784 // before mixer thread can run. This is important when offloading
785 // because the hardware buffer could hold a large amount of audio
Eric Laurentede6c3b2013-09-19 14:37:46 -0700786 playbackThread->broadcast_l();
Eric Laurent81784c32012-11-19 14:55:58 -0800787 }
788}
789
Haynes Mathew George7844f672014-01-15 12:32:55 -0800790// must be called with thread lock held
791void AudioFlinger::PlaybackThread::Track::flushAck()
792{
793 if (!isOffloaded())
794 return;
795
796 mFlushHwPending = false;
797}
798
Eric Laurent81784c32012-11-19 14:55:58 -0800799void AudioFlinger::PlaybackThread::Track::reset()
800{
801 // Do not reset twice to avoid discarding data written just after a flush and before
802 // the audioflinger thread detects the track is stopped.
803 if (!mResetDone) {
Eric Laurent81784c32012-11-19 14:55:58 -0800804 // Force underrun condition to avoid false underrun callback until first data is
805 // written to buffer
Glenn Kasten96f60d82013-07-12 10:21:18 -0700806 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -0800807 mFillingUpStatus = FS_FILLING;
808 mResetDone = true;
809 if (mState == FLUSHED) {
810 mState = IDLE;
811 }
812 }
813}
814
Eric Laurentbfb1b832013-01-07 09:53:42 -0800815status_t AudioFlinger::PlaybackThread::Track::setParameters(const String8& keyValuePairs)
816{
817 sp<ThreadBase> thread = mThread.promote();
818 if (thread == 0) {
819 ALOGE("thread is dead");
820 return FAILED_TRANSACTION;
821 } else if ((thread->type() == ThreadBase::DIRECT) ||
822 (thread->type() == ThreadBase::OFFLOAD)) {
823 return thread->setParameters(keyValuePairs);
824 } else {
825 return PERMISSION_DENIED;
826 }
827}
828
Glenn Kasten573d80a2013-08-26 09:36:23 -0700829status_t AudioFlinger::PlaybackThread::Track::getTimestamp(AudioTimestamp& timestamp)
830{
Glenn Kastenfe346c72013-08-30 13:28:22 -0700831 // Client should implement this using SSQ; the unpresented frame count in latch is irrelevant
832 if (isFastTrack()) {
833 return INVALID_OPERATION;
834 }
Glenn Kasten573d80a2013-08-26 09:36:23 -0700835 sp<ThreadBase> thread = mThread.promote();
836 if (thread == 0) {
Glenn Kastenfe346c72013-08-30 13:28:22 -0700837 return INVALID_OPERATION;
Glenn Kasten573d80a2013-08-26 09:36:23 -0700838 }
839 Mutex::Autolock _l(thread->mLock);
840 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
Eric Laurentaccc1472013-09-20 09:36:34 -0700841 if (!isOffloaded()) {
842 if (!playbackThread->mLatchQValid) {
843 return INVALID_OPERATION;
844 }
845 uint32_t unpresentedFrames =
846 ((int64_t) playbackThread->mLatchQ.mUnpresentedFrames * mSampleRate) /
847 playbackThread->mSampleRate;
848 uint32_t framesWritten = mAudioTrackServerProxy->framesReleased();
849 if (framesWritten < unpresentedFrames) {
850 return INVALID_OPERATION;
851 }
852 timestamp.mPosition = framesWritten - unpresentedFrames;
853 timestamp.mTime = playbackThread->mLatchQ.mTimestamp.mTime;
854 return NO_ERROR;
Glenn Kastenbd096fd2013-08-23 13:53:56 -0700855 }
Eric Laurentaccc1472013-09-20 09:36:34 -0700856
857 return playbackThread->getTimestamp_l(timestamp);
Glenn Kasten573d80a2013-08-26 09:36:23 -0700858}
859
Eric Laurent81784c32012-11-19 14:55:58 -0800860status_t AudioFlinger::PlaybackThread::Track::attachAuxEffect(int EffectId)
861{
862 status_t status = DEAD_OBJECT;
863 sp<ThreadBase> thread = mThread.promote();
864 if (thread != 0) {
865 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
866 sp<AudioFlinger> af = mClient->audioFlinger();
867
868 Mutex::Autolock _l(af->mLock);
869
870 sp<PlaybackThread> srcThread = af->getEffectThread_l(AUDIO_SESSION_OUTPUT_MIX, EffectId);
871
872 if (EffectId != 0 && srcThread != 0 && playbackThread != srcThread.get()) {
873 Mutex::Autolock _dl(playbackThread->mLock);
874 Mutex::Autolock _sl(srcThread->mLock);
875 sp<EffectChain> chain = srcThread->getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
876 if (chain == 0) {
877 return INVALID_OPERATION;
878 }
879
880 sp<EffectModule> effect = chain->getEffectFromId_l(EffectId);
881 if (effect == 0) {
882 return INVALID_OPERATION;
883 }
884 srcThread->removeEffect_l(effect);
Eric Laurent5baf2af2013-09-12 17:37:00 -0700885 status = playbackThread->addEffect_l(effect);
886 if (status != NO_ERROR) {
887 srcThread->addEffect_l(effect);
888 return INVALID_OPERATION;
889 }
Eric Laurent81784c32012-11-19 14:55:58 -0800890 // removeEffect_l() has stopped the effect if it was active so it must be restarted
891 if (effect->state() == EffectModule::ACTIVE ||
892 effect->state() == EffectModule::STOPPING) {
893 effect->start();
894 }
895
896 sp<EffectChain> dstChain = effect->chain().promote();
897 if (dstChain == 0) {
898 srcThread->addEffect_l(effect);
899 return INVALID_OPERATION;
900 }
901 AudioSystem::unregisterEffect(effect->id());
902 AudioSystem::registerEffect(&effect->desc(),
903 srcThread->id(),
904 dstChain->strategy(),
905 AUDIO_SESSION_OUTPUT_MIX,
906 effect->id());
Eric Laurentd72b7c02013-10-12 16:17:46 -0700907 AudioSystem::setEffectEnabled(effect->id(), effect->isEnabled());
Eric Laurent81784c32012-11-19 14:55:58 -0800908 }
909 status = playbackThread->attachAuxEffect(this, EffectId);
910 }
911 return status;
912}
913
914void AudioFlinger::PlaybackThread::Track::setAuxBuffer(int EffectId, int32_t *buffer)
915{
916 mAuxEffectId = EffectId;
917 mAuxBuffer = buffer;
918}
919
920bool AudioFlinger::PlaybackThread::Track::presentationComplete(size_t framesWritten,
921 size_t audioHalFrames)
922{
923 // a track is considered presented when the total number of frames written to audio HAL
924 // corresponds to the number of frames written when presentationComplete() is called for the
925 // first time (mPresentationCompleteFrames == 0) plus the buffer filling status at that time.
Eric Laurentbfb1b832013-01-07 09:53:42 -0800926 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
927 // to detect when all frames have been played. In this case framesWritten isn't
928 // useful because it doesn't always reflect whether there is data in the h/w
929 // buffers, particularly if a track has been paused and resumed during draining
930 ALOGV("presentationComplete() mPresentationCompleteFrames %d framesWritten %d",
931 mPresentationCompleteFrames, framesWritten);
Eric Laurent81784c32012-11-19 14:55:58 -0800932 if (mPresentationCompleteFrames == 0) {
933 mPresentationCompleteFrames = framesWritten + audioHalFrames;
934 ALOGV("presentationComplete() reset: mPresentationCompleteFrames %d audioHalFrames %d",
935 mPresentationCompleteFrames, audioHalFrames);
936 }
Eric Laurentbfb1b832013-01-07 09:53:42 -0800937
938 if (framesWritten >= mPresentationCompleteFrames || isOffloaded()) {
Eric Laurent81784c32012-11-19 14:55:58 -0800939 ALOGV("presentationComplete() session %d complete: framesWritten %d",
940 mSessionId, framesWritten);
941 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
Eric Laurentbfb1b832013-01-07 09:53:42 -0800942 mAudioTrackServerProxy->setStreamEndDone();
Eric Laurent81784c32012-11-19 14:55:58 -0800943 return true;
944 }
945 return false;
946}
947
948void AudioFlinger::PlaybackThread::Track::triggerEvents(AudioSystem::sync_event_t type)
949{
Mark Salyzyn3ab368e2014-04-15 14:55:53 -0700950 for (size_t i = 0; i < mSyncEvents.size(); i++) {
Eric Laurent81784c32012-11-19 14:55:58 -0800951 if (mSyncEvents[i]->type() == type) {
952 mSyncEvents[i]->trigger();
953 mSyncEvents.removeAt(i);
954 i--;
955 }
956 }
957}
958
959// implement VolumeBufferProvider interface
960
961uint32_t AudioFlinger::PlaybackThread::Track::getVolumeLR()
962{
963 // called by FastMixer, so not allowed to take any locks, block, or do I/O including logs
964 ALOG_ASSERT(isFastTrack() && (mCblk != NULL));
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800965 uint32_t vlr = mAudioTrackServerProxy->getVolumeLR();
Eric Laurent81784c32012-11-19 14:55:58 -0800966 uint32_t vl = vlr & 0xFFFF;
967 uint32_t vr = vlr >> 16;
968 // track volumes come from shared memory, so can't be trusted and must be clamped
969 if (vl > MAX_GAIN_INT) {
970 vl = MAX_GAIN_INT;
971 }
972 if (vr > MAX_GAIN_INT) {
973 vr = MAX_GAIN_INT;
974 }
975 // now apply the cached master volume and stream type volume;
976 // this is trusted but lacks any synchronization or barrier so may be stale
977 float v = mCachedVolume;
978 vl *= v;
979 vr *= v;
980 // re-combine into U4.16
981 vlr = (vr << 16) | (vl & 0xFFFF);
982 // FIXME look at mute, pause, and stop flags
983 return vlr;
984}
985
986status_t AudioFlinger::PlaybackThread::Track::setSyncEvent(const sp<SyncEvent>& event)
987{
Eric Laurentbfb1b832013-01-07 09:53:42 -0800988 if (isTerminated() || mState == PAUSED ||
Eric Laurent81784c32012-11-19 14:55:58 -0800989 ((framesReady() == 0) && ((mSharedBuffer != 0) ||
990 (mState == STOPPED)))) {
991 ALOGW("Track::setSyncEvent() in invalid state %d on session %d %s mode, framesReady %d ",
992 mState, mSessionId, (mSharedBuffer != 0) ? "static" : "stream", framesReady());
993 event->cancel();
994 return INVALID_OPERATION;
995 }
996 (void) TrackBase::setSyncEvent(event);
997 return NO_ERROR;
998}
999
Glenn Kasten5736c352012-12-04 12:12:34 -08001000void AudioFlinger::PlaybackThread::Track::invalidate()
1001{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001002 // FIXME should use proxy, and needs work
1003 audio_track_cblk_t* cblk = mCblk;
Glenn Kasten96f60d82013-07-12 10:21:18 -07001004 android_atomic_or(CBLK_INVALID, &cblk->mFlags);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001005 android_atomic_release_store(0x40000000, &cblk->mFutex);
1006 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
1007 (void) __futex_syscall3(&cblk->mFutex, FUTEX_WAKE, INT_MAX);
Glenn Kasten5736c352012-12-04 12:12:34 -08001008 mIsInvalid = true;
1009}
1010
Eric Laurent59fe0102013-09-27 18:48:26 -07001011void AudioFlinger::PlaybackThread::Track::signal()
1012{
1013 sp<ThreadBase> thread = mThread.promote();
1014 if (thread != 0) {
1015 PlaybackThread *t = (PlaybackThread *)thread.get();
1016 Mutex::Autolock _l(t->mLock);
1017 t->broadcast_l();
1018 }
1019}
1020
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001021//To be called with thread lock held
1022bool AudioFlinger::PlaybackThread::Track::isResumePending() {
1023
1024 if (mState == RESUMING)
1025 return true;
1026 /* Resume is pending if track was stopping before pause was called */
1027 if (mState == STOPPING_1 &&
1028 mResumeToStopping)
1029 return true;
1030
1031 return false;
1032}
1033
1034//To be called with thread lock held
1035void AudioFlinger::PlaybackThread::Track::resumeAck() {
1036
1037
1038 if (mState == RESUMING)
1039 mState = ACTIVE;
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08001040
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001041 // Other possibility of pending resume is stopping_1 state
1042 // Do not update the state from stopping as this prevents
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08001043 // drain being called.
1044 if (mState == STOPPING_1) {
1045 mResumeToStopping = false;
1046 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001047}
Eric Laurent81784c32012-11-19 14:55:58 -08001048// ----------------------------------------------------------------------------
1049
1050sp<AudioFlinger::PlaybackThread::TimedTrack>
1051AudioFlinger::PlaybackThread::TimedTrack::create(
1052 PlaybackThread *thread,
1053 const sp<Client>& client,
1054 audio_stream_type_t streamType,
1055 uint32_t sampleRate,
1056 audio_format_t format,
1057 audio_channel_mask_t channelMask,
1058 size_t frameCount,
1059 const sp<IMemory>& sharedBuffer,
Marco Nelissen462fd2f2013-01-14 14:12:05 -08001060 int sessionId,
Glenn Kasten4944acb2013-08-19 08:39:20 -07001061 int uid)
1062{
Eric Laurent81784c32012-11-19 14:55:58 -08001063 if (!client->reserveTimedTrack())
1064 return 0;
1065
1066 return new TimedTrack(
1067 thread, client, streamType, sampleRate, format, channelMask, frameCount,
Marco Nelissen462fd2f2013-01-14 14:12:05 -08001068 sharedBuffer, sessionId, uid);
Eric Laurent81784c32012-11-19 14:55:58 -08001069}
1070
1071AudioFlinger::PlaybackThread::TimedTrack::TimedTrack(
1072 PlaybackThread *thread,
1073 const sp<Client>& client,
1074 audio_stream_type_t streamType,
1075 uint32_t sampleRate,
1076 audio_format_t format,
1077 audio_channel_mask_t channelMask,
1078 size_t frameCount,
1079 const sp<IMemory>& sharedBuffer,
Marco Nelissen462fd2f2013-01-14 14:12:05 -08001080 int sessionId,
1081 int uid)
Eric Laurent81784c32012-11-19 14:55:58 -08001082 : Track(thread, client, streamType, sampleRate, format, channelMask,
Marco Nelissen462fd2f2013-01-14 14:12:05 -08001083 frameCount, sharedBuffer, sessionId, uid, IAudioFlinger::TRACK_TIMED),
Eric Laurent81784c32012-11-19 14:55:58 -08001084 mQueueHeadInFlight(false),
1085 mTrimQueueHeadOnRelease(false),
1086 mFramesPendingInQueue(0),
1087 mTimedSilenceBuffer(NULL),
1088 mTimedSilenceBufferSize(0),
1089 mTimedAudioOutputOnTime(false),
1090 mMediaTimeTransformValid(false)
1091{
1092 LocalClock lc;
1093 mLocalTimeFreq = lc.getLocalFreq();
1094
1095 mLocalTimeToSampleTransform.a_zero = 0;
1096 mLocalTimeToSampleTransform.b_zero = 0;
1097 mLocalTimeToSampleTransform.a_to_b_numer = sampleRate;
1098 mLocalTimeToSampleTransform.a_to_b_denom = mLocalTimeFreq;
1099 LinearTransform::reduce(&mLocalTimeToSampleTransform.a_to_b_numer,
1100 &mLocalTimeToSampleTransform.a_to_b_denom);
1101
1102 mMediaTimeToSampleTransform.a_zero = 0;
1103 mMediaTimeToSampleTransform.b_zero = 0;
1104 mMediaTimeToSampleTransform.a_to_b_numer = sampleRate;
1105 mMediaTimeToSampleTransform.a_to_b_denom = 1000000;
1106 LinearTransform::reduce(&mMediaTimeToSampleTransform.a_to_b_numer,
1107 &mMediaTimeToSampleTransform.a_to_b_denom);
1108}
1109
1110AudioFlinger::PlaybackThread::TimedTrack::~TimedTrack() {
1111 mClient->releaseTimedTrack();
1112 delete [] mTimedSilenceBuffer;
1113}
1114
1115status_t AudioFlinger::PlaybackThread::TimedTrack::allocateTimedBuffer(
1116 size_t size, sp<IMemory>* buffer) {
1117
1118 Mutex::Autolock _l(mTimedBufferQueueLock);
1119
1120 trimTimedBufferQueue_l();
1121
1122 // lazily initialize the shared memory heap for timed buffers
1123 if (mTimedMemoryDealer == NULL) {
1124 const int kTimedBufferHeapSize = 512 << 10;
1125
1126 mTimedMemoryDealer = new MemoryDealer(kTimedBufferHeapSize,
1127 "AudioFlingerTimed");
Glenn Kasten6e2ebe92013-08-13 09:14:51 -07001128 if (mTimedMemoryDealer == NULL) {
Eric Laurent81784c32012-11-19 14:55:58 -08001129 return NO_MEMORY;
Glenn Kasten6e2ebe92013-08-13 09:14:51 -07001130 }
Eric Laurent81784c32012-11-19 14:55:58 -08001131 }
1132
1133 sp<IMemory> newBuffer = mTimedMemoryDealer->allocate(size);
Glenn Kasten663c2242013-09-24 11:52:37 -07001134 if (newBuffer == 0 || newBuffer->pointer() == NULL) {
Glenn Kasten30ff92c2013-11-20 11:57:08 -08001135 return NO_MEMORY;
Eric Laurent81784c32012-11-19 14:55:58 -08001136 }
1137
1138 *buffer = newBuffer;
1139 return NO_ERROR;
1140}
1141
1142// caller must hold mTimedBufferQueueLock
1143void AudioFlinger::PlaybackThread::TimedTrack::trimTimedBufferQueue_l() {
1144 int64_t mediaTimeNow;
1145 {
1146 Mutex::Autolock mttLock(mMediaTimeTransformLock);
1147 if (!mMediaTimeTransformValid)
1148 return;
1149
1150 int64_t targetTimeNow;
1151 status_t res = (mMediaTimeTransformTarget == TimedAudioTrack::COMMON_TIME)
1152 ? mCCHelper.getCommonTime(&targetTimeNow)
1153 : mCCHelper.getLocalTime(&targetTimeNow);
1154
1155 if (OK != res)
1156 return;
1157
1158 if (!mMediaTimeTransform.doReverseTransform(targetTimeNow,
1159 &mediaTimeNow)) {
1160 return;
1161 }
1162 }
1163
1164 size_t trimEnd;
1165 for (trimEnd = 0; trimEnd < mTimedBufferQueue.size(); trimEnd++) {
1166 int64_t bufEnd;
1167
1168 if ((trimEnd + 1) < mTimedBufferQueue.size()) {
1169 // We have a next buffer. Just use its PTS as the PTS of the frame
1170 // following the last frame in this buffer. If the stream is sparse
1171 // (ie, there are deliberate gaps left in the stream which should be
1172 // filled with silence by the TimedAudioTrack), then this can result
1173 // in one extra buffer being left un-trimmed when it could have
1174 // been. In general, this is not typical, and we would rather
1175 // optimized away the TS calculation below for the more common case
1176 // where PTSes are contiguous.
1177 bufEnd = mTimedBufferQueue[trimEnd + 1].pts();
1178 } else {
1179 // We have no next buffer. Compute the PTS of the frame following
1180 // the last frame in this buffer by computing the duration of of
1181 // this frame in media time units and adding it to the PTS of the
1182 // buffer.
1183 int64_t frameCount = mTimedBufferQueue[trimEnd].buffer()->size()
1184 / mFrameSize;
1185
1186 if (!mMediaTimeToSampleTransform.doReverseTransform(frameCount,
1187 &bufEnd)) {
1188 ALOGE("Failed to convert frame count of %lld to media time"
1189 " duration" " (scale factor %d/%u) in %s",
1190 frameCount,
1191 mMediaTimeToSampleTransform.a_to_b_numer,
1192 mMediaTimeToSampleTransform.a_to_b_denom,
1193 __PRETTY_FUNCTION__);
1194 break;
1195 }
1196 bufEnd += mTimedBufferQueue[trimEnd].pts();
1197 }
1198
1199 if (bufEnd > mediaTimeNow)
1200 break;
1201
1202 // Is the buffer we want to use in the middle of a mix operation right
1203 // now? If so, don't actually trim it. Just wait for the releaseBuffer
1204 // from the mixer which should be coming back shortly.
1205 if (!trimEnd && mQueueHeadInFlight) {
1206 mTrimQueueHeadOnRelease = true;
1207 }
1208 }
1209
1210 size_t trimStart = mTrimQueueHeadOnRelease ? 1 : 0;
1211 if (trimStart < trimEnd) {
1212 // Update the bookkeeping for framesReady()
1213 for (size_t i = trimStart; i < trimEnd; ++i) {
1214 updateFramesPendingAfterTrim_l(mTimedBufferQueue[i], "trim");
1215 }
1216
1217 // Now actually remove the buffers from the queue.
1218 mTimedBufferQueue.removeItemsAt(trimStart, trimEnd);
1219 }
1220}
1221
1222void AudioFlinger::PlaybackThread::TimedTrack::trimTimedBufferQueueHead_l(
1223 const char* logTag) {
1224 ALOG_ASSERT(mTimedBufferQueue.size() > 0,
1225 "%s called (reason \"%s\"), but timed buffer queue has no"
1226 " elements to trim.", __FUNCTION__, logTag);
1227
1228 updateFramesPendingAfterTrim_l(mTimedBufferQueue[0], logTag);
1229 mTimedBufferQueue.removeAt(0);
1230}
1231
1232void AudioFlinger::PlaybackThread::TimedTrack::updateFramesPendingAfterTrim_l(
1233 const TimedBuffer& buf,
Glenn Kasten0f11b512014-01-31 16:18:54 -08001234 const char* logTag __unused) {
Eric Laurent81784c32012-11-19 14:55:58 -08001235 uint32_t bufBytes = buf.buffer()->size();
1236 uint32_t consumedAlready = buf.position();
1237
1238 ALOG_ASSERT(consumedAlready <= bufBytes,
1239 "Bad bookkeeping while updating frames pending. Timed buffer is"
1240 " only %u bytes long, but claims to have consumed %u"
1241 " bytes. (update reason: \"%s\")",
1242 bufBytes, consumedAlready, logTag);
1243
1244 uint32_t bufFrames = (bufBytes - consumedAlready) / mFrameSize;
1245 ALOG_ASSERT(mFramesPendingInQueue >= bufFrames,
1246 "Bad bookkeeping while updating frames pending. Should have at"
1247 " least %u queued frames, but we think we have only %u. (update"
1248 " reason: \"%s\")",
1249 bufFrames, mFramesPendingInQueue, logTag);
1250
1251 mFramesPendingInQueue -= bufFrames;
1252}
1253
1254status_t AudioFlinger::PlaybackThread::TimedTrack::queueTimedBuffer(
1255 const sp<IMemory>& buffer, int64_t pts) {
1256
1257 {
1258 Mutex::Autolock mttLock(mMediaTimeTransformLock);
1259 if (!mMediaTimeTransformValid)
1260 return INVALID_OPERATION;
1261 }
1262
1263 Mutex::Autolock _l(mTimedBufferQueueLock);
1264
1265 uint32_t bufFrames = buffer->size() / mFrameSize;
1266 mFramesPendingInQueue += bufFrames;
1267 mTimedBufferQueue.add(TimedBuffer(buffer, pts));
1268
1269 return NO_ERROR;
1270}
1271
1272status_t AudioFlinger::PlaybackThread::TimedTrack::setMediaTimeTransform(
1273 const LinearTransform& xform, TimedAudioTrack::TargetTimeline target) {
1274
1275 ALOGVV("setMediaTimeTransform az=%lld bz=%lld n=%d d=%u tgt=%d",
1276 xform.a_zero, xform.b_zero, xform.a_to_b_numer, xform.a_to_b_denom,
1277 target);
1278
1279 if (!(target == TimedAudioTrack::LOCAL_TIME ||
1280 target == TimedAudioTrack::COMMON_TIME)) {
1281 return BAD_VALUE;
1282 }
1283
1284 Mutex::Autolock lock(mMediaTimeTransformLock);
1285 mMediaTimeTransform = xform;
1286 mMediaTimeTransformTarget = target;
1287 mMediaTimeTransformValid = true;
1288
1289 return NO_ERROR;
1290}
1291
1292#define min(a, b) ((a) < (b) ? (a) : (b))
1293
1294// implementation of getNextBuffer for tracks whose buffers have timestamps
1295status_t AudioFlinger::PlaybackThread::TimedTrack::getNextBuffer(
1296 AudioBufferProvider::Buffer* buffer, int64_t pts)
1297{
1298 if (pts == AudioBufferProvider::kInvalidPTS) {
1299 buffer->raw = NULL;
1300 buffer->frameCount = 0;
1301 mTimedAudioOutputOnTime = false;
1302 return INVALID_OPERATION;
1303 }
1304
1305 Mutex::Autolock _l(mTimedBufferQueueLock);
1306
1307 ALOG_ASSERT(!mQueueHeadInFlight,
1308 "getNextBuffer called without releaseBuffer!");
1309
1310 while (true) {
1311
1312 // if we have no timed buffers, then fail
1313 if (mTimedBufferQueue.isEmpty()) {
1314 buffer->raw = NULL;
1315 buffer->frameCount = 0;
1316 return NOT_ENOUGH_DATA;
1317 }
1318
1319 TimedBuffer& head = mTimedBufferQueue.editItemAt(0);
1320
1321 // calculate the PTS of the head of the timed buffer queue expressed in
1322 // local time
1323 int64_t headLocalPTS;
1324 {
1325 Mutex::Autolock mttLock(mMediaTimeTransformLock);
1326
1327 ALOG_ASSERT(mMediaTimeTransformValid, "media time transform invalid");
1328
1329 if (mMediaTimeTransform.a_to_b_denom == 0) {
1330 // the transform represents a pause, so yield silence
1331 timedYieldSilence_l(buffer->frameCount, buffer);
1332 return NO_ERROR;
1333 }
1334
1335 int64_t transformedPTS;
1336 if (!mMediaTimeTransform.doForwardTransform(head.pts(),
1337 &transformedPTS)) {
1338 // the transform failed. this shouldn't happen, but if it does
1339 // then just drop this buffer
1340 ALOGW("timedGetNextBuffer transform failed");
1341 buffer->raw = NULL;
1342 buffer->frameCount = 0;
1343 trimTimedBufferQueueHead_l("getNextBuffer; no transform");
1344 return NO_ERROR;
1345 }
1346
1347 if (mMediaTimeTransformTarget == TimedAudioTrack::COMMON_TIME) {
1348 if (OK != mCCHelper.commonTimeToLocalTime(transformedPTS,
1349 &headLocalPTS)) {
1350 buffer->raw = NULL;
1351 buffer->frameCount = 0;
1352 return INVALID_OPERATION;
1353 }
1354 } else {
1355 headLocalPTS = transformedPTS;
1356 }
1357 }
1358
Glenn Kasten9fdcb0a2013-06-26 16:11:36 -07001359 uint32_t sr = sampleRate();
1360
Eric Laurent81784c32012-11-19 14:55:58 -08001361 // adjust the head buffer's PTS to reflect the portion of the head buffer
1362 // that has already been consumed
1363 int64_t effectivePTS = headLocalPTS +
Glenn Kasten9fdcb0a2013-06-26 16:11:36 -07001364 ((head.position() / mFrameSize) * mLocalTimeFreq / sr);
Eric Laurent81784c32012-11-19 14:55:58 -08001365
1366 // Calculate the delta in samples between the head of the input buffer
1367 // queue and the start of the next output buffer that will be written.
1368 // If the transformation fails because of over or underflow, it means
1369 // that the sample's position in the output stream is so far out of
1370 // whack that it should just be dropped.
1371 int64_t sampleDelta;
1372 if (llabs(effectivePTS - pts) >= (static_cast<int64_t>(1) << 31)) {
1373 ALOGV("*** head buffer is too far from PTS: dropped buffer");
1374 trimTimedBufferQueueHead_l("getNextBuffer, buf pts too far from"
1375 " mix");
1376 continue;
1377 }
1378 if (!mLocalTimeToSampleTransform.doForwardTransform(
1379 (effectivePTS - pts) << 32, &sampleDelta)) {
1380 ALOGV("*** too late during sample rate transform: dropped buffer");
1381 trimTimedBufferQueueHead_l("getNextBuffer, bad local to sample");
1382 continue;
1383 }
1384
1385 ALOGVV("*** getNextBuffer head.pts=%lld head.pos=%d pts=%lld"
1386 " sampleDelta=[%d.%08x]",
1387 head.pts(), head.position(), pts,
1388 static_cast<int32_t>((sampleDelta >= 0 ? 0 : 1)
1389 + (sampleDelta >> 32)),
1390 static_cast<uint32_t>(sampleDelta & 0xFFFFFFFF));
1391
1392 // if the delta between the ideal placement for the next input sample and
1393 // the current output position is within this threshold, then we will
1394 // concatenate the next input samples to the previous output
1395 const int64_t kSampleContinuityThreshold =
Glenn Kasten9fdcb0a2013-06-26 16:11:36 -07001396 (static_cast<int64_t>(sr) << 32) / 250;
Eric Laurent81784c32012-11-19 14:55:58 -08001397
1398 // if this is the first buffer of audio that we're emitting from this track
1399 // then it should be almost exactly on time.
1400 const int64_t kSampleStartupThreshold = 1LL << 32;
1401
1402 if ((mTimedAudioOutputOnTime && llabs(sampleDelta) <= kSampleContinuityThreshold) ||
1403 (!mTimedAudioOutputOnTime && llabs(sampleDelta) <= kSampleStartupThreshold)) {
1404 // the next input is close enough to being on time, so concatenate it
1405 // with the last output
1406 timedYieldSamples_l(buffer);
1407
1408 ALOGVV("*** on time: head.pos=%d frameCount=%u",
1409 head.position(), buffer->frameCount);
1410 return NO_ERROR;
1411 }
1412
1413 // Looks like our output is not on time. Reset our on timed status.
1414 // Next time we mix samples from our input queue, then should be within
1415 // the StartupThreshold.
1416 mTimedAudioOutputOnTime = false;
1417 if (sampleDelta > 0) {
1418 // the gap between the current output position and the proper start of
1419 // the next input sample is too big, so fill it with silence
1420 uint32_t framesUntilNextInput = (sampleDelta + 0x80000000) >> 32;
1421
1422 timedYieldSilence_l(framesUntilNextInput, buffer);
1423 ALOGV("*** silence: frameCount=%u", buffer->frameCount);
1424 return NO_ERROR;
1425 } else {
1426 // the next input sample is late
1427 uint32_t lateFrames = static_cast<uint32_t>(-((sampleDelta + 0x80000000) >> 32));
1428 size_t onTimeSamplePosition =
1429 head.position() + lateFrames * mFrameSize;
1430
1431 if (onTimeSamplePosition > head.buffer()->size()) {
1432 // all the remaining samples in the head are too late, so
1433 // drop it and move on
1434 ALOGV("*** too late: dropped buffer");
1435 trimTimedBufferQueueHead_l("getNextBuffer, dropped late buffer");
1436 continue;
1437 } else {
1438 // skip over the late samples
1439 head.setPosition(onTimeSamplePosition);
1440
1441 // yield the available samples
1442 timedYieldSamples_l(buffer);
1443
1444 ALOGV("*** late: head.pos=%d frameCount=%u", head.position(), buffer->frameCount);
1445 return NO_ERROR;
1446 }
1447 }
1448 }
1449}
1450
1451// Yield samples from the timed buffer queue head up to the given output
1452// buffer's capacity.
1453//
1454// Caller must hold mTimedBufferQueueLock
1455void AudioFlinger::PlaybackThread::TimedTrack::timedYieldSamples_l(
1456 AudioBufferProvider::Buffer* buffer) {
1457
1458 const TimedBuffer& head = mTimedBufferQueue[0];
1459
1460 buffer->raw = (static_cast<uint8_t*>(head.buffer()->pointer()) +
1461 head.position());
1462
1463 uint32_t framesLeftInHead = ((head.buffer()->size() - head.position()) /
1464 mFrameSize);
1465 size_t framesRequested = buffer->frameCount;
1466 buffer->frameCount = min(framesLeftInHead, framesRequested);
1467
1468 mQueueHeadInFlight = true;
1469 mTimedAudioOutputOnTime = true;
1470}
1471
1472// Yield samples of silence up to the given output buffer's capacity
1473//
1474// Caller must hold mTimedBufferQueueLock
1475void AudioFlinger::PlaybackThread::TimedTrack::timedYieldSilence_l(
1476 uint32_t numFrames, AudioBufferProvider::Buffer* buffer) {
1477
1478 // lazily allocate a buffer filled with silence
1479 if (mTimedSilenceBufferSize < numFrames * mFrameSize) {
1480 delete [] mTimedSilenceBuffer;
1481 mTimedSilenceBufferSize = numFrames * mFrameSize;
1482 mTimedSilenceBuffer = new uint8_t[mTimedSilenceBufferSize];
1483 memset(mTimedSilenceBuffer, 0, mTimedSilenceBufferSize);
1484 }
1485
1486 buffer->raw = mTimedSilenceBuffer;
1487 size_t framesRequested = buffer->frameCount;
1488 buffer->frameCount = min(numFrames, framesRequested);
1489
1490 mTimedAudioOutputOnTime = false;
1491}
1492
1493// AudioBufferProvider interface
1494void AudioFlinger::PlaybackThread::TimedTrack::releaseBuffer(
1495 AudioBufferProvider::Buffer* buffer) {
1496
1497 Mutex::Autolock _l(mTimedBufferQueueLock);
1498
1499 // If the buffer which was just released is part of the buffer at the head
1500 // of the queue, be sure to update the amt of the buffer which has been
1501 // consumed. If the buffer being returned is not part of the head of the
1502 // queue, its either because the buffer is part of the silence buffer, or
1503 // because the head of the timed queue was trimmed after the mixer called
1504 // getNextBuffer but before the mixer called releaseBuffer.
1505 if (buffer->raw == mTimedSilenceBuffer) {
1506 ALOG_ASSERT(!mQueueHeadInFlight,
1507 "Queue head in flight during release of silence buffer!");
1508 goto done;
1509 }
1510
1511 ALOG_ASSERT(mQueueHeadInFlight,
1512 "TimedTrack::releaseBuffer of non-silence buffer, but no queue"
1513 " head in flight.");
1514
1515 if (mTimedBufferQueue.size()) {
1516 TimedBuffer& head = mTimedBufferQueue.editItemAt(0);
1517
1518 void* start = head.buffer()->pointer();
1519 void* end = reinterpret_cast<void*>(
1520 reinterpret_cast<uint8_t*>(head.buffer()->pointer())
1521 + head.buffer()->size());
1522
1523 ALOG_ASSERT((buffer->raw >= start) && (buffer->raw < end),
1524 "released buffer not within the head of the timed buffer"
1525 " queue; qHead = [%p, %p], released buffer = %p",
1526 start, end, buffer->raw);
1527
1528 head.setPosition(head.position() +
1529 (buffer->frameCount * mFrameSize));
1530 mQueueHeadInFlight = false;
1531
1532 ALOG_ASSERT(mFramesPendingInQueue >= buffer->frameCount,
1533 "Bad bookkeeping during releaseBuffer! Should have at"
1534 " least %u queued frames, but we think we have only %u",
1535 buffer->frameCount, mFramesPendingInQueue);
1536
1537 mFramesPendingInQueue -= buffer->frameCount;
1538
1539 if ((static_cast<size_t>(head.position()) >= head.buffer()->size())
1540 || mTrimQueueHeadOnRelease) {
1541 trimTimedBufferQueueHead_l("releaseBuffer");
1542 mTrimQueueHeadOnRelease = false;
1543 }
1544 } else {
Glenn Kastenadad3d72014-02-21 14:51:43 -08001545 LOG_ALWAYS_FATAL("TimedTrack::releaseBuffer of non-silence buffer with no"
Eric Laurent81784c32012-11-19 14:55:58 -08001546 " buffers in the timed buffer queue");
1547 }
1548
1549done:
1550 buffer->raw = 0;
1551 buffer->frameCount = 0;
1552}
1553
1554size_t AudioFlinger::PlaybackThread::TimedTrack::framesReady() const {
1555 Mutex::Autolock _l(mTimedBufferQueueLock);
1556 return mFramesPendingInQueue;
1557}
1558
1559AudioFlinger::PlaybackThread::TimedTrack::TimedBuffer::TimedBuffer()
1560 : mPTS(0), mPosition(0) {}
1561
1562AudioFlinger::PlaybackThread::TimedTrack::TimedBuffer::TimedBuffer(
1563 const sp<IMemory>& buffer, int64_t pts)
1564 : mBuffer(buffer), mPTS(pts), mPosition(0) {}
1565
1566
1567// ----------------------------------------------------------------------------
1568
1569AudioFlinger::PlaybackThread::OutputTrack::OutputTrack(
1570 PlaybackThread *playbackThread,
1571 DuplicatingThread *sourceThread,
1572 uint32_t sampleRate,
1573 audio_format_t format,
1574 audio_channel_mask_t channelMask,
Marco Nelissen462fd2f2013-01-14 14:12:05 -08001575 size_t frameCount,
1576 int uid)
Eric Laurent81784c32012-11-19 14:55:58 -08001577 : Track(playbackThread, NULL, AUDIO_STREAM_CNT, sampleRate, format, channelMask, frameCount,
Marco Nelissen462fd2f2013-01-14 14:12:05 -08001578 NULL, 0, uid, IAudioFlinger::TRACK_DEFAULT),
Glenn Kastene3aa6592012-12-04 12:22:46 -08001579 mActive(false), mSourceThread(sourceThread), mClientProxy(NULL)
Eric Laurent81784c32012-11-19 14:55:58 -08001580{
1581
1582 if (mCblk != NULL) {
Eric Laurent81784c32012-11-19 14:55:58 -08001583 mOutBuffer.frameCount = 0;
1584 playbackThread->mTracks.add(this);
Glenn Kastene3aa6592012-12-04 12:22:46 -08001585 ALOGV("OutputTrack constructor mCblk %p, mBuffer %p, "
Glenn Kasten74935e42013-12-19 08:56:45 -08001586 "frameCount %u, mChannelMask 0x%08x",
Glenn Kastene3aa6592012-12-04 12:22:46 -08001587 mCblk, mBuffer,
Glenn Kasten74935e42013-12-19 08:56:45 -08001588 frameCount, mChannelMask);
Glenn Kastene3aa6592012-12-04 12:22:46 -08001589 // since client and server are in the same process,
1590 // the buffer has the same virtual address on both sides
1591 mClientProxy = new AudioTrackClientProxy(mCblk, mBuffer, mFrameCount, mFrameSize);
Eric Laurent8d2d4932013-04-25 12:56:18 -07001592 mClientProxy->setVolumeLR((uint32_t(uint16_t(0x1000)) << 16) | uint16_t(0x1000));
1593 mClientProxy->setSendLevel(0.0);
1594 mClientProxy->setSampleRate(sampleRate);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001595 mClientProxy = new AudioTrackClientProxy(mCblk, mBuffer, mFrameCount, mFrameSize,
1596 true /*clientInServer*/);
Eric Laurent81784c32012-11-19 14:55:58 -08001597 } else {
1598 ALOGW("Error creating output track on thread %p", playbackThread);
1599 }
1600}
1601
1602AudioFlinger::PlaybackThread::OutputTrack::~OutputTrack()
1603{
1604 clearBufferQueue();
Glenn Kastene3aa6592012-12-04 12:22:46 -08001605 delete mClientProxy;
1606 // superclass destructor will now delete the server proxy and shared memory both refer to
Eric Laurent81784c32012-11-19 14:55:58 -08001607}
1608
1609status_t AudioFlinger::PlaybackThread::OutputTrack::start(AudioSystem::sync_event_t event,
1610 int triggerSession)
1611{
1612 status_t status = Track::start(event, triggerSession);
1613 if (status != NO_ERROR) {
1614 return status;
1615 }
1616
1617 mActive = true;
1618 mRetryCount = 127;
1619 return status;
1620}
1621
1622void AudioFlinger::PlaybackThread::OutputTrack::stop()
1623{
1624 Track::stop();
1625 clearBufferQueue();
1626 mOutBuffer.frameCount = 0;
1627 mActive = false;
1628}
1629
1630bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t frames)
1631{
1632 Buffer *pInBuffer;
1633 Buffer inBuffer;
1634 uint32_t channelCount = mChannelCount;
1635 bool outputBufferFull = false;
1636 inBuffer.frameCount = frames;
1637 inBuffer.i16 = data;
1638
1639 uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
1640
1641 if (!mActive && frames != 0) {
1642 start();
1643 sp<ThreadBase> thread = mThread.promote();
1644 if (thread != 0) {
1645 MixerThread *mixerThread = (MixerThread *)thread.get();
1646 if (mFrameCount > frames) {
1647 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
1648 uint32_t startFrames = (mFrameCount - frames);
1649 pInBuffer = new Buffer;
1650 pInBuffer->mBuffer = new int16_t[startFrames * channelCount];
1651 pInBuffer->frameCount = startFrames;
1652 pInBuffer->i16 = pInBuffer->mBuffer;
1653 memset(pInBuffer->raw, 0, startFrames * channelCount * sizeof(int16_t));
1654 mBufferQueue.add(pInBuffer);
1655 } else {
Glenn Kasten7c027242012-12-26 14:43:16 -08001656 ALOGW("OutputTrack::write() %p no more buffers in queue", this);
Eric Laurent81784c32012-11-19 14:55:58 -08001657 }
1658 }
1659 }
1660 }
1661
1662 while (waitTimeLeftMs) {
1663 // First write pending buffers, then new data
1664 if (mBufferQueue.size()) {
1665 pInBuffer = mBufferQueue.itemAt(0);
1666 } else {
1667 pInBuffer = &inBuffer;
1668 }
1669
1670 if (pInBuffer->frameCount == 0) {
1671 break;
1672 }
1673
1674 if (mOutBuffer.frameCount == 0) {
1675 mOutBuffer.frameCount = pInBuffer->frameCount;
1676 nsecs_t startTime = systemTime();
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001677 status_t status = obtainBuffer(&mOutBuffer, waitTimeLeftMs);
1678 if (status != NO_ERROR) {
1679 ALOGV("OutputTrack::write() %p thread %p no more output buffers; status %d", this,
1680 mThread.unsafe_get(), status);
Eric Laurent81784c32012-11-19 14:55:58 -08001681 outputBufferFull = true;
1682 break;
1683 }
1684 uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
1685 if (waitTimeLeftMs >= waitTimeMs) {
1686 waitTimeLeftMs -= waitTimeMs;
1687 } else {
1688 waitTimeLeftMs = 0;
1689 }
1690 }
1691
1692 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount :
1693 pInBuffer->frameCount;
1694 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * channelCount * sizeof(int16_t));
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001695 Proxy::Buffer buf;
1696 buf.mFrameCount = outFrames;
1697 buf.mRaw = NULL;
1698 mClientProxy->releaseBuffer(&buf);
Eric Laurent81784c32012-11-19 14:55:58 -08001699 pInBuffer->frameCount -= outFrames;
1700 pInBuffer->i16 += outFrames * channelCount;
1701 mOutBuffer.frameCount -= outFrames;
1702 mOutBuffer.i16 += outFrames * channelCount;
1703
1704 if (pInBuffer->frameCount == 0) {
1705 if (mBufferQueue.size()) {
1706 mBufferQueue.removeAt(0);
1707 delete [] pInBuffer->mBuffer;
1708 delete pInBuffer;
1709 ALOGV("OutputTrack::write() %p thread %p released overflow buffer %d", this,
1710 mThread.unsafe_get(), mBufferQueue.size());
1711 } else {
1712 break;
1713 }
1714 }
1715 }
1716
1717 // If we could not write all frames, allocate a buffer and queue it for next time.
1718 if (inBuffer.frameCount) {
1719 sp<ThreadBase> thread = mThread.promote();
1720 if (thread != 0 && !thread->standby()) {
1721 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
1722 pInBuffer = new Buffer;
1723 pInBuffer->mBuffer = new int16_t[inBuffer.frameCount * channelCount];
1724 pInBuffer->frameCount = inBuffer.frameCount;
1725 pInBuffer->i16 = pInBuffer->mBuffer;
1726 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * channelCount *
1727 sizeof(int16_t));
1728 mBufferQueue.add(pInBuffer);
1729 ALOGV("OutputTrack::write() %p thread %p adding overflow buffer %d", this,
1730 mThread.unsafe_get(), mBufferQueue.size());
1731 } else {
1732 ALOGW("OutputTrack::write() %p thread %p no more overflow buffers",
1733 mThread.unsafe_get(), this);
1734 }
1735 }
1736 }
1737
1738 // Calling write() with a 0 length buffer, means that no more data will be written:
1739 // If no more buffers are pending, fill output track buffer to make sure it is started
1740 // by output mixer.
1741 if (frames == 0 && mBufferQueue.size() == 0) {
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001742 // FIXME borken, replace by getting framesReady() from proxy
1743 size_t user = 0; // was mCblk->user
1744 if (user < mFrameCount) {
1745 frames = mFrameCount - user;
Eric Laurent81784c32012-11-19 14:55:58 -08001746 pInBuffer = new Buffer;
1747 pInBuffer->mBuffer = new int16_t[frames * channelCount];
1748 pInBuffer->frameCount = frames;
1749 pInBuffer->i16 = pInBuffer->mBuffer;
1750 memset(pInBuffer->raw, 0, frames * channelCount * sizeof(int16_t));
1751 mBufferQueue.add(pInBuffer);
1752 } else if (mActive) {
1753 stop();
1754 }
1755 }
1756
1757 return outputBufferFull;
1758}
1759
1760status_t AudioFlinger::PlaybackThread::OutputTrack::obtainBuffer(
1761 AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
1762{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001763 ClientProxy::Buffer buf;
1764 buf.mFrameCount = buffer->frameCount;
1765 struct timespec timeout;
1766 timeout.tv_sec = waitTimeMs / 1000;
1767 timeout.tv_nsec = (int) (waitTimeMs % 1000) * 1000000;
1768 status_t status = mClientProxy->obtainBuffer(&buf, &timeout);
1769 buffer->frameCount = buf.mFrameCount;
1770 buffer->raw = buf.mRaw;
1771 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08001772}
1773
Eric Laurent81784c32012-11-19 14:55:58 -08001774void AudioFlinger::PlaybackThread::OutputTrack::clearBufferQueue()
1775{
1776 size_t size = mBufferQueue.size();
1777
1778 for (size_t i = 0; i < size; i++) {
1779 Buffer *pBuffer = mBufferQueue.itemAt(i);
1780 delete [] pBuffer->mBuffer;
1781 delete pBuffer;
1782 }
1783 mBufferQueue.clear();
1784}
1785
1786
1787// ----------------------------------------------------------------------------
1788// Record
1789// ----------------------------------------------------------------------------
1790
1791AudioFlinger::RecordHandle::RecordHandle(
1792 const sp<AudioFlinger::RecordThread::RecordTrack>& recordTrack)
1793 : BnAudioRecord(),
1794 mRecordTrack(recordTrack)
1795{
1796}
1797
1798AudioFlinger::RecordHandle::~RecordHandle() {
1799 stop_nonvirtual();
1800 mRecordTrack->destroy();
1801}
1802
Eric Laurent81784c32012-11-19 14:55:58 -08001803status_t AudioFlinger::RecordHandle::start(int /*AudioSystem::sync_event_t*/ event,
1804 int triggerSession) {
1805 ALOGV("RecordHandle::start()");
1806 return mRecordTrack->start((AudioSystem::sync_event_t)event, triggerSession);
1807}
1808
1809void AudioFlinger::RecordHandle::stop() {
1810 stop_nonvirtual();
1811}
1812
1813void AudioFlinger::RecordHandle::stop_nonvirtual() {
1814 ALOGV("RecordHandle::stop()");
1815 mRecordTrack->stop();
1816}
1817
1818status_t AudioFlinger::RecordHandle::onTransact(
1819 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1820{
1821 return BnAudioRecord::onTransact(code, data, reply, flags);
1822}
1823
1824// ----------------------------------------------------------------------------
1825
Glenn Kasten05997e22014-03-13 15:08:33 -07001826// RecordTrack constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
Eric Laurent81784c32012-11-19 14:55:58 -08001827AudioFlinger::RecordThread::RecordTrack::RecordTrack(
1828 RecordThread *thread,
1829 const sp<Client>& client,
1830 uint32_t sampleRate,
1831 audio_format_t format,
1832 audio_channel_mask_t channelMask,
1833 size_t frameCount,
Marco Nelissen462fd2f2013-01-14 14:12:05 -08001834 int sessionId,
Glenn Kastend776ac62014-05-07 09:16:09 -07001835 int uid,
1836 bool isFast)
Eric Laurent81784c32012-11-19 14:55:58 -08001837 : TrackBase(thread, client, sampleRate, format,
Glenn Kastend776ac62014-05-07 09:16:09 -07001838 channelMask, frameCount, 0 /*sharedBuffer*/, sessionId, uid, false /*isOut*/,
1839 isFast /*useReadOnlyHeap*/),
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08001840 mOverflow(false), mResampler(NULL), mRsmpOutBuffer(NULL), mRsmpOutFrameCount(0),
1841 // See real initialization of mRsmpInFront at RecordThread::start()
1842 mRsmpInUnrel(0), mRsmpInFront(0), mFramesToDrop(0), mResamplerBufferProvider(NULL)
Eric Laurent81784c32012-11-19 14:55:58 -08001843{
Glenn Kasten3ef14ef2014-03-13 15:08:51 -07001844 if (mCblk == NULL) {
1845 return;
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001846 }
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08001847
Glenn Kasten3ef14ef2014-03-13 15:08:51 -07001848 mServerProxy = new AudioRecordServerProxy(mCblk, mBuffer, frameCount, mFrameSize);
1849
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08001850 uint32_t channelCount = popcount(channelMask);
1851 // FIXME I don't understand either of the channel count checks
1852 if (thread->mSampleRate != sampleRate && thread->mChannelCount <= FCC_2 &&
1853 channelCount <= FCC_2) {
1854 // sink SR
1855 mResampler = AudioResampler::create(16, thread->mChannelCount, sampleRate);
1856 // source SR
1857 mResampler->setSampleRate(thread->mSampleRate);
1858 mResampler->setVolume(AudioMixer::UNITY_GAIN, AudioMixer::UNITY_GAIN);
1859 mResamplerBufferProvider = new ResamplerBufferProvider(this);
1860 }
Eric Laurent81784c32012-11-19 14:55:58 -08001861}
1862
1863AudioFlinger::RecordThread::RecordTrack::~RecordTrack()
1864{
1865 ALOGV("%s", __func__);
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08001866 delete mResampler;
1867 delete[] mRsmpOutBuffer;
1868 delete mResamplerBufferProvider;
Eric Laurent81784c32012-11-19 14:55:58 -08001869}
1870
1871// AudioBufferProvider interface
1872status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer,
Glenn Kasten0f11b512014-01-31 16:18:54 -08001873 int64_t pts __unused)
Eric Laurent81784c32012-11-19 14:55:58 -08001874{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001875 ServerProxy::Buffer buf;
1876 buf.mFrameCount = buffer->frameCount;
1877 status_t status = mServerProxy->obtainBuffer(&buf);
1878 buffer->frameCount = buf.mFrameCount;
1879 buffer->raw = buf.mRaw;
1880 if (buf.mFrameCount == 0) {
1881 // FIXME also wake futex so that overrun is noticed more quickly
Glenn Kasten96f60d82013-07-12 10:21:18 -07001882 (void) android_atomic_or(CBLK_OVERRUN, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08001883 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001884 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08001885}
1886
1887status_t AudioFlinger::RecordThread::RecordTrack::start(AudioSystem::sync_event_t event,
1888 int triggerSession)
1889{
1890 sp<ThreadBase> thread = mThread.promote();
1891 if (thread != 0) {
1892 RecordThread *recordThread = (RecordThread *)thread.get();
1893 return recordThread->start(this, event, triggerSession);
1894 } else {
1895 return BAD_VALUE;
1896 }
1897}
1898
1899void AudioFlinger::RecordThread::RecordTrack::stop()
1900{
1901 sp<ThreadBase> thread = mThread.promote();
1902 if (thread != 0) {
1903 RecordThread *recordThread = (RecordThread *)thread.get();
Glenn Kastena8356f62013-07-25 14:37:52 -07001904 if (recordThread->stop(this)) {
Eric Laurent81784c32012-11-19 14:55:58 -08001905 AudioSystem::stopInput(recordThread->id());
1906 }
1907 }
1908}
1909
1910void AudioFlinger::RecordThread::RecordTrack::destroy()
1911{
1912 // see comments at AudioFlinger::PlaybackThread::Track::destroy()
1913 sp<RecordTrack> keep(this);
1914 {
1915 sp<ThreadBase> thread = mThread.promote();
1916 if (thread != 0) {
1917 if (mState == ACTIVE || mState == RESUMING) {
1918 AudioSystem::stopInput(thread->id());
1919 }
1920 AudioSystem::releaseInput(thread->id());
1921 Mutex::Autolock _l(thread->mLock);
1922 RecordThread *recordThread = (RecordThread *) thread.get();
1923 recordThread->destroyTrack_l(this);
1924 }
1925 }
1926}
1927
Eric Laurent9a54bc22013-09-09 09:08:44 -07001928void AudioFlinger::RecordThread::RecordTrack::invalidate()
1929{
1930 // FIXME should use proxy, and needs work
1931 audio_track_cblk_t* cblk = mCblk;
1932 android_atomic_or(CBLK_INVALID, &cblk->mFlags);
1933 android_atomic_release_store(0x40000000, &cblk->mFutex);
1934 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
1935 (void) __futex_syscall3(&cblk->mFutex, FUTEX_WAKE, INT_MAX);
1936}
1937
Eric Laurent81784c32012-11-19 14:55:58 -08001938
1939/*static*/ void AudioFlinger::RecordThread::RecordTrack::appendDumpHeader(String8& result)
1940{
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08001941 result.append(" Active Client Fmt Chn mask Session S Server fCount Resampling\n");
Eric Laurent81784c32012-11-19 14:55:58 -08001942}
1943
Marco Nelissenb2208842014-02-07 14:00:50 -08001944void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size, bool active)
Eric Laurent81784c32012-11-19 14:55:58 -08001945{
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08001946 snprintf(buffer, size, " %6s %6u %3u %08X %7u %1d %08X %6zu %10d\n",
Marco Nelissenb2208842014-02-07 14:00:50 -08001947 active ? "yes" : "no",
Eric Laurent81784c32012-11-19 14:55:58 -08001948 (mClient == 0) ? getpid_cached : mClient->pid(),
1949 mFormat,
1950 mChannelMask,
1951 mSessionId,
Eric Laurent81784c32012-11-19 14:55:58 -08001952 mState,
Glenn Kastenf20e1d82013-07-12 09:45:18 -07001953 mCblk->mServer,
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08001954 mFrameCount,
1955 mResampler != NULL);
1956
Eric Laurent81784c32012-11-19 14:55:58 -08001957}
1958
Glenn Kasten25f4aa82014-02-07 10:50:43 -08001959void AudioFlinger::RecordThread::RecordTrack::handleSyncStartEvent(const sp<SyncEvent>& event)
1960{
1961 if (event == mSyncStartEvent) {
1962 ssize_t framesToDrop = 0;
1963 sp<ThreadBase> threadBase = mThread.promote();
1964 if (threadBase != 0) {
1965 // TODO: use actual buffer filling status instead of 2 buffers when info is available
1966 // from audio HAL
1967 framesToDrop = threadBase->mFrameCount * 2;
1968 }
1969 mFramesToDrop = framesToDrop;
1970 }
1971}
1972
1973void AudioFlinger::RecordThread::RecordTrack::clearSyncStartEvent()
1974{
1975 if (mSyncStartEvent != 0) {
1976 mSyncStartEvent->cancel();
1977 mSyncStartEvent.clear();
1978 }
1979 mFramesToDrop = 0;
1980}
1981
Eric Laurent81784c32012-11-19 14:55:58 -08001982}; // namespace android