Tracks.cpp revision d776ac63ce9c013c9626226e43f7db606e035838
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Copyright 2012, The Android Open Source Project 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License"); 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** you may not use this file except in compliance with the License. 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** You may obtain a copy of the License at 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** http://www.apache.org/licenses/LICENSE-2.0 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Unless required by applicable law or agreed to in writing, software 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS, 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** See the License for the specific language governing permissions and 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** limitations under the License. 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project*/ 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LOG_TAG "AudioFlinger" 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//#define LOG_NDEBUG 0 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "Configuration.h" 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <math.h> 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Log.h> 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <private/media/AudioTrackShared.h> 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <common_time/cc_helper.h> 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <common_time/local_clock.h> 3058feea74b42bbaaa0552d76af23873bdd0b5dca2Mitsuru Oshima 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "AudioMixer.h" 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "AudioFlinger.h" 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "ServiceUtilities.h" 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <media/nbaio/Pipe.h> 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <media/nbaio/PipeReader.h> 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// Note: the following macro is used for extremely verbose logging message. In 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// order to run with ALOG_ASSERT turned on, we need to have LOG_NDEBUG set to 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// 0; but one side effect of this is to turn all LOGV's as well. Some messages 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// are so verbose that we want to suppress them even when we have ALOG_ASSERT 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// turned on. Do not uncomment the #def below unless you really know what you 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// are doing and want to see all of the extremely verbose messages. 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//#define VERY_VERY_VERBOSE_LOGGING 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef VERY_VERY_VERBOSE_LOGGING 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define ALOGVV ALOGV 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define ALOGVV(a...) do { } while(0) 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android { 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// TrackBase 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic volatile int32_t nextTrackId = 55; 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// TrackBase constructor must be called with AudioFlinger::mLock held 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAudioFlinger::ThreadBase::TrackBase::TrackBase( 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ThreadBase *thread, 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const sp<Client>& client, 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t sampleRate, 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project audio_format_t format, 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project audio_channel_mask_t channelMask, 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t frameCount, 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const sp<IMemory>& sharedBuffer, 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int sessionId, 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int clientUid, 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool isOut, 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool useReadOnlyHeap) 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : RefBase(), 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mThread(thread), 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mClient(client), 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCblk(NULL), 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // mBuffer 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState(IDLE), 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSampleRate(sampleRate), 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFormat(format), 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChannelMask(channelMask), 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChannelCount(popcount(channelMask)), 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFrameSize(audio_is_linear_pcm(format) ? 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChannelCount * audio_bytes_per_sample(format) : sizeof(int8_t)), 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFrameCount(frameCount), 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSessionId(sessionId), 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIsOut(isOut), 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mServerProxy(NULL), 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mId(android_atomic_inc(&nextTrackId)), 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTerminated(false) 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // if the caller is us, trust the specified uid 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (IPCThreadState::self()->getCallingPid() != getpid_cached || clientUid == -1) { 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int newclientUid = IPCThreadState::self()->getCallingUid(); 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (clientUid != -1 && clientUid != newclientUid) { 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ALOGW("uid %d tried to pass itself off as %d", newclientUid, clientUid); 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project clientUid = newclientUid; 1006465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller } 1016465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller // clientUid contains the uid of the app that is responsible for this track, so we can blame 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // battery usage on it. 1036465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller mUid = clientUid; 1046465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // client == 0 implies sharedBuffer == 0 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ALOG_ASSERT(!(client == 0 && sharedBuffer != 0)); 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ALOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sharedBuffer->size()); 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // ALOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize); 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t size = sizeof(audio_track_cblk_t); 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t bufferSize = (sharedBuffer == 0 ? roundup(frameCount) : frameCount) * mFrameSize; 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sharedBuffer == 0 && !useReadOnlyHeap) { 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size += bufferSize; 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (client != 0) { 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCblkMemory = client->heap()->allocate(size); 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mCblkMemory == 0 || 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer())) == NULL) { 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ALOGE("not enough memory for AudioTrack size=%u", size); 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project client->heap()->dump("AudioTrack"); 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCblkMemory.clear(); 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // this syntax avoids calling the audio_track_cblk_t constructor twice 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCblk = (audio_track_cblk_t *) new uint8_t[size]; 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // assume mCblk != NULL 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // construct the shared structure in-place. 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mCblk != NULL) { 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new(mCblk) audio_track_cblk_t(); 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (useReadOnlyHeap) { 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const sp<MemoryDealer> roHeap(thread->readOnlyHeap()); 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (roHeap == 0 || 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (mBufferMemory = roHeap->allocate(bufferSize)) == 0 || 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (mBuffer = mBufferMemory->pointer()) == NULL) { 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ALOGE("not enough memory for read-only buffer size=%zu", bufferSize); 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (roHeap != 0) { 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project roHeap->dump("buffer"); 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 145ae09878698ba6ad56ea43843f5a0895c94c32d90Amith Yamasani mCblkMemory.clear(); 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBufferMemory.clear(); 147a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase return; 148a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase } 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memset(mBuffer, 0, bufferSize); 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // clear all buffers 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sharedBuffer == 0) { 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t); 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memset(mBuffer, 0, bufferSize); 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBuffer = sharedBuffer->pointer(); 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if 0 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCblk->mFlags = CBLK_FORCEREADY; // FIXME hack, need to fix the track ready logic 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef TEE_SINK 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mTeeSinkTrackEnabled) { 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NBAIO_Format pipeFormat = Format_from_SR_C(mSampleRate, mChannelCount); 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Format_isValid(pipeFormat)) { 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Pipe *pipe = new Pipe(mTeeSinkTrackFrames, pipeFormat); 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t numCounterOffers = 0; 169a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase const NBAIO_Format offers[1] = {pipeFormat}; 170a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase ssize_t index = pipe->negotiate(offers, 1, NULL, numCounterOffers); 171a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase ALOG_ASSERT(index == 0); 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PipeReader *pipeReader = new PipeReader(*pipe); 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project numCounterOffers = 0; 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index = pipeReader->negotiate(offers, 1, NULL, numCounterOffers); 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ALOG_ASSERT(index == 0); 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTeeSink = pipe; 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTeeSource = pipeReader; 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAudioFlinger::ThreadBase::TrackBase::~TrackBase() 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef TEE_SINK 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dumpTee(-1, mTeeSource, mId); 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // delete the proxy before deleting the shared memory it refers to, to avoid dangling reference 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delete mServerProxy; 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mCblk != NULL) { 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mClient == 0) { 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delete mCblk; 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCblk->~audio_track_cblk_t(); // destroy our shared-structure. 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mClient != 0) { 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Client destructor must run with AudioFlinger mutex locked 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Mutex::Autolock _l(mClient->audioFlinger()->mLock); 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If the client's reference count drops to zero, the associated destructor 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // must run with AudioFlinger lock held. Thus the explicit clear() rather than 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // relying on the automatic clear() at end of scope. 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mClient.clear(); 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// AudioBufferProvider interface 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// getNextBuffer() = 0; 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// This implementation of releaseBuffer() is used by Track and RecordTrack, but not TimedTrack 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AudioFlinger::ThreadBase::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer) 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef TEE_SINK 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mTeeSink != 0) { 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (void) mTeeSink->write(buffer->raw, buffer->frameCount); 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ServerProxy::Buffer buf; 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buf.mFrameCount = buffer->frameCount; 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buf.mRaw = buffer->raw; 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buffer->frameCount = 0; 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buffer->raw = NULL; 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mServerProxy->releaseBuffer(&buf); 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t AudioFlinger::ThreadBase::TrackBase::setSyncEvent(const sp<SyncEvent>& event) 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSyncEvents.add(event); 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_ERROR; 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// Playback 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::PlaybackThread::Track>& track) 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : BnAudioTrack(), 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTrack(track) 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAudioFlinger::TrackHandle::~TrackHandle() { 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // just stop the track on deletion, associated resources 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // will be freed from the main thread once all pending buffers have 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // been played. Unless it's not in the active track list, in which 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // case we free everything now... 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTrack->destroy(); 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectsp<IMemory> AudioFlinger::TrackHandle::getCblk() const { 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mTrack->getCblk(); 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t AudioFlinger::TrackHandle::start() { 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mTrack->start(); 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AudioFlinger::TrackHandle::stop() { 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTrack->stop(); 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 264a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AudioFlinger::TrackHandle::flush() { 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTrack->flush(); 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AudioFlinger::TrackHandle::pause() { 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTrack->pause(); 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t AudioFlinger::TrackHandle::attachAuxEffect(int EffectId) 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mTrack->attachAuxEffect(EffectId); 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t AudioFlinger::TrackHandle::allocateTimedBuffer(size_t size, 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp<IMemory>* buffer) { 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mTrack->isTimedTrack()) 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return INVALID_OPERATION; 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PlaybackThread::TimedTrack* tt = 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project reinterpret_cast<PlaybackThread::TimedTrack*>(mTrack.get()); 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return tt->allocateTimedBuffer(size, buffer); 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t AudioFlinger::TrackHandle::queueTimedBuffer(const sp<IMemory>& buffer, 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int64_t pts) { 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mTrack->isTimedTrack()) 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return INVALID_OPERATION; 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (buffer == 0 || buffer->pointer() == NULL) { 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ALOGE("queueTimedBuffer() buffer is 0 or has NULL pointer()"); 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return BAD_VALUE; 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PlaybackThread::TimedTrack* tt = 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project reinterpret_cast<PlaybackThread::TimedTrack*>(mTrack.get()); 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return tt->queueTimedBuffer(buffer, pts); 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t AudioFlinger::TrackHandle::setMediaTimeTransform( 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const LinearTransform& xform, int target) { 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mTrack->isTimedTrack()) 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return INVALID_OPERATION; 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PlaybackThread::TimedTrack* tt = 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project reinterpret_cast<PlaybackThread::TimedTrack*>(mTrack.get()); 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return tt->setMediaTimeTransform( 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project xform, static_cast<TimedAudioTrack::TargetTimeline>(target)); 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 315b65b7cb5808a3cea59cbfa72ecd46bdda90351faTadashi G. Takaokastatus_t AudioFlinger::TrackHandle::setParameters(const String8& keyValuePairs) { 316b65b7cb5808a3cea59cbfa72ecd46bdda90351faTadashi G. Takaoka return mTrack->setParameters(keyValuePairs); 317b65b7cb5808a3cea59cbfa72ecd46bdda90351faTadashi G. Takaoka} 318b65b7cb5808a3cea59cbfa72ecd46bdda90351faTadashi G. Takaoka 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t AudioFlinger::TrackHandle::getTimestamp(AudioTimestamp& timestamp) 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mTrack->getTimestamp(timestamp); 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AudioFlinger::TrackHandle::signal() 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mTrack->signal(); 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t AudioFlinger::TrackHandle::onTransact( 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return BnAudioTrack::onTransact(code, data, reply, flags); 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAudioFlinger::PlaybackThread::Track::Track( 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PlaybackThread *thread, 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const sp<Client>& client, 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project audio_stream_type_t streamType, 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t sampleRate, 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project audio_format_t format, 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project audio_channel_mask_t channelMask, 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t frameCount, 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const sp<IMemory>& sharedBuffer, 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int sessionId, 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int uid, 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IAudioFlinger::track_flags_t flags) 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : TrackBase(thread, client, sampleRate, format, channelMask, frameCount, sharedBuffer, 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sessionId, uid, true /*isOut*/), 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFillingUpStatus(FS_INVALID), 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // mRetryCount initialized later when needed 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSharedBuffer(sharedBuffer), 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStreamType(streamType), 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mName(-1), // see note below 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMainBuffer(thread->mixBuffer()), 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAuxBuffer(NULL), 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAuxEffectId(0), mHasVolumeController(false), 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPresentationCompleteFrames(0), 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFlags(flags), 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFastIndex(-1), 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCachedVolume(1.0), 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIsInvalid(false), 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAudioTrackServerProxy(NULL), 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mResumeToStopping(false), 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFlushHwPending(false) 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mCblk == NULL) { 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sharedBuffer == 0) { 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAudioTrackServerProxy = new AudioTrackServerProxy(mCblk, mBuffer, frameCount, 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFrameSize); 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAudioTrackServerProxy = new StaticAudioTrackServerProxy(mCblk, mBuffer, frameCount, 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFrameSize); 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mServerProxy = mAudioTrackServerProxy; 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mName = thread->getTrackName_l(channelMask, sessionId); 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mName < 0) { 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ALOGE("no more track names available"); 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // only allocate a fast track index if we were able to allocate a normal track name 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (flags & IAudioFlinger::TRACK_FAST) { 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAudioTrackServerProxy->framesReadyIsCalledByMultipleThreads(); 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ALOG_ASSERT(thread->mFastTrackAvailMask != 0); 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int i = __builtin_ctz(thread->mFastTrackAvailMask); 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ALOG_ASSERT(0 < i && i < (int)FastMixerState::kMaxFastTracks); 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // FIXME This is too eager. We allocate a fast track index before the 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // fast track becomes active. Since fast tracks are a scarce resource, 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // this means we are potentially denying other more important fast tracks from 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // being created. It would be better to allocate the index dynamically. 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFastIndex = i; 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Read the initial underruns because this field is never cleared by the fast mixer 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mObservedUnderruns = thread->getFastTrackUnderruns(i); 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project thread->mFastTrackAvailMask &= ~(1 << i); 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAudioFlinger::PlaybackThread::Track::~Track() 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ALOGV("PlaybackThread::Track destructor"); 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // The destructor would clear mSharedBuffer, 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // but it will not push the decremented reference count, 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // leaving the client's IMemory dangling indefinitely. 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This prevents that leak. 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSharedBuffer != 0) { 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSharedBuffer.clear(); 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // flush the binder command buffer 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IPCThreadState::self()->flushCommands(); 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t AudioFlinger::PlaybackThread::Track::initCheck() const 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project status_t status = TrackBase::initCheck(); 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (status == NO_ERROR && mName < 0) { 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project status = NO_MEMORY; 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return status; 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AudioFlinger::PlaybackThread::Track::destroy() 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // NOTE: destroyTrack_l() can remove a strong reference to this Track 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // by removing it from mTracks vector, so there is a risk that this Tracks's 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // destructor is called. As the destructor needs to lock mLock, 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // we must acquire a strong reference on this Track before locking mLock 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // here so that the destructor is called only when exiting this function. 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // On the other hand, as long as Track::destroy() is only called by 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // TrackHandle destructor, the TrackHandle still holds a strong ref on 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // this Track with its member mTrack. 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp<Track> keep(this); 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { // scope for mLock 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp<ThreadBase> thread = mThread.promote(); 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (thread != 0) { 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Mutex::Autolock _l(thread->mLock); 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool wasActive = playbackThread->destroyTrack_l(this); 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!isOutputTrack() && !wasActive) { 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AudioSystem::releaseOutput(thread->id()); 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*static*/ void AudioFlinger::PlaybackThread::Track::appendDumpHeader(String8& result) 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result.append(" Name Active Client Type Fmt Chn mask Session fCount S F SRate " 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "L dB R dB Server Main buf Aux Buf Flags UndFrmCnt\n"); 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size, bool active) 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t vlr = mAudioTrackServerProxy->getVolumeLR(); 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (isFastTrack()) { 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sprintf(buffer, " F %2d", mFastIndex); 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (mName >= AudioMixer::TRACK0) { 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sprintf(buffer, " %4d", mName - AudioMixer::TRACK0); 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sprintf(buffer, " none"); 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project track_state state = mState; 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char stateChar; 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (isTerminated()) { 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project stateChar = 'T'; 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (state) { 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case IDLE: 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project stateChar = 'I'; 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case STOPPING_1: 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project stateChar = 's'; 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case STOPPING_2: 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project stateChar = '5'; 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case STOPPED: 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project stateChar = 'S'; 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case RESUMING: 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project stateChar = 'R'; 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case ACTIVE: 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project stateChar = 'A'; 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case PAUSING: 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project stateChar = 'p'; 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case PAUSED: 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project stateChar = 'P'; 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case FLUSHED: 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project stateChar = 'F'; 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project stateChar = '?'; 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char nowInUnderrun; 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (mObservedUnderruns.mBitFields.mMostRecent) { 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case UNDERRUN_FULL: 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nowInUnderrun = ' '; 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 5128171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung case UNDERRUN_PARTIAL: 5138171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung nowInUnderrun = '<'; 5148171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung break; 5158171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung case UNDERRUN_EMPTY: 5168171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung nowInUnderrun = '*'; 5178171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung break; 5188171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung default: 5198171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung nowInUnderrun = '?'; 5208171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung break; 5218171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung } 5228171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung snprintf(&buffer[8], size-8, " %6s %6u %4u %08X %08X %7u %6zu %1c %1d %5u %5.2g %5.2g " 5238171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung "%08X %p %p 0x%03X %9u%c\n", 5248171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung active ? "yes" : "no", 5258171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung (mClient == 0) ? getpid_cached : mClient->pid(), 5268171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung mStreamType, 5278171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung mFormat, 5288171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung mChannelMask, 5298171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung mSessionId, 5308171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung mFrameCount, 5318171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung stateChar, 5328171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung mFillingUpStatus, 5338171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung mAudioTrackServerProxy->getSampleRate(), 5348171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung 20.0 * log10((vlr & 0xFFFF) / 4096.0), 5358171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung 20.0 * log10((vlr >> 16) / 4096.0), 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCblk->mServer, 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMainBuffer, 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAuxBuffer, 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCblk->mFlags, 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAudioTrackServerProxy->getUnderrunFrames(), 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nowInUnderrun); 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 54458feea74b42bbaaa0552d76af23873bdd0b5dca2Mitsuru Oshimauint32_t AudioFlinger::PlaybackThread::Track::sampleRate() const { 54558feea74b42bbaaa0552d76af23873bdd0b5dca2Mitsuru Oshima return mAudioTrackServerProxy->getSampleRate(); 54658feea74b42bbaaa0552d76af23873bdd0b5dca2Mitsuru Oshima} 54758feea74b42bbaaa0552d76af23873bdd0b5dca2Mitsuru Oshima 54858feea74b42bbaaa0552d76af23873bdd0b5dca2Mitsuru Oshima// AudioBufferProvider interface 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t AudioFlinger::PlaybackThread::Track::getNextBuffer( 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AudioBufferProvider::Buffer* buffer, int64_t pts __unused) 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ServerProxy::Buffer buf; 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t desiredFrames = buffer->frameCount; 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buf.mFrameCount = desiredFrames; 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project status_t status = mServerProxy->obtainBuffer(&buf); 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buffer->frameCount = buf.mFrameCount; 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buffer->raw = buf.mRaw; 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (buf.mFrameCount == 0) { 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAudioTrackServerProxy->tallyUnderrunFrames(desiredFrames); 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return status; 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// releaseBuffer() is not overridden 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ExtendedAudioBufferProvider interface 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// Note that framesReady() takes a mutex on the control block using tryLock(). 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// This could result in priority inversion if framesReady() is called by the normal mixer, 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// as the normal mixer thread runs at lower 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// priority than the client's callback thread: there is a short window within framesReady() 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// during which the normal mixer could be preempted, and the client callback would block. 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// Another problem can occur if framesReady() is called by the fast mixer: 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// the tryLock() could block for up to 1 ms, and a sequence of these could delay fast mixer. 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// FIXME Replace AudioTrackShared control block implementation by a non-blocking FIFO queue. 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectsize_t AudioFlinger::PlaybackThread::Track::framesReady() const { 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mAudioTrackServerProxy->framesReady(); 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectsize_t AudioFlinger::PlaybackThread::Track::framesReleased() const 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mAudioTrackServerProxy->framesReleased(); 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// Don't call for fast tracks; the framesReady() could result in priority inversion 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbool AudioFlinger::PlaybackThread::Track::isReady() const { 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mFillingUpStatus != FS_FILLING || isStopped() || isPausing()) { 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (isStopping()) { 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (framesReady() > 0) { 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFillingUpStatus = FS_FILLED; 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (framesReady() >= mFrameCount || 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (mCblk->mFlags & CBLK_FORCEREADY)) { 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFillingUpStatus = FS_FILLED; 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags); 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 604a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase return false; 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t AudioFlinger::PlaybackThread::Track::start(AudioSystem::sync_event_t event __unused, 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int triggerSession __unused) 609a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase{ 610a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase status_t status = NO_ERROR; 611a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase ALOGV("start(%d), calling pid %d session %d", 612a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase mName, IPCThreadState::self()->getCallingPid(), mSessionId); 613a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase 614a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase sp<ThreadBase> thread = mThread.promote(); 615a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase if (thread != 0) { 616a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase if (isOffloaded()) { 617a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase Mutex::Autolock _laf(thread->mAudioFlinger->mLock); 618a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase Mutex::Autolock _lth(thread->mLock); 619a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase sp<EffectChain> ec = thread->getEffectChain_l(mSessionId); 620a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase if (thread->mAudioFlinger->isNonOffloadableGlobalEffectEnabled_l() || 621a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase (ec != 0 && ec->isNonOffloadableEnabled())) { 622a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase invalidate(); 623a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase return PERMISSION_DENIED; 624a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase } 625a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase } 626a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase Mutex::Autolock _lth(thread->mLock); 627a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase track_state state = mState; 628a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase // here the track could be either new, or restarted 629a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase // in both cases "unstop" the track 630a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase 631a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase // initial state-stopping. next state-pausing. 632a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase // What if resume is called ? 633a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase 634a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase if (state == PAUSED || state == PAUSING) { 635a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase if (mResumeToStopping) { 636a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase // happened we need to resume to STOPPING_1 637a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase mState = TrackBase::STOPPING_1; 638a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase ALOGV("PAUSED => STOPPING_1 (%d) on thread %p", mName, this); 639a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase } else { 640a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase mState = TrackBase::RESUMING; 641a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase ALOGV("PAUSED => RESUMING (%d) on thread %p", mName, this); 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState = TrackBase::ACTIVE; 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ALOGV("? => ACTIVE (%d) on thread %p", mName, this); 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project status = playbackThread->addTrack_l(this); 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (status == INVALID_OPERATION || status == PERMISSION_DENIED) { 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE); 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // restore previous state if start was rejected by policy manager 6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (status == PERMISSION_DENIED) { 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState = state; 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // track was already in the active list, not a problem 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (status == ALREADY_EXISTS) { 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project status = NO_ERROR; 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Acknowledge any pending flush(), so that subsequent new data isn't discarded. 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // It is usually unsafe to access the server proxy from a binder thread. 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // But in this case we know the mixer thread (whether normal mixer or fast mixer) 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // isn't looking at this track yet: we still hold the normal mixer thread lock, 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // and for fast tracks the track is not yet in the fast mixer thread's active set. 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ServerProxy::Buffer buffer; 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buffer.mFrameCount = 1; 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (void) mAudioTrackServerProxy->obtainBuffer(&buffer, true /*ackFlush*/); 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project status = BAD_VALUE; 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return status; 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AudioFlinger::PlaybackThread::Track::stop() 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ALOGV("stop(%d), calling pid %d", mName, IPCThreadState::self()->getCallingPid()); 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp<ThreadBase> thread = mThread.promote(); 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (thread != 0) { 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Mutex::Autolock _l(thread->mLock); 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project track_state state = mState; 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (state == RESUMING || state == ACTIVE || state == PAUSING || state == PAUSED) { 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If the track is not active (PAUSED and buffers full), flush buffers 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (playbackThread->mActiveTracks.indexOf(this) < 0) { 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project reset(); 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState = STOPPED; 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (!isFastTrack() && !isOffloaded()) { 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState = STOPPED; 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // For fast tracks prepareTracks_l() will set state to STOPPING_2 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // presentation is complete 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // For an offloaded track this starts a drain and state will 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // move to STOPPING_2 when drain completes and then STOPPED 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState = STOPPING_1; 6976465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller } 6986465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller ALOGV("not stopping/stopped => stopping/stopped (%d) on thread %p", mName, 6996465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller playbackThread); 7006465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller } 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AudioFlinger::PlaybackThread::Track::pause() 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ALOGV("pause(%d), calling pid %d", mName, IPCThreadState::self()->getCallingPid()); 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp<ThreadBase> thread = mThread.promote(); 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (thread != 0) { 7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Mutex::Autolock _l(thread->mLock); 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (mState) { 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case STOPPING_1: 7136465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller case STOPPING_2: 7146465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller if (!isOffloaded()) { 7156465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller /* nothing to do if track is not offloaded */ 7166465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller break; 7176465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller } 7186465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller 7196465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller // Offloaded track was draining, we need to carry on draining when resumed 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mResumeToStopping = true; 7216465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller // fall through... 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case ACTIVE: 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case RESUMING: 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState = PAUSING; 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ALOGV("ACTIVE/RESUMING => PAUSING (%d) on thread %p", mName, thread.get()); 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project playbackThread->broadcast_l(); 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AudioFlinger::PlaybackThread::Track::flush() 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ALOGV("flush(%d)", mName); 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp<ThreadBase> thread = mThread.promote(); 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (thread != 0) { 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Mutex::Autolock _l(thread->mLock); 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (isOffloaded()) { 7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If offloaded we allow flush during any state except terminated 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // and keep the track active to avoid problems if user is seeking 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // rapidly and underlying hardware has a significant delay handling 7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // a pause 7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (isTerminated()) { 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ALOGV("flush: offload flush"); 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project reset(); 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState == STOPPING_1 || mState == STOPPING_2) { 7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ALOGV("flushed in STOPPING_1 or 2 state, change state to ACTIVE"); 7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState = ACTIVE; 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState == ACTIVE) { 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ALOGV("flush called in active state, resetting buffer time out retry count"); 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRetryCount = PlaybackThread::kMaxTrackRetriesOffload; 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFlushHwPending = true; 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mResumeToStopping = false; 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState != STOPPING_1 && mState != STOPPING_2 && mState != STOPPED && 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState != PAUSED && mState != PAUSING && mState != IDLE && mState != FLUSHED) { 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // No point remaining in PAUSED state after a flush => go to 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // FLUSHED state 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState = FLUSHED; 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // do not reset the track if it is still in the process of being stopped or paused. 7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // this will be done by prepareTracks_l() when the track is stopped. 7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // prepareTracks_l() will see mState == FLUSHED, then 7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // remove from active track list, reset(), and trigger presentation complete 7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (playbackThread->mActiveTracks.indexOf(this) < 0) { 7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project reset(); 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Prevent flush being lost if the track is flushed and then resumed 7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // before mixer thread can run. This is important when offloading 7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // because the hardware buffer could hold a large amount of audio 7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project playbackThread->broadcast_l(); 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 790a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase// must be called with thread lock held 7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AudioFlinger::PlaybackThread::Track::flushAck() 7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!isOffloaded()) 7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFlushHwPending = false; 7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AudioFlinger::PlaybackThread::Track::reset() 800a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase{ 8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Do not reset twice to avoid discarding data written just after a flush and before 8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the audioflinger thread detects the track is stopped. 8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mResetDone) { 8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Force underrun condition to avoid false underrun callback until first data is 8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // written to buffer 8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags); 8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFillingUpStatus = FS_FILLING; 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mResetDone = true; 8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState == FLUSHED) { 8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState = IDLE; 8116465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller } 8126465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller } 8136465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller} 8146465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller 8156465f7753783a614948fb3ffbd8c072345b4eea1Jim Millerstatus_t AudioFlinger::PlaybackThread::Track::setParameters(const String8& keyValuePairs) 8166465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller{ 8176465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller sp<ThreadBase> thread = mThread.promote(); 8186465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller if (thread == 0) { 8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ALOGE("thread is dead"); 8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return FAILED_TRANSACTION; 8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if ((thread->type() == ThreadBase::DIRECT) || 8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (thread->type() == ThreadBase::OFFLOAD)) { 823a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase return thread->setParameters(keyValuePairs); 8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return PERMISSION_DENIED; 8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t AudioFlinger::PlaybackThread::Track::getTimestamp(AudioTimestamp& timestamp) 8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Client should implement this using SSQ; the unpresented frame count in latch is irrelevant 8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (isFastTrack()) { 8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return INVALID_OPERATION; 8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp<ThreadBase> thread = mThread.promote(); 8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (thread == 0) { 8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return INVALID_OPERATION; 8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Mutex::Autolock _l(thread->mLock); 8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); 8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!isOffloaded()) { 8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!playbackThread->mLatchQValid) { 8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return INVALID_OPERATION; 8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t unpresentedFrames = 8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ((int64_t) playbackThread->mLatchQ.mUnpresentedFrames * mSampleRate) / 8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project playbackThread->mSampleRate; 8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t framesWritten = mAudioTrackServerProxy->framesReleased(); 8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (framesWritten < unpresentedFrames) { 8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return INVALID_OPERATION; 8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project timestamp.mPosition = framesWritten - unpresentedFrames; 8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project timestamp.mTime = playbackThread->mLatchQ.mTimestamp.mTime; 8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_ERROR; 8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return playbackThread->getTimestamp_l(timestamp); 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t AudioFlinger::PlaybackThread::Track::attachAuxEffect(int EffectId) 8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project status_t status = DEAD_OBJECT; 8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp<ThreadBase> thread = mThread.promote(); 8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (thread != 0) { 8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); 8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp<AudioFlinger> af = mClient->audioFlinger(); 8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Mutex::Autolock _l(af->mLock); 8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp<PlaybackThread> srcThread = af->getEffectThread_l(AUDIO_SESSION_OUTPUT_MIX, EffectId); 8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (EffectId != 0 && srcThread != 0 && playbackThread != srcThread.get()) { 8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Mutex::Autolock _dl(playbackThread->mLock); 8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Mutex::Autolock _sl(srcThread->mLock); 8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp<EffectChain> chain = srcThread->getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX); 8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (chain == 0) { 8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return INVALID_OPERATION; 8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp<EffectModule> effect = chain->getEffectFromId_l(EffectId); 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (effect == 0) { 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return INVALID_OPERATION; 8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project srcThread->removeEffect_l(effect); 8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project status = playbackThread->addEffect_l(effect); 8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (status != NO_ERROR) { 8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project srcThread->addEffect_l(effect); 8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return INVALID_OPERATION; 8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // removeEffect_l() has stopped the effect if it was active so it must be restarted 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (effect->state() == EffectModule::ACTIVE || 8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project effect->state() == EffectModule::STOPPING) { 8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project effect->start(); 8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 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()); 907 AudioSystem::setEffectEnabled(effect->id(), effect->isEnabled()); 908 } 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. 926 // 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); 932 if (mPresentationCompleteFrames == 0) { 933 mPresentationCompleteFrames = framesWritten + audioHalFrames; 934 ALOGV("presentationComplete() reset: mPresentationCompleteFrames %d audioHalFrames %d", 935 mPresentationCompleteFrames, audioHalFrames); 936 } 937 938 if (framesWritten >= mPresentationCompleteFrames || isOffloaded()) { 939 ALOGV("presentationComplete() session %d complete: framesWritten %d", 940 mSessionId, framesWritten); 941 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE); 942 mAudioTrackServerProxy->setStreamEndDone(); 943 return true; 944 } 945 return false; 946} 947 948void AudioFlinger::PlaybackThread::Track::triggerEvents(AudioSystem::sync_event_t type) 949{ 950 for (size_t i = 0; i < mSyncEvents.size(); i++) { 951 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)); 965 uint32_t vlr = mAudioTrackServerProxy->getVolumeLR(); 966 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{ 988 if (isTerminated() || mState == PAUSED || 989 ((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 1000void AudioFlinger::PlaybackThread::Track::invalidate() 1001{ 1002 // FIXME should use proxy, and needs work 1003 audio_track_cblk_t* cblk = mCblk; 1004 android_atomic_or(CBLK_INVALID, &cblk->mFlags); 1005 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); 1008 mIsInvalid = true; 1009} 1010 1011void 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 1021//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; 1040 1041 // Other possibility of pending resume is stopping_1 state 1042 // Do not update the state from stopping as this prevents 1043 // drain being called. 1044 if (mState == STOPPING_1) { 1045 mResumeToStopping = false; 1046 } 1047} 1048// ---------------------------------------------------------------------------- 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, 1060 int sessionId, 1061 int uid) 1062{ 1063 if (!client->reserveTimedTrack()) 1064 return 0; 1065 1066 return new TimedTrack( 1067 thread, client, streamType, sampleRate, format, channelMask, frameCount, 1068 sharedBuffer, sessionId, uid); 1069} 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, 1080 int sessionId, 1081 int uid) 1082 : Track(thread, client, streamType, sampleRate, format, channelMask, 1083 frameCount, sharedBuffer, sessionId, uid, IAudioFlinger::TRACK_TIMED), 1084 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"); 1128 if (mTimedMemoryDealer == NULL) { 1129 return NO_MEMORY; 1130 } 1131 } 1132 1133 sp<IMemory> newBuffer = mTimedMemoryDealer->allocate(size); 1134 if (newBuffer == 0 || newBuffer->pointer() == NULL) { 1135 return NO_MEMORY; 1136 } 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, 1234 const char* logTag __unused) { 1235 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 1359 uint32_t sr = sampleRate(); 1360 1361 // 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 + 1364 ((head.position() / mFrameSize) * mLocalTimeFreq / sr); 1365 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 = 1396 (static_cast<int64_t>(sr) << 32) / 250; 1397 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 { 1545 LOG_ALWAYS_FATAL("TimedTrack::releaseBuffer of non-silence buffer with no" 1546 " 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, 1575 size_t frameCount, 1576 int uid) 1577 : Track(playbackThread, NULL, AUDIO_STREAM_CNT, sampleRate, format, channelMask, frameCount, 1578 NULL, 0, uid, IAudioFlinger::TRACK_DEFAULT), 1579 mActive(false), mSourceThread(sourceThread), mClientProxy(NULL) 1580{ 1581 1582 if (mCblk != NULL) { 1583 mOutBuffer.frameCount = 0; 1584 playbackThread->mTracks.add(this); 1585 ALOGV("OutputTrack constructor mCblk %p, mBuffer %p, " 1586 "frameCount %u, mChannelMask 0x%08x", 1587 mCblk, mBuffer, 1588 frameCount, mChannelMask); 1589 // 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); 1592 mClientProxy->setVolumeLR((uint32_t(uint16_t(0x1000)) << 16) | uint16_t(0x1000)); 1593 mClientProxy->setSendLevel(0.0); 1594 mClientProxy->setSampleRate(sampleRate); 1595 mClientProxy = new AudioTrackClientProxy(mCblk, mBuffer, mFrameCount, mFrameSize, 1596 true /*clientInServer*/); 1597 } else { 1598 ALOGW("Error creating output track on thread %p", playbackThread); 1599 } 1600} 1601 1602AudioFlinger::PlaybackThread::OutputTrack::~OutputTrack() 1603{ 1604 clearBufferQueue(); 1605 delete mClientProxy; 1606 // superclass destructor will now delete the server proxy and shared memory both refer to 1607} 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 { 1656 ALOGW("OutputTrack::write() %p no more buffers in queue", this); 1657 } 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(); 1677 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); 1681 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)); 1695 Proxy::Buffer buf; 1696 buf.mFrameCount = outFrames; 1697 buf.mRaw = NULL; 1698 mClientProxy->releaseBuffer(&buf); 1699 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) { 1742 // FIXME borken, replace by getting framesReady() from proxy 1743 size_t user = 0; // was mCblk->user 1744 if (user < mFrameCount) { 1745 frames = mFrameCount - user; 1746 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{ 1763 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; 1772} 1773 1774void 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 1803sp<IMemory> AudioFlinger::RecordHandle::getCblk() const { 1804 return mRecordTrack->getCblk(); 1805} 1806 1807status_t AudioFlinger::RecordHandle::start(int /*AudioSystem::sync_event_t*/ event, 1808 int triggerSession) { 1809 ALOGV("RecordHandle::start()"); 1810 return mRecordTrack->start((AudioSystem::sync_event_t)event, triggerSession); 1811} 1812 1813void AudioFlinger::RecordHandle::stop() { 1814 stop_nonvirtual(); 1815} 1816 1817void AudioFlinger::RecordHandle::stop_nonvirtual() { 1818 ALOGV("RecordHandle::stop()"); 1819 mRecordTrack->stop(); 1820} 1821 1822status_t AudioFlinger::RecordHandle::onTransact( 1823 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) 1824{ 1825 return BnAudioRecord::onTransact(code, data, reply, flags); 1826} 1827 1828// ---------------------------------------------------------------------------- 1829 1830// RecordTrack constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held 1831AudioFlinger::RecordThread::RecordTrack::RecordTrack( 1832 RecordThread *thread, 1833 const sp<Client>& client, 1834 uint32_t sampleRate, 1835 audio_format_t format, 1836 audio_channel_mask_t channelMask, 1837 size_t frameCount, 1838 int sessionId, 1839 int uid, 1840 bool isFast) 1841 : TrackBase(thread, client, sampleRate, format, 1842 channelMask, frameCount, 0 /*sharedBuffer*/, sessionId, uid, false /*isOut*/, 1843 isFast /*useReadOnlyHeap*/), 1844 mOverflow(false), mResampler(NULL), mRsmpOutBuffer(NULL), mRsmpOutFrameCount(0), 1845 // See real initialization of mRsmpInFront at RecordThread::start() 1846 mRsmpInUnrel(0), mRsmpInFront(0), mFramesToDrop(0), mResamplerBufferProvider(NULL) 1847{ 1848 if (mCblk == NULL) { 1849 return; 1850 } 1851 1852 mServerProxy = new AudioRecordServerProxy(mCblk, mBuffer, frameCount, mFrameSize); 1853 1854 uint32_t channelCount = popcount(channelMask); 1855 // FIXME I don't understand either of the channel count checks 1856 if (thread->mSampleRate != sampleRate && thread->mChannelCount <= FCC_2 && 1857 channelCount <= FCC_2) { 1858 // sink SR 1859 mResampler = AudioResampler::create(16, thread->mChannelCount, sampleRate); 1860 // source SR 1861 mResampler->setSampleRate(thread->mSampleRate); 1862 mResampler->setVolume(AudioMixer::UNITY_GAIN, AudioMixer::UNITY_GAIN); 1863 mResamplerBufferProvider = new ResamplerBufferProvider(this); 1864 } 1865} 1866 1867AudioFlinger::RecordThread::RecordTrack::~RecordTrack() 1868{ 1869 ALOGV("%s", __func__); 1870 delete mResampler; 1871 delete[] mRsmpOutBuffer; 1872 delete mResamplerBufferProvider; 1873} 1874 1875// AudioBufferProvider interface 1876status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer, 1877 int64_t pts __unused) 1878{ 1879 ServerProxy::Buffer buf; 1880 buf.mFrameCount = buffer->frameCount; 1881 status_t status = mServerProxy->obtainBuffer(&buf); 1882 buffer->frameCount = buf.mFrameCount; 1883 buffer->raw = buf.mRaw; 1884 if (buf.mFrameCount == 0) { 1885 // FIXME also wake futex so that overrun is noticed more quickly 1886 (void) android_atomic_or(CBLK_OVERRUN, &mCblk->mFlags); 1887 } 1888 return status; 1889} 1890 1891status_t AudioFlinger::RecordThread::RecordTrack::start(AudioSystem::sync_event_t event, 1892 int triggerSession) 1893{ 1894 sp<ThreadBase> thread = mThread.promote(); 1895 if (thread != 0) { 1896 RecordThread *recordThread = (RecordThread *)thread.get(); 1897 return recordThread->start(this, event, triggerSession); 1898 } else { 1899 return BAD_VALUE; 1900 } 1901} 1902 1903void AudioFlinger::RecordThread::RecordTrack::stop() 1904{ 1905 sp<ThreadBase> thread = mThread.promote(); 1906 if (thread != 0) { 1907 RecordThread *recordThread = (RecordThread *)thread.get(); 1908 if (recordThread->stop(this)) { 1909 AudioSystem::stopInput(recordThread->id()); 1910 } 1911 } 1912} 1913 1914void AudioFlinger::RecordThread::RecordTrack::destroy() 1915{ 1916 // see comments at AudioFlinger::PlaybackThread::Track::destroy() 1917 sp<RecordTrack> keep(this); 1918 { 1919 sp<ThreadBase> thread = mThread.promote(); 1920 if (thread != 0) { 1921 if (mState == ACTIVE || mState == RESUMING) { 1922 AudioSystem::stopInput(thread->id()); 1923 } 1924 AudioSystem::releaseInput(thread->id()); 1925 Mutex::Autolock _l(thread->mLock); 1926 RecordThread *recordThread = (RecordThread *) thread.get(); 1927 recordThread->destroyTrack_l(this); 1928 } 1929 } 1930} 1931 1932void AudioFlinger::RecordThread::RecordTrack::invalidate() 1933{ 1934 // FIXME should use proxy, and needs work 1935 audio_track_cblk_t* cblk = mCblk; 1936 android_atomic_or(CBLK_INVALID, &cblk->mFlags); 1937 android_atomic_release_store(0x40000000, &cblk->mFutex); 1938 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE 1939 (void) __futex_syscall3(&cblk->mFutex, FUTEX_WAKE, INT_MAX); 1940} 1941 1942 1943/*static*/ void AudioFlinger::RecordThread::RecordTrack::appendDumpHeader(String8& result) 1944{ 1945 result.append(" Active Client Fmt Chn mask Session S Server fCount Resampling\n"); 1946} 1947 1948void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size, bool active) 1949{ 1950 snprintf(buffer, size, " %6s %6u %3u %08X %7u %1d %08X %6zu %10d\n", 1951 active ? "yes" : "no", 1952 (mClient == 0) ? getpid_cached : mClient->pid(), 1953 mFormat, 1954 mChannelMask, 1955 mSessionId, 1956 mState, 1957 mCblk->mServer, 1958 mFrameCount, 1959 mResampler != NULL); 1960 1961} 1962 1963void AudioFlinger::RecordThread::RecordTrack::handleSyncStartEvent(const sp<SyncEvent>& event) 1964{ 1965 if (event == mSyncStartEvent) { 1966 ssize_t framesToDrop = 0; 1967 sp<ThreadBase> threadBase = mThread.promote(); 1968 if (threadBase != 0) { 1969 // TODO: use actual buffer filling status instead of 2 buffers when info is available 1970 // from audio HAL 1971 framesToDrop = threadBase->mFrameCount * 2; 1972 } 1973 mFramesToDrop = framesToDrop; 1974 } 1975} 1976 1977void AudioFlinger::RecordThread::RecordTrack::clearSyncStartEvent() 1978{ 1979 if (mSyncStartEvent != 0) { 1980 mSyncStartEvent->cancel(); 1981 mSyncStartEvent.clear(); 1982 } 1983 mFramesToDrop = 0; 1984} 1985 1986}; // namespace android 1987