blob: 918b01fea9185f212c683e0e865e8ae111c23e34 [file] [log] [blame]
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001/* //device/include/server/AudioFlinger/AudioFlinger.cpp
2**
3** Copyright 2007, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18
19#define LOG_TAG "AudioFlinger"
20//#define LOG_NDEBUG 0
21
22#include <math.h>
23#include <signal.h>
24#include <sys/time.h>
25#include <sys/resource.h>
26
27#include <utils/IServiceManager.h>
28#include <utils/Log.h>
29#include <utils/Parcel.h>
30#include <utils/IPCThreadState.h>
31#include <utils/String16.h>
32#include <utils/threads.h>
33
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -080034#include <cutils/properties.h>
35
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070036#include <media/AudioTrack.h>
37#include <media/AudioRecord.h>
38
39#include <private/media/AudioTrackShared.h>
40
The Android Open Source Project8a7a6752009-01-15 16:12:10 -080041#include <hardware_legacy/AudioHardwareInterface.h>
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070042
43#include "AudioMixer.h"
44#include "AudioFlinger.h"
45
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -080046#ifdef WITH_A2DP
47#include "A2dpAudioInterface.h"
48#endif
49
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070050namespace android {
51
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -080052//static const nsecs_t kStandbyTimeInNsecs = seconds(3);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070053static const unsigned long kBufferRecoveryInUsecs = 2000;
54static const unsigned long kMaxBufferRecoveryInUsecs = 20000;
55static const float MAX_GAIN = 4096.0f;
56
57// retry counts for buffer fill timeout
58// 50 * ~20msecs = 1 second
59static const int8_t kMaxTrackRetries = 50;
60static const int8_t kMaxTrackStartupRetries = 50;
61
62#define AUDIOFLINGER_SECURITY_ENABLED 1
63
64// ----------------------------------------------------------------------------
65
66static bool recordingAllowed() {
67#ifndef HAVE_ANDROID_OS
68 return true;
69#endif
70#if AUDIOFLINGER_SECURITY_ENABLED
71 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
72 bool ok = checkCallingPermission(String16("android.permission.RECORD_AUDIO"));
73 if (!ok) LOGE("Request requires android.permission.RECORD_AUDIO");
74 return ok;
75#else
76 if (!checkCallingPermission(String16("android.permission.RECORD_AUDIO")))
77 LOGW("WARNING: Need to add android.permission.RECORD_AUDIO to manifest");
78 return true;
79#endif
80}
81
82static bool settingsAllowed() {
83#ifndef HAVE_ANDROID_OS
84 return true;
85#endif
86#if AUDIOFLINGER_SECURITY_ENABLED
87 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
88 bool ok = checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS"));
89 if (!ok) LOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS");
90 return ok;
91#else
92 if (!checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS")))
93 LOGW("WARNING: Need to add android.permission.MODIFY_AUDIO_SETTINGS to manifest");
94 return true;
95#endif
96}
97
98// ----------------------------------------------------------------------------
99
100AudioFlinger::AudioFlinger()
101 : BnAudioFlinger(), Thread(false),
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800102 mMasterVolume(0), mMasterMute(true), mHardwareAudioMixer(0), mA2dpAudioMixer(0),
The Android Open Source Project27629322009-01-09 17:51:23 -0800103 mAudioMixer(0), mAudioHardware(0), mA2dpAudioInterface(0), mHardwareOutput(0),
104 mA2dpOutput(0), mOutput(0), mRequestedOutput(0), mAudioRecordThread(0),
105 mSampleRate(0), mFrameCount(0), mChannelCount(0), mFormat(0), mMixBuffer(0),
106 mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mStandby(false),
The Android Open Source Projecte41dd752009-01-22 00:13:42 -0800107 mInWrite(false), mA2dpDisableCount(0), mA2dpSuppressed(false)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700108{
109 mHardwareStatus = AUDIO_HW_IDLE;
110 mAudioHardware = AudioHardwareInterface::create();
111 mHardwareStatus = AUDIO_HW_INIT;
112 if (mAudioHardware->initCheck() == NO_ERROR) {
113 // open 16-bit output stream for s/w mixer
114 mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800115 status_t status;
116 mHardwareOutput = mAudioHardware->openOutputStream(AudioSystem::PCM_16_BIT, 0, 0, &status);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700117 mHardwareStatus = AUDIO_HW_IDLE;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800118 if (mHardwareOutput) {
The Android Open Source Project27629322009-01-09 17:51:23 -0800119 mHardwareAudioMixer = new AudioMixer(getOutputFrameCount(mHardwareOutput), mHardwareOutput->sampleRate());
120 mRequestedOutput = mHardwareOutput;
121 doSetOutput(mHardwareOutput);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800122
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700123 // FIXME - this should come from settings
124 setMasterVolume(1.0f);
125 setRouting(AudioSystem::MODE_NORMAL, AudioSystem::ROUTE_SPEAKER, AudioSystem::ROUTE_ALL);
126 setRouting(AudioSystem::MODE_RINGTONE, AudioSystem::ROUTE_SPEAKER, AudioSystem::ROUTE_ALL);
127 setRouting(AudioSystem::MODE_IN_CALL, AudioSystem::ROUTE_EARPIECE, AudioSystem::ROUTE_ALL);
128 setMode(AudioSystem::MODE_NORMAL);
129 mMasterMute = false;
130 } else {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800131 LOGE("Failed to initialize output stream, status: %d", status);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700132 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800133
134#ifdef WITH_A2DP
135 // Create A2DP interface
136 mA2dpAudioInterface = new A2dpAudioInterface();
137 mA2dpOutput = mA2dpAudioInterface->openOutputStream(AudioSystem::PCM_16_BIT, 0, 0, &status);
138 mA2dpAudioMixer = new AudioMixer(getOutputFrameCount(mA2dpOutput), mA2dpOutput->sampleRate());
139
140 // create a buffer big enough for both hardware and A2DP audio output.
141 size_t hwFrameCount = getOutputFrameCount(mHardwareOutput);
142 size_t a2dpFrameCount = getOutputFrameCount(mA2dpOutput);
143 size_t frameCount = (hwFrameCount > a2dpFrameCount ? hwFrameCount : a2dpFrameCount);
144#else
145 size_t frameCount = getOutputFrameCount(mHardwareOutput);
146#endif
147 // FIXME - Current mixer implementation only supports stereo output: Always
148 // Allocate a stereo buffer even if HW output is mono.
149 mMixBuffer = new int16_t[frameCount * 2];
150 memset(mMixBuffer, 0, frameCount * 2 * sizeof(int16_t));
151
152 // Start record thread
153 mAudioRecordThread = new AudioRecordThread(mAudioHardware);
154 if (mAudioRecordThread != 0) {
155 mAudioRecordThread->run("AudioRecordThread", PRIORITY_URGENT_AUDIO);
156 }
157 } else {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700158 LOGE("Couldn't even initialize the stubbed audio hardware!");
159 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800160
161 char value[PROPERTY_VALUE_MAX];
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800162 property_get("ro.audio.silent", value, "0");
163 if (atoi(value)) {
164 LOGD("Silence is golden");
165 mMasterMute = true;
166 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700167}
168
169AudioFlinger::~AudioFlinger()
170{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800171 if (mAudioRecordThread != 0) {
172 mAudioRecordThread->exit();
173 mAudioRecordThread.clear();
174 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700175 delete mAudioHardware;
The Android Open Source Project27629322009-01-09 17:51:23 -0800176 // deleting mA2dpAudioInterface also deletes mA2dpOutput;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800177 delete mA2dpAudioInterface;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700178 delete [] mMixBuffer;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800179 delete mHardwareAudioMixer;
180 delete mA2dpAudioMixer;
181}
182
183void AudioFlinger::setOutput(AudioStreamOut* output)
184{
The Android Open Source Project27629322009-01-09 17:51:23 -0800185 mRequestedOutput = output;
186}
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800187
The Android Open Source Project27629322009-01-09 17:51:23 -0800188void AudioFlinger::doSetOutput(AudioStreamOut* output)
189{
190 mSampleRate = output->sampleRate();
191 mChannelCount = output->channelCount();
192
193 // FIXME - Current mixer implementation only supports stereo output
194 if (mChannelCount == 1) {
195 LOGE("Invalid audio hardware channel count");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800196 }
The Android Open Source Project27629322009-01-09 17:51:23 -0800197 mFormat = output->format();
198 mFrameCount = getOutputFrameCount(output);
199 mAudioMixer = (output == mA2dpOutput ? mA2dpAudioMixer : mHardwareAudioMixer);
200 mOutput = output;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800201}
202
203size_t AudioFlinger::getOutputFrameCount(AudioStreamOut* output)
204{
205 return output->bufferSize() / output->channelCount() / sizeof(int16_t);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700206}
207
The Android Open Source Projecte41dd752009-01-22 00:13:42 -0800208#ifdef WITH_A2DP
209bool AudioFlinger::streamDisablesA2dp(int streamType)
210{
211 return (streamType == AudioTrack::SYSTEM ||
212 streamType == AudioTrack::RING ||
213 streamType == AudioTrack::ALARM ||
214 streamType == AudioTrack::NOTIFICATION);
215}
216
217void AudioFlinger::setA2dpEnabled(bool enable)
218{
219 if (enable) {
220 LOGD("set output to A2DP\n");
221 setOutput(mA2dpOutput);
222 } else {
223 LOGD("set output to hardware audio\n");
224 setOutput(mHardwareOutput);
225 }
226}
227#endif // WITH_A2DP
228
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700229status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args)
230{
231 const size_t SIZE = 256;
232 char buffer[SIZE];
233 String8 result;
234
235 result.append("Clients:\n");
236 for (size_t i = 0; i < mClients.size(); ++i) {
237 wp<Client> wClient = mClients.valueAt(i);
238 if (wClient != 0) {
239 sp<Client> client = wClient.promote();
240 if (client != 0) {
241 snprintf(buffer, SIZE, " pid: %d\n", client->pid());
242 result.append(buffer);
243 }
244 }
245 }
246 write(fd, result.string(), result.size());
247 return NO_ERROR;
248}
249
250status_t AudioFlinger::dumpTracks(int fd, const Vector<String16>& args)
251{
252 const size_t SIZE = 256;
253 char buffer[SIZE];
254 String8 result;
255
256 result.append("Tracks:\n");
257 result.append(" Name Clien Typ Fmt Chn Buf S M F SRate LeftV RighV Serv User\n");
258 for (size_t i = 0; i < mTracks.size(); ++i) {
259 wp<Track> wTrack = mTracks[i];
260 if (wTrack != 0) {
261 sp<Track> track = wTrack.promote();
262 if (track != 0) {
263 track->dump(buffer, SIZE);
264 result.append(buffer);
265 }
266 }
267 }
268
269 result.append("Active Tracks:\n");
270 result.append(" Name Clien Typ Fmt Chn Buf S M F SRate LeftV RighV Serv User\n");
271 for (size_t i = 0; i < mActiveTracks.size(); ++i) {
272 wp<Track> wTrack = mTracks[i];
273 if (wTrack != 0) {
274 sp<Track> track = wTrack.promote();
275 if (track != 0) {
276 track->dump(buffer, SIZE);
277 result.append(buffer);
278 }
279 }
280 }
281 write(fd, result.string(), result.size());
282 return NO_ERROR;
283}
284
285status_t AudioFlinger::dumpInternals(int fd, const Vector<String16>& args)
286{
287 const size_t SIZE = 256;
288 char buffer[SIZE];
289 String8 result;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800290
291 snprintf(buffer, SIZE, "AudioMixer tracks: %08x\n", audioMixer()->trackNames());
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700292 result.append(buffer);
293 snprintf(buffer, SIZE, "last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime));
294 result.append(buffer);
295 snprintf(buffer, SIZE, "total writes: %d\n", mNumWrites);
296 result.append(buffer);
297 snprintf(buffer, SIZE, "delayed writes: %d\n", mNumDelayedWrites);
298 result.append(buffer);
299 snprintf(buffer, SIZE, "blocked in write: %d\n", mInWrite);
300 result.append(buffer);
301 snprintf(buffer, SIZE, "standby: %d\n", mStandby);
302 result.append(buffer);
303 snprintf(buffer, SIZE, "Hardware status: %d\n", mHardwareStatus);
304 result.append(buffer);
305 write(fd, result.string(), result.size());
306 return NO_ERROR;
307}
308
309status_t AudioFlinger::dumpPermissionDenial(int fd, const Vector<String16>& args)
310{
311 const size_t SIZE = 256;
312 char buffer[SIZE];
313 String8 result;
314 snprintf(buffer, SIZE, "Permission Denial: "
315 "can't dump AudioFlinger from pid=%d, uid=%d\n",
316 IPCThreadState::self()->getCallingPid(),
317 IPCThreadState::self()->getCallingUid());
318 result.append(buffer);
319 write(fd, result.string(), result.size());
320 return NO_ERROR;
321}
322
323status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
324{
325 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
326 dumpPermissionDenial(fd, args);
327 } else {
328 AutoMutex lock(&mLock);
329
330 dumpClients(fd, args);
331 dumpTracks(fd, args);
332 dumpInternals(fd, args);
333 if (mAudioHardware) {
334 mAudioHardware->dumpState(fd, args);
335 }
336 }
337 return NO_ERROR;
338}
339
340// Thread virtuals
341bool AudioFlinger::threadLoop()
342{
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700343 unsigned long sleepTime = kBufferRecoveryInUsecs;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700344 int16_t* curBuf = mMixBuffer;
345 Vector< sp<Track> > tracksToRemove;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800346 size_t enabledTracks = 0;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700347 nsecs_t standbyTime = systemTime();
348
349 do {
350 enabledTracks = 0;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800351 { // scope for the mLock
352
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700353 Mutex::Autolock _l(mLock);
354 const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
355
356 // put audio hardware into standby after short delay
357 if UNLIKELY(!activeTracks.size() && systemTime() > standbyTime) {
358 // wait until we have something to do...
359 LOGV("Audio hardware entering standby\n");
360 mHardwareStatus = AUDIO_HW_STANDBY;
361 if (!mStandby) {
The Android Open Source Project27629322009-01-09 17:51:23 -0800362 mOutput->standby();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700363 mStandby = true;
364 }
365 mHardwareStatus = AUDIO_HW_IDLE;
366 // we're about to wait, flush the binder command buffer
367 IPCThreadState::self()->flushCommands();
368 mWaitWorkCV.wait(mLock);
369 LOGV("Audio hardware exiting standby\n");
370 standbyTime = systemTime() + kStandbyTimeInNsecs;
371 continue;
372 }
373
The Android Open Source Project27629322009-01-09 17:51:23 -0800374 // check for change in output
375 if (mRequestedOutput != mOutput) {
376
377 // put current output into standby mode
378 if (mOutput) mOutput->standby();
379
380 // change output
381 doSetOutput(mRequestedOutput);
382 }
383
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700384 // find out which tracks need to be processed
385 size_t count = activeTracks.size();
386 for (size_t i=0 ; i<count ; i++) {
387 sp<Track> t = activeTracks[i].promote();
388 if (t == 0) continue;
389
390 Track* const track = t.get();
391 audio_track_cblk_t* cblk = track->cblk();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700392
393 // The first time a track is added we wait
394 // for all its buffers to be filled before processing it
The Android Open Source Project27629322009-01-09 17:51:23 -0800395 mAudioMixer->setActiveTrack(track->name());
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800396 if (cblk->framesReady() && (track->isReady() || track->isStopped()) &&
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700397 !track->isPaused())
398 {
399 //LOGD("u=%08x, s=%08x [OK]", u, s);
400
401 // compute volume for this track
402 int16_t left, right;
403 if (track->isMuted() || mMasterMute || track->isPausing()) {
404 left = right = 0;
405 if (track->isPausing()) {
406 LOGV("paused(%d)", track->name());
407 track->setPaused();
408 }
409 } else {
410 float typeVolume = mStreamTypes[track->type()].volume;
411 float v = mMasterVolume * typeVolume;
412 float v_clamped = v * cblk->volume[0];
413 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
414 left = int16_t(v_clamped);
415 v_clamped = v * cblk->volume[1];
416 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
417 right = int16_t(v_clamped);
418 }
419
420 // XXX: these things DON'T need to be done each time
The Android Open Source Project27629322009-01-09 17:51:23 -0800421 mAudioMixer->setBufferProvider(track);
422 mAudioMixer->enable(AudioMixer::MIXING);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700423
424 int param;
425 if ( track->mFillingUpStatus == Track::FS_FILLED) {
426 // no ramp for the first volume setting
427 track->mFillingUpStatus = Track::FS_ACTIVE;
428 if (track->mState == TrackBase::RESUMING) {
429 track->mState = TrackBase::ACTIVE;
430 param = AudioMixer::RAMP_VOLUME;
431 } else {
432 param = AudioMixer::VOLUME;
433 }
434 } else {
435 param = AudioMixer::RAMP_VOLUME;
436 }
The Android Open Source Project27629322009-01-09 17:51:23 -0800437 mAudioMixer->setParameter(param, AudioMixer::VOLUME0, left);
438 mAudioMixer->setParameter(param, AudioMixer::VOLUME1, right);
439 mAudioMixer->setParameter(
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700440 AudioMixer::TRACK,
441 AudioMixer::FORMAT, track->format());
The Android Open Source Project27629322009-01-09 17:51:23 -0800442 mAudioMixer->setParameter(
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700443 AudioMixer::TRACK,
444 AudioMixer::CHANNEL_COUNT, track->channelCount());
The Android Open Source Project27629322009-01-09 17:51:23 -0800445 mAudioMixer->setParameter(
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700446 AudioMixer::RESAMPLE,
447 AudioMixer::SAMPLE_RATE,
448 int(cblk->sampleRate));
449
450 // reset retry count
451 track->mRetryCount = kMaxTrackRetries;
452 enabledTracks++;
453 } else {
454 //LOGD("u=%08x, s=%08x [NOT READY]", u, s);
455 if (track->isStopped()) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800456 track->reset();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700457 }
458 if (track->isTerminated() || track->isStopped() || track->isPaused()) {
459 // We have consumed all the buffers of this track.
460 // Remove it from the list of active tracks.
461 LOGV("remove(%d) from active list", track->name());
462 tracksToRemove.add(track);
463 } else {
464 // No buffers for this track. Give it a few chances to
465 // fill a buffer, then remove it from active list.
466 if (--(track->mRetryCount) <= 0) {
467 LOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
468 tracksToRemove.add(track);
469 }
470 }
471 // LOGV("disable(%d)", track->name());
The Android Open Source Project27629322009-01-09 17:51:23 -0800472 mAudioMixer->disable(AudioMixer::MIXING);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700473 }
474 }
475
476 // remove all the tracks that need to be...
477 count = tracksToRemove.size();
478 if (UNLIKELY(count)) {
479 for (size_t i=0 ; i<count ; i++) {
480 const sp<Track>& track = tracksToRemove[i];
The Android Open Source Projecte41dd752009-01-22 00:13:42 -0800481 removeActiveTrack(track);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700482 if (track->isTerminated()) {
483 mTracks.remove(track);
The Android Open Source Project27629322009-01-09 17:51:23 -0800484 mAudioMixer->deleteTrackName(track->mName);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700485 }
486 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800487 }
488 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700489 if (LIKELY(enabledTracks)) {
490 // mix buffers...
The Android Open Source Project27629322009-01-09 17:51:23 -0800491 mAudioMixer->process(curBuf);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700492
493 // output audio to hardware
494 mLastWriteTime = systemTime();
495 mInWrite = true;
The Android Open Source Project27629322009-01-09 17:51:23 -0800496 size_t mixBufferSize = mFrameCount*mChannelCount*sizeof(int16_t);
497 mOutput->write(curBuf, mixBufferSize);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700498 mNumWrites++;
499 mInWrite = false;
500 mStandby = false;
501 nsecs_t temp = systemTime();
502 standbyTime = temp + kStandbyTimeInNsecs;
503 nsecs_t delta = temp - mLastWriteTime;
The Android Open Source Project27629322009-01-09 17:51:23 -0800504 nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 2;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700505 if (delta > maxPeriod) {
506 LOGW("write blocked for %llu msecs", ns2ms(delta));
507 mNumDelayedWrites++;
508 }
509 sleepTime = kBufferRecoveryInUsecs;
510 } else {
511 // There was nothing to mix this round, which means all
512 // active tracks were late. Sleep a little bit to give
513 // them another chance. If we're too late, the audio
514 // hardware will zero-fill for us.
515 LOGV("no buffers - usleep(%lu)", sleepTime);
516 usleep(sleepTime);
517 if (sleepTime < kMaxBufferRecoveryInUsecs) {
518 sleepTime += kBufferRecoveryInUsecs;
519 }
520 }
521
522 // finally let go of all our tracks, without the lock held
523 // since we can't guarantee the destructors won't acquire that
524 // same lock.
525 tracksToRemove.clear();
526 } while (true);
527
528 return false;
529}
530
531status_t AudioFlinger::readyToRun()
532{
533 if (mSampleRate == 0) {
534 LOGE("No working audio driver found.");
535 return NO_INIT;
536 }
537 LOGI("AudioFlinger's main thread ready to run.");
538 return NO_ERROR;
539}
540
541void AudioFlinger::onFirstRef()
542{
543 run("AudioFlinger", ANDROID_PRIORITY_URGENT_AUDIO);
544}
545
546// IAudioFlinger interface
547sp<IAudioTrack> AudioFlinger::createTrack(
548 pid_t pid,
549 int streamType,
550 uint32_t sampleRate,
551 int format,
552 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800553 int frameCount,
554 uint32_t flags,
555 const sp<IMemory>& sharedBuffer,
556 status_t *status)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700557{
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700558 sp<Track> track;
559 sp<TrackHandle> trackHandle;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700560 sp<Client> client;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800561 wp<Client> wclient;
562 status_t lStatus;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700563
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800564 if (streamType >= AudioTrack::NUM_STREAM_TYPES) {
565 LOGE("invalid stream type");
566 lStatus = BAD_VALUE;
567 goto Exit;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700568 }
569
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800570 // Resampler implementation limits input sampling rate to 2 x output sampling rate.
571 if (sampleRate > MAX_SAMPLE_RATE || sampleRate > mSampleRate*2) {
572 LOGE("Sample rate out of range: %d", sampleRate);
573 lStatus = BAD_VALUE;
574 goto Exit;
575 }
576
577 {
578 Mutex::Autolock _l(mLock);
579
580 if (mSampleRate == 0) {
581 LOGE("Audio driver not initialized.");
582 lStatus = NO_INIT;
583 goto Exit;
584 }
585
586 wclient = mClients.valueFor(pid);
587
588 if (wclient != NULL) {
589 client = wclient.promote();
590 } else {
591 client = new Client(this, pid);
592 mClients.add(pid, client);
593 }
594
595 track = new Track(this, client, streamType, sampleRate, format,
596 channelCount, frameCount, sharedBuffer);
597 mTracks.add(track);
598 trackHandle = new TrackHandle(track);
599
600 lStatus = NO_ERROR;
601 }
602
603Exit:
604 if(status) {
605 *status = lStatus;
606 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700607 return trackHandle;
608}
609
610uint32_t AudioFlinger::sampleRate() const
611{
612 return mSampleRate;
613}
614
615int AudioFlinger::channelCount() const
616{
617 return mChannelCount;
618}
619
620int AudioFlinger::format() const
621{
622 return mFormat;
623}
624
625size_t AudioFlinger::frameCount() const
626{
627 return mFrameCount;
628}
629
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800630uint32_t AudioFlinger::latency() const
631{
632 if (mOutput) {
633 return mOutput->latency();
634 }
635 else {
636 return 0;
637 }
638}
639
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700640status_t AudioFlinger::setMasterVolume(float value)
641{
642 // check calling permissions
643 if (!settingsAllowed()) {
644 return PERMISSION_DENIED;
645 }
646
647 // when hw supports master volume, don't scale in sw mixer
648 AutoMutex lock(mHardwareLock);
649 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
650 if (mAudioHardware->setMasterVolume(value) == NO_ERROR) {
651 mMasterVolume = 1.0f;
652 }
653 else {
654 mMasterVolume = value;
655 }
656 mHardwareStatus = AUDIO_HW_IDLE;
657 return NO_ERROR;
658}
659
660status_t AudioFlinger::setRouting(int mode, uint32_t routes, uint32_t mask)
661{
The Android Open Source Project27629322009-01-09 17:51:23 -0800662 status_t err = NO_ERROR;
663
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700664 // check calling permissions
665 if (!settingsAllowed()) {
666 return PERMISSION_DENIED;
667 }
668 if ((mode < AudioSystem::MODE_CURRENT) || (mode >= AudioSystem::NUM_MODES)) {
669 LOGW("Illegal value: setRouting(%d, %u, %u)", mode, routes, mask);
670 return BAD_VALUE;
671 }
672
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800673#ifdef WITH_A2DP
674 LOGD("setRouting %d %d %d\n", mode, routes, mask);
675 if (mode == AudioSystem::MODE_NORMAL &&
676 (mask & AudioSystem::ROUTE_BLUETOOTH_A2DP)) {
The Android Open Source Projecte41dd752009-01-22 00:13:42 -0800677 AutoMutex lock(&mLock);
678
679 bool enableA2dp = false;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800680 if (routes & AudioSystem::ROUTE_BLUETOOTH_A2DP) {
The Android Open Source Projecte41dd752009-01-22 00:13:42 -0800681 if (mA2dpDisableCount > 0)
682 mA2dpSuppressed = true;
683 else
684 enableA2dp = true;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800685 }
The Android Open Source Projecte41dd752009-01-22 00:13:42 -0800686 setA2dpEnabled(enableA2dp);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800687 LOGD("setOutput done\n");
688 }
689#endif
690
The Android Open Source Project27629322009-01-09 17:51:23 -0800691 // do nothing if only A2DP routing is affected
692 mask &= ~AudioSystem::ROUTE_BLUETOOTH_A2DP;
693 if (mask) {
694 AutoMutex lock(mHardwareLock);
695 mHardwareStatus = AUDIO_HW_GET_ROUTING;
696 uint32_t r;
697 err = mAudioHardware->getRouting(mode, &r);
698 if (err == NO_ERROR) {
699 r = (r & ~mask) | (routes & mask);
700 mHardwareStatus = AUDIO_HW_SET_ROUTING;
701 err = mAudioHardware->setRouting(mode, r);
702 }
703 mHardwareStatus = AUDIO_HW_IDLE;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700704 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700705 return err;
706}
707
708uint32_t AudioFlinger::getRouting(int mode) const
709{
710 uint32_t routes = 0;
711 if ((mode >= AudioSystem::MODE_CURRENT) && (mode < AudioSystem::NUM_MODES)) {
712 mHardwareStatus = AUDIO_HW_GET_ROUTING;
713 mAudioHardware->getRouting(mode, &routes);
714 mHardwareStatus = AUDIO_HW_IDLE;
715 } else {
716 LOGW("Illegal value: getRouting(%d)", mode);
717 }
718 return routes;
719}
720
721status_t AudioFlinger::setMode(int mode)
722{
723 // check calling permissions
724 if (!settingsAllowed()) {
725 return PERMISSION_DENIED;
726 }
727 if ((mode < 0) || (mode >= AudioSystem::NUM_MODES)) {
728 LOGW("Illegal value: setMode(%d)", mode);
729 return BAD_VALUE;
730 }
731
732 AutoMutex lock(mHardwareLock);
733 mHardwareStatus = AUDIO_HW_SET_MODE;
734 status_t ret = mAudioHardware->setMode(mode);
735 mHardwareStatus = AUDIO_HW_IDLE;
736 return ret;
737}
738
739int AudioFlinger::getMode() const
740{
741 int mode = AudioSystem::MODE_INVALID;
742 mHardwareStatus = AUDIO_HW_SET_MODE;
743 mAudioHardware->getMode(&mode);
744 mHardwareStatus = AUDIO_HW_IDLE;
745 return mode;
746}
747
748status_t AudioFlinger::setMicMute(bool state)
749{
750 // check calling permissions
751 if (!settingsAllowed()) {
752 return PERMISSION_DENIED;
753 }
754
755 AutoMutex lock(mHardwareLock);
756 mHardwareStatus = AUDIO_HW_SET_MIC_MUTE;
757 status_t ret = mAudioHardware->setMicMute(state);
758 mHardwareStatus = AUDIO_HW_IDLE;
759 return ret;
760}
761
762bool AudioFlinger::getMicMute() const
763{
764 bool state = AudioSystem::MODE_INVALID;
765 mHardwareStatus = AUDIO_HW_GET_MIC_MUTE;
766 mAudioHardware->getMicMute(&state);
767 mHardwareStatus = AUDIO_HW_IDLE;
768 return state;
769}
770
771status_t AudioFlinger::setMasterMute(bool muted)
772{
773 // check calling permissions
774 if (!settingsAllowed()) {
775 return PERMISSION_DENIED;
776 }
777
778 mMasterMute = muted;
779 return NO_ERROR;
780}
781
782float AudioFlinger::masterVolume() const
783{
784 return mMasterVolume;
785}
786
787bool AudioFlinger::masterMute() const
788{
789 return mMasterMute;
790}
791
792status_t AudioFlinger::setStreamVolume(int stream, float value)
793{
794 // check calling permissions
795 if (!settingsAllowed()) {
796 return PERMISSION_DENIED;
797 }
798
799 if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) {
800 return BAD_VALUE;
801 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800802
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700803 status_t ret = NO_ERROR;
804 if (stream == AudioTrack::VOICE_CALL) {
805 AutoMutex lock(mHardwareLock);
806 mHardwareStatus = AUDIO_SET_VOICE_VOLUME;
807 ret = mAudioHardware->setVoiceVolume(value);
808 mHardwareStatus = AUDIO_HW_IDLE;
James E. Blair6015dfc2009-01-17 13:30:20 -0800809 // FIXME: This is a temporary fix to re-base the internally
810 // generated in-call audio so that it is never muted, which is
811 // already the case for the hardware routed in-call audio.
812 // When audio stream handling is reworked, this should be
813 // addressed more cleanly. Fixes #1324; see discussion at
814 // http://review.source.android.com/8224
815 mStreamTypes[stream].volume = value * (1.0 - 1.0 / 6.0) + (1.0 / 6.0);
816 } else {
817 mStreamTypes[stream].volume = value;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700818 }
819 return ret;
820}
821
822status_t AudioFlinger::setStreamMute(int stream, bool muted)
823{
824 // check calling permissions
825 if (!settingsAllowed()) {
826 return PERMISSION_DENIED;
827 }
828
829 if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) {
830 return BAD_VALUE;
831 }
832 mStreamTypes[stream].mute = muted;
833 return NO_ERROR;
834}
835
836float AudioFlinger::streamVolume(int stream) const
837{
838 if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) {
839 return 0.0f;
840 }
James E. Blair6015dfc2009-01-17 13:30:20 -0800841 if (stream == AudioTrack::VOICE_CALL) {
842 // FIXME: Re-base internally generated in-call audio,
843 // reverse of above in setStreamVolume.
844 return (mStreamTypes[stream].volume - (1.0 / 6.0)) / (1.0 - 1.0 / 6.0);
845 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700846 return mStreamTypes[stream].volume;
847}
848
849bool AudioFlinger::streamMute(int stream) const
850{
851 if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) {
852 return true;
853 }
854 return mStreamTypes[stream].mute;
855}
856
857bool AudioFlinger::isMusicActive() const
858{
859 size_t count = mActiveTracks.size();
860 for (size_t i = 0 ; i < count ; ++i) {
861 sp<Track> t = mActiveTracks[i].promote();
862 if (t == 0) continue;
863 Track* const track = t.get();
864 if (t->mStreamType == AudioTrack::MUSIC)
865 return true;
866 }
867 return false;
868}
869
870status_t AudioFlinger::setParameter(const char* key, const char* value)
871{
The Android Open Source Project8a7a6752009-01-15 16:12:10 -0800872 status_t result, result2;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700873 AutoMutex lock(mHardwareLock);
874 mHardwareStatus = AUDIO_SET_PARAMETER;
875 result = mAudioHardware->setParameter(key, value);
The Android Open Source Project8a7a6752009-01-15 16:12:10 -0800876 if (mA2dpAudioInterface) {
877 result2 = mA2dpAudioInterface->setParameter(key, value);
878 if (result2)
879 result = result2;
880 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700881 mHardwareStatus = AUDIO_HW_IDLE;
882 return result;
883}
884
885void AudioFlinger::removeClient(pid_t pid)
886{
887 Mutex::Autolock _l(mLock);
888 mClients.removeItem(pid);
889}
890
891status_t AudioFlinger::addTrack(const sp<Track>& track)
892{
893 Mutex::Autolock _l(mLock);
894
895 // here the track could be either new, or restarted
896 // in both cases "unstop" the track
897 if (track->isPaused()) {
898 track->mState = TrackBase::RESUMING;
899 LOGV("PAUSED => RESUMING (%d)", track->name());
900 } else {
901 track->mState = TrackBase::ACTIVE;
902 LOGV("? => ACTIVE (%d)", track->name());
903 }
904 // set retry count for buffer fill
905 track->mRetryCount = kMaxTrackStartupRetries;
906 LOGV("mWaitWorkCV.broadcast");
907 mWaitWorkCV.broadcast();
908
909 if (mActiveTracks.indexOf(track) < 0) {
910 // the track is newly added, make sure it fills up all its
911 // buffers before playing. This is to ensure the client will
912 // effectively get the latency it requested.
913 track->mFillingUpStatus = Track::FS_FILLING;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800914 track->mResetDone = false;
The Android Open Source Projecte41dd752009-01-22 00:13:42 -0800915 addActiveTrack(track);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700916 return NO_ERROR;
917 }
918 return ALREADY_EXISTS;
919}
920
921void AudioFlinger::removeTrack(wp<Track> track, int name)
922{
923 Mutex::Autolock _l(mLock);
924 sp<Track> t = track.promote();
925 if (t!=NULL && (t->mState <= TrackBase::STOPPED)) {
926 remove_track_l(track, name);
927 }
928}
929
930void AudioFlinger::remove_track_l(wp<Track> track, int name)
931{
932 sp<Track> t = track.promote();
933 if (t!=NULL) {
934 t->reset();
935 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800936 audioMixer()->deleteTrackName(name);
The Android Open Source Projecte41dd752009-01-22 00:13:42 -0800937 removeActiveTrack(track);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700938 mWaitWorkCV.broadcast();
939}
940
941void AudioFlinger::destroyTrack(const sp<Track>& track)
942{
943 // NOTE: We're acquiring a strong reference on the track before
944 // acquiring the lock, this is to make sure removing it from
945 // mTracks won't cause the destructor to be called while the lock is
946 // held (note that technically, 'track' could be a reference to an item
947 // in mTracks, which is why we need to do this).
948 sp<Track> keep(track);
949 Mutex::Autolock _l(mLock);
950 track->mState = TrackBase::TERMINATED;
951 if (mActiveTracks.indexOf(track) < 0) {
952 LOGV("remove track (%d) and delete from mixer", track->name());
953 mTracks.remove(track);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800954 audioMixer()->deleteTrackName(keep->name());
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700955 }
956}
957
The Android Open Source Projecte41dd752009-01-22 00:13:42 -0800958void AudioFlinger::addActiveTrack(const wp<Track>& t)
959{
960 mActiveTracks.add(t);
961
962#ifdef WITH_A2DP
963 // disable A2DP for certain stream types
964 sp<Track> track = t.promote();
965 if (streamDisablesA2dp(track->type())) {
966 if (mA2dpDisableCount++ == 0 && isA2dpEnabled()) {
967 setA2dpEnabled(false);
968 mA2dpSuppressed = true;
969 LOGD("mA2dpSuppressed = true\n");
970 }
971 LOGD("mA2dpDisableCount incremented to %d\n", mA2dpDisableCount);
972 }
973#endif
974}
975
976void AudioFlinger::removeActiveTrack(const wp<Track>& t)
977{
978 mActiveTracks.remove(t);
979#ifdef WITH_A2DP
980 // disable A2DP for certain stream types
981 sp<Track> track = t.promote();
982 if (streamDisablesA2dp(track->type())) {
983 if (mA2dpDisableCount > 0) {
984 mA2dpDisableCount--;
985 if (mA2dpDisableCount == 0 && mA2dpSuppressed) {
986 setA2dpEnabled(true);
987 mA2dpSuppressed = false;
988 }
989 LOGD("mA2dpDisableCount decremented to %d\n", mA2dpDisableCount);
990 } else
991 LOGE("mA2dpDisableCount is already zero");
992 }
993#endif
994}
995
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700996// ----------------------------------------------------------------------------
997
998AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
999 : RefBase(),
1000 mAudioFlinger(audioFlinger),
1001 mMemoryDealer(new MemoryDealer(1024*1024)),
1002 mPid(pid)
1003{
1004 // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
1005}
1006
1007AudioFlinger::Client::~Client()
1008{
1009 mAudioFlinger->removeClient(mPid);
1010}
1011
1012const sp<MemoryDealer>& AudioFlinger::Client::heap() const
1013{
1014 return mMemoryDealer;
1015}
1016
1017// ----------------------------------------------------------------------------
1018
1019AudioFlinger::TrackBase::TrackBase(
1020 const sp<AudioFlinger>& audioFlinger,
1021 const sp<Client>& client,
1022 int streamType,
1023 uint32_t sampleRate,
1024 int format,
1025 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001026 int frameCount,
1027 const sp<IMemory>& sharedBuffer)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001028 : RefBase(),
1029 mAudioFlinger(audioFlinger),
1030 mClient(client),
1031 mStreamType(streamType),
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001032 mFrameCount(0),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001033 mState(IDLE),
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001034 mClientTid(-1),
1035 mFormat(format),
1036 mFlags(0)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001037{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001038 mName = audioFlinger->audioMixer()->getTrackName();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001039 if (mName < 0) {
1040 LOGE("no more track names availlable");
1041 return;
1042 }
1043
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001044 LOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size());
1045
1046
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001047 // LOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001048 size_t size = sizeof(audio_track_cblk_t);
1049 size_t bufferSize = frameCount*channelCount*sizeof(int16_t);
1050 if (sharedBuffer == 0) {
1051 size += bufferSize;
1052 }
1053
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001054 mCblkMemory = client->heap()->allocate(size);
1055 if (mCblkMemory != 0) {
1056 mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer());
1057 if (mCblk) { // construct the shared structure in-place.
1058 new(mCblk) audio_track_cblk_t();
1059 // clear all buffers
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001060 mCblk->frameCount = frameCount;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001061 mCblk->sampleRate = sampleRate;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001062 mCblk->channels = channelCount;
1063 if (sharedBuffer == 0) {
1064 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
1065 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
1066 // Force underrun condition to avoid false underrun callback until first data is
1067 // written to buffer
1068 mCblk->flowControlFlag = 1;
1069 } else {
1070 mBuffer = sharedBuffer->pointer();
1071 }
1072 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001073 }
1074 } else {
1075 LOGE("not enough memory for AudioTrack size=%u", size);
1076 client->heap()->dump("AudioTrack");
1077 return;
1078 }
1079}
1080
1081AudioFlinger::TrackBase::~TrackBase()
1082{
1083 mCblk->~audio_track_cblk_t(); // destroy our shared-structure.
1084 mCblkMemory.clear(); // and free the shared memory
1085 mClient.clear();
1086}
1087
1088void AudioFlinger::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
1089{
1090 buffer->raw = 0;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001091 mFrameCount = buffer->frameCount;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001092 step();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001093 buffer->frameCount = 0;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001094}
1095
1096bool AudioFlinger::TrackBase::step() {
1097 bool result;
1098 audio_track_cblk_t* cblk = this->cblk();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001099
1100 result = cblk->stepServer(mFrameCount);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001101 if (!result) {
1102 LOGV("stepServer failed acquiring cblk mutex");
1103 mFlags |= STEPSERVER_FAILED;
1104 }
1105 return result;
1106}
1107
1108void AudioFlinger::TrackBase::reset() {
1109 audio_track_cblk_t* cblk = this->cblk();
1110
1111 cblk->user = 0;
1112 cblk->server = 0;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001113 cblk->userBase = 0;
1114 cblk->serverBase = 0;
1115 mFlags = 0;
1116 LOGV("TrackBase::reset");
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001117}
1118
1119sp<IMemory> AudioFlinger::TrackBase::getCblk() const
1120{
1121 return mCblkMemory;
1122}
1123
1124int AudioFlinger::TrackBase::sampleRate() const {
1125 return mCblk->sampleRate;
1126}
1127
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001128int AudioFlinger::TrackBase::channelCount() const {
1129 return mCblk->channels;
1130}
1131
1132void* AudioFlinger::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
1133 audio_track_cblk_t* cblk = this->cblk();
1134 int16_t *bufferStart = (int16_t *)mBuffer + (offset-cblk->serverBase)*cblk->channels;
1135 int16_t *bufferEnd = bufferStart + frames * cblk->channels;
1136
1137 // Check validity of returned pointer in case the track control block would have been corrupted.
1138 if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd) {
1139 LOGW("TrackBase::getBuffer buffer out of range:\n start: %p, end %p , mBuffer %p mBufferEnd %p\n \
1140 server %d, serverBase %d, user %d, userBase %d",
1141 bufferStart, bufferEnd, mBuffer, mBufferEnd,
1142 cblk->server, cblk->serverBase, cblk->user, cblk->userBase);
1143 return 0;
1144 }
1145
1146 return bufferStart;
1147}
1148
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001149// ----------------------------------------------------------------------------
1150
1151AudioFlinger::Track::Track(
1152 const sp<AudioFlinger>& audioFlinger,
1153 const sp<Client>& client,
1154 int streamType,
1155 uint32_t sampleRate,
1156 int format,
1157 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001158 int frameCount,
1159 const sp<IMemory>& sharedBuffer)
1160 : TrackBase(audioFlinger, client, streamType, sampleRate, format, channelCount, frameCount, sharedBuffer)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001161{
1162 mVolume[0] = 1.0f;
1163 mVolume[1] = 1.0f;
1164 mMute = false;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001165 mSharedBuffer = sharedBuffer;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001166}
1167
1168AudioFlinger::Track::~Track()
1169{
1170 wp<Track> weak(this); // never create a strong ref from the dtor
1171 mState = TERMINATED;
1172 mAudioFlinger->removeTrack(weak, mName);
1173}
1174
1175void AudioFlinger::Track::destroy()
1176{
1177 mAudioFlinger->destroyTrack(this);
1178}
1179
1180void AudioFlinger::Track::dump(char* buffer, size_t size)
1181{
1182 snprintf(buffer, size, " %5d %5d %3u %3u %3u %3u %1d %1d %1d %5u %5u %5u %04x %04x\n",
1183 mName - AudioMixer::TRACK0,
1184 mClient->pid(),
1185 mStreamType,
1186 mFormat,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001187 mCblk->channels,
1188 mFrameCount,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001189 mState,
1190 mMute,
1191 mFillingUpStatus,
1192 mCblk->sampleRate,
1193 mCblk->volume[0],
1194 mCblk->volume[1],
1195 mCblk->server,
1196 mCblk->user);
1197}
1198
1199status_t AudioFlinger::Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
1200{
1201 audio_track_cblk_t* cblk = this->cblk();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001202 uint32_t framesReady;
1203 uint32_t framesReq = buffer->frameCount;
1204
1205 // Check if last stepServer failed, try to step now
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001206 if (mFlags & TrackBase::STEPSERVER_FAILED) {
1207 if (!step()) goto getNextBuffer_exit;
1208 LOGV("stepServer recovered");
1209 mFlags &= ~TrackBase::STEPSERVER_FAILED;
1210 }
1211
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001212 framesReady = cblk->framesReady();
1213
1214 if (LIKELY(framesReady)) {
1215 uint32_t s = cblk->server;
1216 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
1217
1218 bufferEnd = (cblk->loopEnd < bufferEnd) ? cblk->loopEnd : bufferEnd;
1219 if (framesReq > framesReady) {
1220 framesReq = framesReady;
1221 }
1222 if (s + framesReq > bufferEnd) {
1223 framesReq = bufferEnd - s;
1224 }
1225
1226 buffer->raw = getBuffer(s, framesReq);
1227 if (buffer->raw == 0) goto getNextBuffer_exit;
1228
1229 buffer->frameCount = framesReq;
1230 return NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001231 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001232
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001233getNextBuffer_exit:
1234 buffer->raw = 0;
1235 buffer->frameCount = 0;
1236 return NOT_ENOUGH_DATA;
1237}
1238
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001239bool AudioFlinger::Track::isReady() const {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001240 if (mFillingUpStatus != FS_FILLING) return true;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001241
1242 if (mCblk->framesReady() >= mCblk->frameCount ||
1243 mCblk->forceReady) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001244 mFillingUpStatus = FS_FILLED;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001245 mCblk->forceReady = 0;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001246 return true;
1247 }
1248 return false;
1249}
1250
1251status_t AudioFlinger::Track::start()
1252{
1253 LOGV("start(%d)", mName);
1254 mAudioFlinger->addTrack(this);
1255 return NO_ERROR;
1256}
1257
1258void AudioFlinger::Track::stop()
1259{
1260 LOGV("stop(%d)", mName);
1261 Mutex::Autolock _l(mAudioFlinger->mLock);
1262 if (mState > STOPPED) {
1263 mState = STOPPED;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001264 // If the track is not active (PAUSED and buffers full), flush buffers
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001265 if (mAudioFlinger->mActiveTracks.indexOf(this) < 0) {
1266 reset();
1267 }
1268 LOGV("(> STOPPED) => STOPPED (%d)", mName);
1269 }
1270}
1271
1272void AudioFlinger::Track::pause()
1273{
1274 LOGV("pause(%d)", mName);
1275 Mutex::Autolock _l(mAudioFlinger->mLock);
1276 if (mState == ACTIVE || mState == RESUMING) {
1277 mState = PAUSING;
1278 LOGV("ACTIVE/RESUMING => PAUSING (%d)", mName);
1279 }
1280}
1281
1282void AudioFlinger::Track::flush()
1283{
1284 LOGV("flush(%d)", mName);
1285 Mutex::Autolock _l(mAudioFlinger->mLock);
1286 if (mState != STOPPED && mState != PAUSED && mState != PAUSING) {
1287 return;
1288 }
1289 // No point remaining in PAUSED state after a flush => go to
1290 // STOPPED state
1291 mState = STOPPED;
1292
1293 // NOTE: reset() will reset cblk->user and cblk->server with
1294 // the risk that at the same time, the AudioMixer is trying to read
1295 // data. In this case, getNextBuffer() would return a NULL pointer
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001296 // as audio buffer => the AudioMixer code MUST always test that pointer
1297 // returned by getNextBuffer() is not NULL!
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001298 reset();
1299}
1300
1301void AudioFlinger::Track::reset()
1302{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001303 // Do not reset twice to avoid discarding data written just after a flush and before
1304 // the audioflinger thread detects the track is stopped.
1305 if (!mResetDone) {
1306 TrackBase::reset();
1307 // Force underrun condition to avoid false underrun callback until first data is
1308 // written to buffer
1309 mCblk->flowControlFlag = 1;
1310 mCblk->forceReady = 0;
1311 mFillingUpStatus = FS_FILLING;
1312 mResetDone = true;
1313 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001314}
1315
1316void AudioFlinger::Track::mute(bool muted)
1317{
1318 mMute = muted;
1319}
1320
1321void AudioFlinger::Track::setVolume(float left, float right)
1322{
1323 mVolume[0] = left;
1324 mVolume[1] = right;
1325}
1326
1327// ----------------------------------------------------------------------------
1328
1329AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::Track>& track)
1330 : BnAudioTrack(),
1331 mTrack(track)
1332{
1333}
1334
1335AudioFlinger::TrackHandle::~TrackHandle() {
1336 // just stop the track on deletion, associated resources
1337 // will be freed from the main thread once all pending buffers have
1338 // been played. Unless it's not in the active track list, in which
1339 // case we free everything now...
1340 mTrack->destroy();
1341}
1342
1343status_t AudioFlinger::TrackHandle::start() {
1344 return mTrack->start();
1345}
1346
1347void AudioFlinger::TrackHandle::stop() {
1348 mTrack->stop();
1349}
1350
1351void AudioFlinger::TrackHandle::flush() {
1352 mTrack->flush();
1353}
1354
1355void AudioFlinger::TrackHandle::mute(bool e) {
1356 mTrack->mute(e);
1357}
1358
1359void AudioFlinger::TrackHandle::pause() {
1360 mTrack->pause();
1361}
1362
1363void AudioFlinger::TrackHandle::setVolume(float left, float right) {
1364 mTrack->setVolume(left, right);
1365}
1366
1367sp<IMemory> AudioFlinger::TrackHandle::getCblk() const {
1368 return mTrack->getCblk();
1369}
1370
1371status_t AudioFlinger::TrackHandle::onTransact(
1372 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1373{
1374 return BnAudioTrack::onTransact(code, data, reply, flags);
1375}
1376
1377// ----------------------------------------------------------------------------
1378
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001379sp<IAudioRecord> AudioFlinger::openRecord(
1380 pid_t pid,
1381 int streamType,
1382 uint32_t sampleRate,
1383 int format,
1384 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001385 int frameCount,
1386 uint32_t flags,
1387 status_t *status)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001388{
1389 sp<AudioRecordThread> thread;
1390 sp<RecordTrack> recordTrack;
1391 sp<RecordHandle> recordHandle;
1392 sp<Client> client;
1393 wp<Client> wclient;
1394 AudioStreamIn* input = 0;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001395 int inFrameCount;
1396 size_t inputBufferSize;
1397 status_t lStatus;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001398
1399 // check calling permissions
1400 if (!recordingAllowed()) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001401 lStatus = PERMISSION_DENIED;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001402 goto Exit;
1403 }
1404
1405 if (uint32_t(streamType) >= AudioRecord::NUM_STREAM_TYPES) {
1406 LOGE("invalid stream type");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001407 lStatus = BAD_VALUE;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001408 goto Exit;
1409 }
1410
1411 if (sampleRate > MAX_SAMPLE_RATE) {
1412 LOGE("Sample rate out of range");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001413 lStatus = BAD_VALUE;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001414 goto Exit;
1415 }
1416
1417 if (mSampleRate == 0) {
1418 LOGE("Audio driver not initialized");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001419 lStatus = NO_INIT;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001420 goto Exit;
1421 }
1422
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001423 if (mAudioRecordThread == 0) {
1424 LOGE("Audio record thread not started");
1425 lStatus = NO_INIT;
1426 goto Exit;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001427 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001428
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001429
1430 // Check that audio input stream accepts requested audio parameters
1431 inputBufferSize = mAudioHardware->getInputBufferSize(sampleRate, format, channelCount);
1432 if (inputBufferSize == 0) {
1433 lStatus = BAD_VALUE;
1434 LOGE("Bad audio input parameters: sampling rate %u, format %d, channels %d", sampleRate, format, channelCount);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001435 goto Exit;
1436 }
1437
1438 // add client to list
1439 {
1440 Mutex::Autolock _l(mLock);
1441 wclient = mClients.valueFor(pid);
1442 if (wclient != NULL) {
1443 client = wclient.promote();
1444 } else {
1445 client = new Client(this, pid);
1446 mClients.add(pid, client);
1447 }
1448 }
1449
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001450 // frameCount must be a multiple of input buffer size
1451 inFrameCount = inputBufferSize/channelCount/sizeof(short);
1452 frameCount = ((frameCount - 1)/inFrameCount + 1) * inFrameCount;
1453
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001454 // create new record track and pass to record thread
1455 recordTrack = new RecordTrack(this, client, streamType, sampleRate,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001456 format, channelCount, frameCount);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001457
1458 // return to handle to client
1459 recordHandle = new RecordHandle(recordTrack);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001460 lStatus = NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001461
1462Exit:
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001463 if (status) {
1464 *status = lStatus;
1465 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001466 return recordHandle;
1467}
1468
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001469status_t AudioFlinger::startRecord(RecordTrack* recordTrack) {
1470 if (mAudioRecordThread != 0) {
1471 return mAudioRecordThread->start(recordTrack);
1472 }
1473 return NO_INIT;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001474}
1475
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001476void AudioFlinger::stopRecord(RecordTrack* recordTrack) {
1477 if (mAudioRecordThread != 0) {
1478 mAudioRecordThread->stop(recordTrack);
1479 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001480}
1481
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001482
1483// ----------------------------------------------------------------------------
1484
1485AudioFlinger::RecordTrack::RecordTrack(
1486 const sp<AudioFlinger>& audioFlinger,
1487 const sp<Client>& client,
1488 int streamType,
1489 uint32_t sampleRate,
1490 int format,
1491 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001492 int frameCount)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001493 : TrackBase(audioFlinger, client, streamType, sampleRate, format,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001494 channelCount, frameCount, 0),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001495 mOverflow(false)
1496{
1497}
1498
1499AudioFlinger::RecordTrack::~RecordTrack()
1500{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001501 mAudioFlinger->audioMixer()->deleteTrackName(mName);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001502}
1503
1504status_t AudioFlinger::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
1505{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001506 audio_track_cblk_t* cblk = this->cblk();
1507 uint32_t framesAvail;
1508 uint32_t framesReq = buffer->frameCount;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001509
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001510 // Check if last stepServer failed, try to step now
1511 if (mFlags & TrackBase::STEPSERVER_FAILED) {
1512 if (!step()) goto getNextBuffer_exit;
1513 LOGV("stepServer recovered");
1514 mFlags &= ~TrackBase::STEPSERVER_FAILED;
1515 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001516
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001517 framesAvail = cblk->framesAvailable_l();
1518
1519 if (LIKELY(framesAvail)) {
1520 uint32_t s = cblk->server;
1521 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
1522
1523 if (framesReq > framesAvail) {
1524 framesReq = framesAvail;
1525 }
1526 if (s + framesReq > bufferEnd) {
1527 framesReq = bufferEnd - s;
1528 }
1529
1530 buffer->raw = getBuffer(s, framesReq);
1531 if (buffer->raw == 0) goto getNextBuffer_exit;
1532
1533 buffer->frameCount = framesReq;
1534 return NO_ERROR;
1535 }
1536
1537getNextBuffer_exit:
1538 buffer->raw = 0;
1539 buffer->frameCount = 0;
1540 return NOT_ENOUGH_DATA;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001541}
1542
1543status_t AudioFlinger::RecordTrack::start()
1544{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001545 return mAudioFlinger->startRecord(this);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001546}
1547
1548void AudioFlinger::RecordTrack::stop()
1549{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001550 mAudioFlinger->stopRecord(this);
1551 TrackBase::reset();
1552 // Force overerrun condition to avoid false overrun callback until first data is
1553 // read from buffer
1554 mCblk->flowControlFlag = 1;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001555}
1556
1557// ----------------------------------------------------------------------------
1558
1559AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::RecordTrack>& recordTrack)
1560 : BnAudioRecord(),
1561 mRecordTrack(recordTrack)
1562{
1563}
1564
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001565AudioFlinger::RecordHandle::~RecordHandle() {
1566 stop();
1567}
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001568
1569status_t AudioFlinger::RecordHandle::start() {
1570 LOGV("RecordHandle::start()");
1571 return mRecordTrack->start();
1572}
1573
1574void AudioFlinger::RecordHandle::stop() {
1575 LOGV("RecordHandle::stop()");
1576 mRecordTrack->stop();
1577}
1578
1579sp<IMemory> AudioFlinger::RecordHandle::getCblk() const {
1580 return mRecordTrack->getCblk();
1581}
1582
1583status_t AudioFlinger::RecordHandle::onTransact(
1584 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1585{
1586 return BnAudioRecord::onTransact(code, data, reply, flags);
1587}
1588
1589// ----------------------------------------------------------------------------
1590
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001591AudioFlinger::AudioRecordThread::AudioRecordThread(AudioHardwareInterface* audioHardware) :
1592 mAudioHardware(audioHardware),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001593 mActive(false)
1594{
1595}
1596
1597AudioFlinger::AudioRecordThread::~AudioRecordThread()
1598{
1599}
1600
1601bool AudioFlinger::AudioRecordThread::threadLoop()
1602{
1603 LOGV("AudioRecordThread: start record loop");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001604 AudioBufferProvider::Buffer buffer;
1605 int inBufferSize = 0;
1606 int inFrameCount = 0;
1607 AudioStreamIn* input = 0;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001608
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001609 mActive = 0;
1610
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001611 // start recording
1612 while (!exitPending()) {
1613 if (!mActive) {
1614 mLock.lock();
1615 if (!mActive && !exitPending()) {
1616 LOGV("AudioRecordThread: loop stopping");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001617 if (input) {
1618 delete input;
1619 input = 0;
1620 }
1621 mRecordTrack.clear();
1622
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001623 mWaitWorkCV.wait(mLock);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001624
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001625 LOGV("AudioRecordThread: loop starting");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001626 if (mRecordTrack != 0) {
1627 input = mAudioHardware->openInputStream(mRecordTrack->format(),
1628 mRecordTrack->channelCount(),
1629 mRecordTrack->sampleRate(),
1630 &mStartStatus);
1631 if (input != 0) {
1632 inBufferSize = input->bufferSize();
1633 inFrameCount = inBufferSize/input->frameSize();
1634 }
1635 } else {
1636 mStartStatus = NO_INIT;
1637 }
1638 if (mStartStatus !=NO_ERROR) {
1639 LOGW("record start failed, status %d", mStartStatus);
1640 mActive = false;
1641 mRecordTrack.clear();
1642 }
1643 mWaitWorkCV.signal();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001644 }
1645 mLock.unlock();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001646 } else if (mRecordTrack != 0){
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001647
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001648 buffer.frameCount = inFrameCount;
1649 if (LIKELY(mRecordTrack->getNextBuffer(&buffer) == NO_ERROR)) {
1650 LOGV("AudioRecordThread read: %d frames", buffer.frameCount);
1651 if (input->read(buffer.raw, inBufferSize) < 0) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001652 LOGE("Error reading audio input");
1653 sleep(1);
1654 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001655 mRecordTrack->releaseBuffer(&buffer);
1656 mRecordTrack->overflow();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001657 }
1658
1659 // client isn't retrieving buffers fast enough
1660 else {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001661 if (!mRecordTrack->setOverflow())
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001662 LOGW("AudioRecordThread: buffer overflow");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001663 // Release the processor for a while before asking for a new buffer.
1664 // This will give the application more chance to read from the buffer and
1665 // clear the overflow.
1666 usleep(5000);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001667 }
1668 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001669 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001670
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001671
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001672 if (input) {
1673 delete input;
1674 }
1675 mRecordTrack.clear();
1676
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001677 return false;
1678}
1679
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001680status_t AudioFlinger::AudioRecordThread::start(RecordTrack* recordTrack)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001681{
1682 LOGV("AudioRecordThread::start");
1683 AutoMutex lock(&mLock);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001684 mActive = true;
1685 // If starting the active track, just reset mActive in case a stop
1686 // was pending and exit
1687 if (recordTrack == mRecordTrack.get()) return NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001688
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001689 if (mRecordTrack != 0) return -EBUSY;
1690
1691 mRecordTrack = recordTrack;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001692
1693 // signal thread to start
1694 LOGV("Signal record thread");
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001695 mWaitWorkCV.signal();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001696 mWaitWorkCV.wait(mLock);
1697 LOGV("Record started, status %d", mStartStatus);
1698 return mStartStatus;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001699}
1700
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001701void AudioFlinger::AudioRecordThread::stop(RecordTrack* recordTrack) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001702 LOGV("AudioRecordThread::stop");
1703 AutoMutex lock(&mLock);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001704 if (mActive && (recordTrack == mRecordTrack.get())) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001705 mActive = false;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001706 }
1707}
1708
1709void AudioFlinger::AudioRecordThread::exit()
1710{
1711 LOGV("AudioRecordThread::exit");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001712 {
1713 AutoMutex lock(&mLock);
1714 requestExit();
1715 mWaitWorkCV.signal();
1716 }
1717 requestExitAndWait();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001718}
1719
1720
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001721status_t AudioFlinger::onTransact(
1722 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1723{
1724 return BnAudioFlinger::onTransact(code, data, reply, flags);
1725}
1726
1727// ----------------------------------------------------------------------------
1728void AudioFlinger::instantiate() {
1729 defaultServiceManager()->addService(
1730 String16("media.audio_flinger"), new AudioFlinger());
1731}
1732
1733}; // namespace android