blob: 017a298c69274592216af1ee32ea56c40863facf [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;
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800186 mWaitWorkCV.broadcast();
The Android Open Source Project27629322009-01-09 17:51:23 -0800187}
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800188
The Android Open Source Project27629322009-01-09 17:51:23 -0800189void AudioFlinger::doSetOutput(AudioStreamOut* output)
190{
191 mSampleRate = output->sampleRate();
192 mChannelCount = output->channelCount();
193
194 // FIXME - Current mixer implementation only supports stereo output
195 if (mChannelCount == 1) {
196 LOGE("Invalid audio hardware channel count");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800197 }
The Android Open Source Project27629322009-01-09 17:51:23 -0800198 mFormat = output->format();
199 mFrameCount = getOutputFrameCount(output);
200 mAudioMixer = (output == mA2dpOutput ? mA2dpAudioMixer : mHardwareAudioMixer);
201 mOutput = output;
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800202 notifyOutputChange_l();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800203}
204
205size_t AudioFlinger::getOutputFrameCount(AudioStreamOut* output)
206{
207 return output->bufferSize() / output->channelCount() / sizeof(int16_t);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700208}
209
The Android Open Source Projecte41dd752009-01-22 00:13:42 -0800210#ifdef WITH_A2DP
211bool AudioFlinger::streamDisablesA2dp(int streamType)
212{
213 return (streamType == AudioTrack::SYSTEM ||
214 streamType == AudioTrack::RING ||
215 streamType == AudioTrack::ALARM ||
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800216 streamType == AudioTrack::VOICE_CALL ||
217 streamType == AudioTrack::BLUETOOTH_SCO ||
The Android Open Source Projecte41dd752009-01-22 00:13:42 -0800218 streamType == AudioTrack::NOTIFICATION);
219}
220
221void AudioFlinger::setA2dpEnabled(bool enable)
222{
223 if (enable) {
224 LOGD("set output to A2DP\n");
225 setOutput(mA2dpOutput);
226 } else {
227 LOGD("set output to hardware audio\n");
228 setOutput(mHardwareOutput);
229 }
230}
231#endif // WITH_A2DP
232
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700233status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args)
234{
235 const size_t SIZE = 256;
236 char buffer[SIZE];
237 String8 result;
238
239 result.append("Clients:\n");
240 for (size_t i = 0; i < mClients.size(); ++i) {
241 wp<Client> wClient = mClients.valueAt(i);
242 if (wClient != 0) {
243 sp<Client> client = wClient.promote();
244 if (client != 0) {
245 snprintf(buffer, SIZE, " pid: %d\n", client->pid());
246 result.append(buffer);
247 }
248 }
249 }
250 write(fd, result.string(), result.size());
251 return NO_ERROR;
252}
253
254status_t AudioFlinger::dumpTracks(int fd, const Vector<String16>& args)
255{
256 const size_t SIZE = 256;
257 char buffer[SIZE];
258 String8 result;
259
260 result.append("Tracks:\n");
261 result.append(" Name Clien Typ Fmt Chn Buf S M F SRate LeftV RighV Serv User\n");
262 for (size_t i = 0; i < mTracks.size(); ++i) {
263 wp<Track> wTrack = mTracks[i];
264 if (wTrack != 0) {
265 sp<Track> track = wTrack.promote();
266 if (track != 0) {
267 track->dump(buffer, SIZE);
268 result.append(buffer);
269 }
270 }
271 }
272
273 result.append("Active Tracks:\n");
274 result.append(" Name Clien Typ Fmt Chn Buf S M F SRate LeftV RighV Serv User\n");
275 for (size_t i = 0; i < mActiveTracks.size(); ++i) {
276 wp<Track> wTrack = mTracks[i];
277 if (wTrack != 0) {
278 sp<Track> track = wTrack.promote();
279 if (track != 0) {
280 track->dump(buffer, SIZE);
281 result.append(buffer);
282 }
283 }
284 }
285 write(fd, result.string(), result.size());
286 return NO_ERROR;
287}
288
289status_t AudioFlinger::dumpInternals(int fd, const Vector<String16>& args)
290{
291 const size_t SIZE = 256;
292 char buffer[SIZE];
293 String8 result;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800294
295 snprintf(buffer, SIZE, "AudioMixer tracks: %08x\n", audioMixer()->trackNames());
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700296 result.append(buffer);
297 snprintf(buffer, SIZE, "last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime));
298 result.append(buffer);
299 snprintf(buffer, SIZE, "total writes: %d\n", mNumWrites);
300 result.append(buffer);
301 snprintf(buffer, SIZE, "delayed writes: %d\n", mNumDelayedWrites);
302 result.append(buffer);
303 snprintf(buffer, SIZE, "blocked in write: %d\n", mInWrite);
304 result.append(buffer);
305 snprintf(buffer, SIZE, "standby: %d\n", mStandby);
306 result.append(buffer);
307 snprintf(buffer, SIZE, "Hardware status: %d\n", mHardwareStatus);
308 result.append(buffer);
309 write(fd, result.string(), result.size());
310 return NO_ERROR;
311}
312
313status_t AudioFlinger::dumpPermissionDenial(int fd, const Vector<String16>& args)
314{
315 const size_t SIZE = 256;
316 char buffer[SIZE];
317 String8 result;
318 snprintf(buffer, SIZE, "Permission Denial: "
319 "can't dump AudioFlinger from pid=%d, uid=%d\n",
320 IPCThreadState::self()->getCallingPid(),
321 IPCThreadState::self()->getCallingUid());
322 result.append(buffer);
323 write(fd, result.string(), result.size());
324 return NO_ERROR;
325}
326
327status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
328{
329 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
330 dumpPermissionDenial(fd, args);
331 } else {
332 AutoMutex lock(&mLock);
333
334 dumpClients(fd, args);
335 dumpTracks(fd, args);
336 dumpInternals(fd, args);
337 if (mAudioHardware) {
338 mAudioHardware->dumpState(fd, args);
339 }
340 }
341 return NO_ERROR;
342}
343
344// Thread virtuals
345bool AudioFlinger::threadLoop()
346{
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700347 unsigned long sleepTime = kBufferRecoveryInUsecs;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700348 int16_t* curBuf = mMixBuffer;
349 Vector< sp<Track> > tracksToRemove;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800350 size_t enabledTracks = 0;
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800351 nsecs_t standbyTime = systemTime();
352 nsecs_t outputSwitchStandbyTime = 0;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700353
354 do {
355 enabledTracks = 0;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800356 { // scope for the mLock
357
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700358 Mutex::Autolock _l(mLock);
359 const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
360
361 // put audio hardware into standby after short delay
362 if UNLIKELY(!activeTracks.size() && systemTime() > standbyTime) {
363 // wait until we have something to do...
364 LOGV("Audio hardware entering standby\n");
365 mHardwareStatus = AUDIO_HW_STANDBY;
366 if (!mStandby) {
The Android Open Source Project27629322009-01-09 17:51:23 -0800367 mOutput->standby();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700368 mStandby = true;
369 }
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800370 if (outputSwitchStandbyTime) {
371 AudioStreamOut *output = (mOutput == mHardwareOutput) ? mA2dpOutput : mHardwareOutput;
372 output->standby();
373 outputSwitchStandbyTime = 0;
374 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700375 mHardwareStatus = AUDIO_HW_IDLE;
376 // we're about to wait, flush the binder command buffer
377 IPCThreadState::self()->flushCommands();
378 mWaitWorkCV.wait(mLock);
379 LOGV("Audio hardware exiting standby\n");
380 standbyTime = systemTime() + kStandbyTimeInNsecs;
381 continue;
382 }
383
The Android Open Source Project27629322009-01-09 17:51:23 -0800384 // check for change in output
385 if (mRequestedOutput != mOutput) {
386
387 // put current output into standby mode
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800388 if (mOutput) {
389 outputSwitchStandbyTime = systemTime() + milliseconds(mOutput->latency());
390 }
The Android Open Source Project27629322009-01-09 17:51:23 -0800391
392 // change output
393 doSetOutput(mRequestedOutput);
394 }
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800395 if (outputSwitchStandbyTime && systemTime() > outputSwitchStandbyTime) {
396 AudioStreamOut *output = (mOutput == mHardwareOutput) ? mA2dpOutput : mHardwareOutput;
397 output->standby();
398 outputSwitchStandbyTime = 0;
399 }
The Android Open Source Project27629322009-01-09 17:51:23 -0800400
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700401 // find out which tracks need to be processed
402 size_t count = activeTracks.size();
403 for (size_t i=0 ; i<count ; i++) {
404 sp<Track> t = activeTracks[i].promote();
405 if (t == 0) continue;
406
407 Track* const track = t.get();
408 audio_track_cblk_t* cblk = track->cblk();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700409
410 // The first time a track is added we wait
411 // for all its buffers to be filled before processing it
The Android Open Source Project27629322009-01-09 17:51:23 -0800412 mAudioMixer->setActiveTrack(track->name());
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800413 if (cblk->framesReady() && (track->isReady() || track->isStopped()) &&
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700414 !track->isPaused())
415 {
416 //LOGD("u=%08x, s=%08x [OK]", u, s);
417
418 // compute volume for this track
419 int16_t left, right;
420 if (track->isMuted() || mMasterMute || track->isPausing()) {
421 left = right = 0;
422 if (track->isPausing()) {
423 LOGV("paused(%d)", track->name());
424 track->setPaused();
425 }
426 } else {
427 float typeVolume = mStreamTypes[track->type()].volume;
428 float v = mMasterVolume * typeVolume;
429 float v_clamped = v * cblk->volume[0];
430 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
431 left = int16_t(v_clamped);
432 v_clamped = v * cblk->volume[1];
433 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
434 right = int16_t(v_clamped);
435 }
436
437 // XXX: these things DON'T need to be done each time
The Android Open Source Project27629322009-01-09 17:51:23 -0800438 mAudioMixer->setBufferProvider(track);
439 mAudioMixer->enable(AudioMixer::MIXING);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700440
441 int param;
442 if ( track->mFillingUpStatus == Track::FS_FILLED) {
443 // no ramp for the first volume setting
444 track->mFillingUpStatus = Track::FS_ACTIVE;
445 if (track->mState == TrackBase::RESUMING) {
446 track->mState = TrackBase::ACTIVE;
447 param = AudioMixer::RAMP_VOLUME;
448 } else {
449 param = AudioMixer::VOLUME;
450 }
451 } else {
452 param = AudioMixer::RAMP_VOLUME;
453 }
The Android Open Source Project27629322009-01-09 17:51:23 -0800454 mAudioMixer->setParameter(param, AudioMixer::VOLUME0, left);
455 mAudioMixer->setParameter(param, AudioMixer::VOLUME1, right);
456 mAudioMixer->setParameter(
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700457 AudioMixer::TRACK,
458 AudioMixer::FORMAT, track->format());
The Android Open Source Project27629322009-01-09 17:51:23 -0800459 mAudioMixer->setParameter(
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700460 AudioMixer::TRACK,
461 AudioMixer::CHANNEL_COUNT, track->channelCount());
The Android Open Source Project27629322009-01-09 17:51:23 -0800462 mAudioMixer->setParameter(
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700463 AudioMixer::RESAMPLE,
464 AudioMixer::SAMPLE_RATE,
465 int(cblk->sampleRate));
466
467 // reset retry count
468 track->mRetryCount = kMaxTrackRetries;
469 enabledTracks++;
470 } else {
471 //LOGD("u=%08x, s=%08x [NOT READY]", u, s);
472 if (track->isStopped()) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800473 track->reset();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700474 }
475 if (track->isTerminated() || track->isStopped() || track->isPaused()) {
476 // We have consumed all the buffers of this track.
477 // Remove it from the list of active tracks.
478 LOGV("remove(%d) from active list", track->name());
479 tracksToRemove.add(track);
480 } else {
481 // No buffers for this track. Give it a few chances to
482 // fill a buffer, then remove it from active list.
483 if (--(track->mRetryCount) <= 0) {
484 LOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
485 tracksToRemove.add(track);
486 }
487 }
488 // LOGV("disable(%d)", track->name());
The Android Open Source Project27629322009-01-09 17:51:23 -0800489 mAudioMixer->disable(AudioMixer::MIXING);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700490 }
491 }
492
493 // remove all the tracks that need to be...
494 count = tracksToRemove.size();
495 if (UNLIKELY(count)) {
496 for (size_t i=0 ; i<count ; i++) {
497 const sp<Track>& track = tracksToRemove[i];
The Android Open Source Projecte41dd752009-01-22 00:13:42 -0800498 removeActiveTrack(track);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700499 if (track->isTerminated()) {
500 mTracks.remove(track);
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800501 deleteTrackName(track->mName);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700502 }
503 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800504 }
505 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700506 if (LIKELY(enabledTracks)) {
507 // mix buffers...
The Android Open Source Project27629322009-01-09 17:51:23 -0800508 mAudioMixer->process(curBuf);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700509
510 // output audio to hardware
511 mLastWriteTime = systemTime();
512 mInWrite = true;
The Android Open Source Project27629322009-01-09 17:51:23 -0800513 size_t mixBufferSize = mFrameCount*mChannelCount*sizeof(int16_t);
514 mOutput->write(curBuf, mixBufferSize);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700515 mNumWrites++;
516 mInWrite = false;
517 mStandby = false;
518 nsecs_t temp = systemTime();
519 standbyTime = temp + kStandbyTimeInNsecs;
520 nsecs_t delta = temp - mLastWriteTime;
The Android Open Source Project27629322009-01-09 17:51:23 -0800521 nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 2;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700522 if (delta > maxPeriod) {
523 LOGW("write blocked for %llu msecs", ns2ms(delta));
524 mNumDelayedWrites++;
525 }
526 sleepTime = kBufferRecoveryInUsecs;
527 } else {
528 // There was nothing to mix this round, which means all
529 // active tracks were late. Sleep a little bit to give
530 // them another chance. If we're too late, the audio
531 // hardware will zero-fill for us.
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800532// LOGV("no buffers - usleep(%lu)", sleepTime);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700533 usleep(sleepTime);
534 if (sleepTime < kMaxBufferRecoveryInUsecs) {
535 sleepTime += kBufferRecoveryInUsecs;
536 }
537 }
538
539 // finally let go of all our tracks, without the lock held
540 // since we can't guarantee the destructors won't acquire that
541 // same lock.
542 tracksToRemove.clear();
543 } while (true);
544
545 return false;
546}
547
548status_t AudioFlinger::readyToRun()
549{
550 if (mSampleRate == 0) {
551 LOGE("No working audio driver found.");
552 return NO_INIT;
553 }
554 LOGI("AudioFlinger's main thread ready to run.");
555 return NO_ERROR;
556}
557
558void AudioFlinger::onFirstRef()
559{
560 run("AudioFlinger", ANDROID_PRIORITY_URGENT_AUDIO);
561}
562
563// IAudioFlinger interface
564sp<IAudioTrack> AudioFlinger::createTrack(
565 pid_t pid,
566 int streamType,
567 uint32_t sampleRate,
568 int format,
569 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800570 int frameCount,
571 uint32_t flags,
572 const sp<IMemory>& sharedBuffer,
573 status_t *status)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700574{
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700575 sp<Track> track;
576 sp<TrackHandle> trackHandle;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700577 sp<Client> client;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800578 wp<Client> wclient;
579 status_t lStatus;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700580
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800581 if (streamType >= AudioTrack::NUM_STREAM_TYPES) {
582 LOGE("invalid stream type");
583 lStatus = BAD_VALUE;
584 goto Exit;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700585 }
586
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800587 // Resampler implementation limits input sampling rate to 2 x output sampling rate.
588 if (sampleRate > MAX_SAMPLE_RATE || sampleRate > mSampleRate*2) {
589 LOGE("Sample rate out of range: %d", sampleRate);
590 lStatus = BAD_VALUE;
591 goto Exit;
592 }
593
594 {
595 Mutex::Autolock _l(mLock);
596
597 if (mSampleRate == 0) {
598 LOGE("Audio driver not initialized.");
599 lStatus = NO_INIT;
600 goto Exit;
601 }
602
603 wclient = mClients.valueFor(pid);
604
605 if (wclient != NULL) {
606 client = wclient.promote();
607 } else {
608 client = new Client(this, pid);
609 mClients.add(pid, client);
610 }
611
612 track = new Track(this, client, streamType, sampleRate, format,
613 channelCount, frameCount, sharedBuffer);
614 mTracks.add(track);
615 trackHandle = new TrackHandle(track);
616
617 lStatus = NO_ERROR;
618 }
619
620Exit:
621 if(status) {
622 *status = lStatus;
623 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700624 return trackHandle;
625}
626
627uint32_t AudioFlinger::sampleRate() const
628{
629 return mSampleRate;
630}
631
632int AudioFlinger::channelCount() const
633{
634 return mChannelCount;
635}
636
637int AudioFlinger::format() const
638{
639 return mFormat;
640}
641
642size_t AudioFlinger::frameCount() const
643{
644 return mFrameCount;
645}
646
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800647uint32_t AudioFlinger::latency() const
648{
649 if (mOutput) {
650 return mOutput->latency();
651 }
652 else {
653 return 0;
654 }
655}
656
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700657status_t AudioFlinger::setMasterVolume(float value)
658{
659 // check calling permissions
660 if (!settingsAllowed()) {
661 return PERMISSION_DENIED;
662 }
663
664 // when hw supports master volume, don't scale in sw mixer
665 AutoMutex lock(mHardwareLock);
666 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
667 if (mAudioHardware->setMasterVolume(value) == NO_ERROR) {
668 mMasterVolume = 1.0f;
669 }
670 else {
671 mMasterVolume = value;
672 }
673 mHardwareStatus = AUDIO_HW_IDLE;
674 return NO_ERROR;
675}
676
677status_t AudioFlinger::setRouting(int mode, uint32_t routes, uint32_t mask)
678{
The Android Open Source Project27629322009-01-09 17:51:23 -0800679 status_t err = NO_ERROR;
680
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700681 // check calling permissions
682 if (!settingsAllowed()) {
683 return PERMISSION_DENIED;
684 }
685 if ((mode < AudioSystem::MODE_CURRENT) || (mode >= AudioSystem::NUM_MODES)) {
686 LOGW("Illegal value: setRouting(%d, %u, %u)", mode, routes, mask);
687 return BAD_VALUE;
688 }
689
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800690#ifdef WITH_A2DP
691 LOGD("setRouting %d %d %d\n", mode, routes, mask);
692 if (mode == AudioSystem::MODE_NORMAL &&
693 (mask & AudioSystem::ROUTE_BLUETOOTH_A2DP)) {
The Android Open Source Projecte41dd752009-01-22 00:13:42 -0800694 AutoMutex lock(&mLock);
695
696 bool enableA2dp = false;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800697 if (routes & AudioSystem::ROUTE_BLUETOOTH_A2DP) {
The Android Open Source Projecte41dd752009-01-22 00:13:42 -0800698 if (mA2dpDisableCount > 0)
699 mA2dpSuppressed = true;
700 else
701 enableA2dp = true;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800702 }
The Android Open Source Projecte41dd752009-01-22 00:13:42 -0800703 setA2dpEnabled(enableA2dp);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800704 LOGD("setOutput done\n");
705 }
706#endif
707
The Android Open Source Project27629322009-01-09 17:51:23 -0800708 // do nothing if only A2DP routing is affected
709 mask &= ~AudioSystem::ROUTE_BLUETOOTH_A2DP;
710 if (mask) {
711 AutoMutex lock(mHardwareLock);
712 mHardwareStatus = AUDIO_HW_GET_ROUTING;
713 uint32_t r;
714 err = mAudioHardware->getRouting(mode, &r);
715 if (err == NO_ERROR) {
716 r = (r & ~mask) | (routes & mask);
717 mHardwareStatus = AUDIO_HW_SET_ROUTING;
718 err = mAudioHardware->setRouting(mode, r);
719 }
720 mHardwareStatus = AUDIO_HW_IDLE;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700721 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700722 return err;
723}
724
725uint32_t AudioFlinger::getRouting(int mode) const
726{
727 uint32_t routes = 0;
728 if ((mode >= AudioSystem::MODE_CURRENT) && (mode < AudioSystem::NUM_MODES)) {
729 mHardwareStatus = AUDIO_HW_GET_ROUTING;
730 mAudioHardware->getRouting(mode, &routes);
731 mHardwareStatus = AUDIO_HW_IDLE;
732 } else {
733 LOGW("Illegal value: getRouting(%d)", mode);
734 }
735 return routes;
736}
737
738status_t AudioFlinger::setMode(int mode)
739{
740 // check calling permissions
741 if (!settingsAllowed()) {
742 return PERMISSION_DENIED;
743 }
744 if ((mode < 0) || (mode >= AudioSystem::NUM_MODES)) {
745 LOGW("Illegal value: setMode(%d)", mode);
746 return BAD_VALUE;
747 }
748
749 AutoMutex lock(mHardwareLock);
750 mHardwareStatus = AUDIO_HW_SET_MODE;
751 status_t ret = mAudioHardware->setMode(mode);
752 mHardwareStatus = AUDIO_HW_IDLE;
753 return ret;
754}
755
756int AudioFlinger::getMode() const
757{
758 int mode = AudioSystem::MODE_INVALID;
759 mHardwareStatus = AUDIO_HW_SET_MODE;
760 mAudioHardware->getMode(&mode);
761 mHardwareStatus = AUDIO_HW_IDLE;
762 return mode;
763}
764
765status_t AudioFlinger::setMicMute(bool state)
766{
767 // check calling permissions
768 if (!settingsAllowed()) {
769 return PERMISSION_DENIED;
770 }
771
772 AutoMutex lock(mHardwareLock);
773 mHardwareStatus = AUDIO_HW_SET_MIC_MUTE;
774 status_t ret = mAudioHardware->setMicMute(state);
775 mHardwareStatus = AUDIO_HW_IDLE;
776 return ret;
777}
778
779bool AudioFlinger::getMicMute() const
780{
781 bool state = AudioSystem::MODE_INVALID;
782 mHardwareStatus = AUDIO_HW_GET_MIC_MUTE;
783 mAudioHardware->getMicMute(&state);
784 mHardwareStatus = AUDIO_HW_IDLE;
785 return state;
786}
787
788status_t AudioFlinger::setMasterMute(bool muted)
789{
790 // check calling permissions
791 if (!settingsAllowed()) {
792 return PERMISSION_DENIED;
793 }
794
795 mMasterMute = muted;
796 return NO_ERROR;
797}
798
799float AudioFlinger::masterVolume() const
800{
801 return mMasterVolume;
802}
803
804bool AudioFlinger::masterMute() const
805{
806 return mMasterMute;
807}
808
809status_t AudioFlinger::setStreamVolume(int stream, float value)
810{
811 // check calling permissions
812 if (!settingsAllowed()) {
813 return PERMISSION_DENIED;
814 }
815
816 if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) {
817 return BAD_VALUE;
818 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800819
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700820 mStreamTypes[stream].volume = value;
821 status_t ret = NO_ERROR;
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800822 if (stream == AudioTrack::VOICE_CALL ||
823 stream == AudioTrack::BLUETOOTH_SCO) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700824 AutoMutex lock(mHardwareLock);
825 mHardwareStatus = AUDIO_SET_VOICE_VOLUME;
826 ret = mAudioHardware->setVoiceVolume(value);
827 mHardwareStatus = AUDIO_HW_IDLE;
828 }
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800829
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700830 return ret;
831}
832
833status_t AudioFlinger::setStreamMute(int stream, bool muted)
834{
835 // check calling permissions
836 if (!settingsAllowed()) {
837 return PERMISSION_DENIED;
838 }
839
840 if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) {
841 return BAD_VALUE;
842 }
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800843#ifdef WITH_A2DP
844 if (stream == AudioTrack::MUSIC)
845 {
846 AutoMutex lock(&mLock);
847 if (mA2dpDisableCount > 0)
848 mMusicMuteSaved = muted;
849 else
850 mStreamTypes[stream].mute = muted;
851 } else {
852 mStreamTypes[stream].mute = muted;
853 }
854#else
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700855 mStreamTypes[stream].mute = muted;
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800856#endif
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700857 return NO_ERROR;
858}
859
860float AudioFlinger::streamVolume(int stream) const
861{
862 if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) {
863 return 0.0f;
864 }
865 return mStreamTypes[stream].volume;
866}
867
868bool AudioFlinger::streamMute(int stream) const
869{
870 if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) {
871 return true;
872 }
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800873#ifdef WITH_A2DP
874 if (stream == AudioTrack::MUSIC && mA2dpDisableCount > 0)
875 {
876 return mMusicMuteSaved;
877 }
878#endif
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700879 return mStreamTypes[stream].mute;
880}
881
882bool AudioFlinger::isMusicActive() const
883{
884 size_t count = mActiveTracks.size();
885 for (size_t i = 0 ; i < count ; ++i) {
886 sp<Track> t = mActiveTracks[i].promote();
887 if (t == 0) continue;
888 Track* const track = t.get();
889 if (t->mStreamType == AudioTrack::MUSIC)
890 return true;
891 }
892 return false;
893}
894
895status_t AudioFlinger::setParameter(const char* key, const char* value)
896{
The Android Open Source Project8a7a6752009-01-15 16:12:10 -0800897 status_t result, result2;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700898 AutoMutex lock(mHardwareLock);
899 mHardwareStatus = AUDIO_SET_PARAMETER;
900 result = mAudioHardware->setParameter(key, value);
The Android Open Source Project8a7a6752009-01-15 16:12:10 -0800901 if (mA2dpAudioInterface) {
902 result2 = mA2dpAudioInterface->setParameter(key, value);
903 if (result2)
904 result = result2;
905 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700906 mHardwareStatus = AUDIO_HW_IDLE;
907 return result;
908}
909
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800910
911void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
912{
913 Mutex::Autolock _l(mLock);
914
915 sp<IBinder> binder = client->asBinder();
916 if (mNotificationClients.indexOf(binder) < 0) {
917 LOGV("Adding notification client %p", binder.get());
918 binder->linkToDeath(this);
919 mNotificationClients.add(binder);
920 }
921}
922
923
924size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
925{
926 return mAudioHardware->getInputBufferSize(sampleRate, format, channelCount);
927}
928
929void AudioFlinger::wakeUp()
930{
931 mWaitWorkCV.broadcast();
932}
933
934void AudioFlinger::binderDied(const wp<IBinder>& who) {
935 Mutex::Autolock _l(mLock);
936
937 IBinder *binder = who.unsafe_get();
938
939 if (binder != NULL) {
940 int index = mNotificationClients.indexOf(binder);
941 if (index >= 0) {
942 LOGV("Removing notification client %p", binder);
943 mNotificationClients.removeAt(index);
944 }
945 }
946}
947
948// must be called with mLock held
949void AudioFlinger::notifyOutputChange_l()
950{
951 size_t size = mNotificationClients.size();
952 uint32_t latency = mOutput->latency();
953 for (size_t i = 0; i < size; i++) {
954 sp<IBinder> binder = mNotificationClients.itemAt(i).promote();
955 if (binder != NULL) {
956 LOGV("Notifying output change to client %p", binder.get());
957 sp<IAudioFlingerClient> client = interface_cast<IAudioFlingerClient> (binder);
958 client->audioOutputChanged(mFrameCount, mSampleRate, latency);
959 }
960 }
961}
962
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700963void AudioFlinger::removeClient(pid_t pid)
964{
965 Mutex::Autolock _l(mLock);
966 mClients.removeItem(pid);
967}
968
969status_t AudioFlinger::addTrack(const sp<Track>& track)
970{
971 Mutex::Autolock _l(mLock);
972
973 // here the track could be either new, or restarted
974 // in both cases "unstop" the track
975 if (track->isPaused()) {
976 track->mState = TrackBase::RESUMING;
977 LOGV("PAUSED => RESUMING (%d)", track->name());
978 } else {
979 track->mState = TrackBase::ACTIVE;
980 LOGV("? => ACTIVE (%d)", track->name());
981 }
982 // set retry count for buffer fill
983 track->mRetryCount = kMaxTrackStartupRetries;
984 LOGV("mWaitWorkCV.broadcast");
985 mWaitWorkCV.broadcast();
986
987 if (mActiveTracks.indexOf(track) < 0) {
988 // the track is newly added, make sure it fills up all its
989 // buffers before playing. This is to ensure the client will
990 // effectively get the latency it requested.
991 track->mFillingUpStatus = Track::FS_FILLING;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800992 track->mResetDone = false;
The Android Open Source Projecte41dd752009-01-22 00:13:42 -0800993 addActiveTrack(track);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700994 return NO_ERROR;
995 }
996 return ALREADY_EXISTS;
997}
998
999void AudioFlinger::removeTrack(wp<Track> track, int name)
1000{
1001 Mutex::Autolock _l(mLock);
1002 sp<Track> t = track.promote();
1003 if (t!=NULL && (t->mState <= TrackBase::STOPPED)) {
1004 remove_track_l(track, name);
1005 }
1006}
1007
1008void AudioFlinger::remove_track_l(wp<Track> track, int name)
1009{
1010 sp<Track> t = track.promote();
1011 if (t!=NULL) {
1012 t->reset();
1013 }
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -08001014 deleteTrackName(name);
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001015 removeActiveTrack(track);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001016 mWaitWorkCV.broadcast();
1017}
1018
1019void AudioFlinger::destroyTrack(const sp<Track>& track)
1020{
1021 // NOTE: We're acquiring a strong reference on the track before
1022 // acquiring the lock, this is to make sure removing it from
1023 // mTracks won't cause the destructor to be called while the lock is
1024 // held (note that technically, 'track' could be a reference to an item
1025 // in mTracks, which is why we need to do this).
1026 sp<Track> keep(track);
1027 Mutex::Autolock _l(mLock);
1028 track->mState = TrackBase::TERMINATED;
1029 if (mActiveTracks.indexOf(track) < 0) {
1030 LOGV("remove track (%d) and delete from mixer", track->name());
1031 mTracks.remove(track);
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -08001032 deleteTrackName(keep->name());
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001033 }
1034}
1035
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001036void AudioFlinger::addActiveTrack(const wp<Track>& t)
1037{
1038 mActiveTracks.add(t);
1039
1040#ifdef WITH_A2DP
1041 // disable A2DP for certain stream types
1042 sp<Track> track = t.promote();
1043 if (streamDisablesA2dp(track->type())) {
1044 if (mA2dpDisableCount++ == 0 && isA2dpEnabled()) {
1045 setA2dpEnabled(false);
1046 mA2dpSuppressed = true;
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -08001047 mMusicMuteSaved = mStreamTypes[AudioTrack::MUSIC].mute;
1048 mStreamTypes[AudioTrack::MUSIC].mute = true;
1049 LOGV("mA2dpSuppressed = true, track %d\n", track->name());
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001050 }
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -08001051 LOGV("mA2dpDisableCount incremented to %d, track %d\n", mA2dpDisableCount, track->name());
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001052 }
1053#endif
1054}
1055
1056void AudioFlinger::removeActiveTrack(const wp<Track>& t)
1057{
1058 mActiveTracks.remove(t);
1059#ifdef WITH_A2DP
1060 // disable A2DP for certain stream types
1061 sp<Track> track = t.promote();
1062 if (streamDisablesA2dp(track->type())) {
1063 if (mA2dpDisableCount > 0) {
1064 mA2dpDisableCount--;
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -08001065 LOGV("mA2dpDisableCount decremented to %d, track %d\n", mA2dpDisableCount, track->name());
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001066 if (mA2dpDisableCount == 0 && mA2dpSuppressed) {
1067 setA2dpEnabled(true);
1068 mA2dpSuppressed = false;
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -08001069 mStreamTypes[AudioTrack::MUSIC].mute = mMusicMuteSaved;
1070 LOGV("mA2dpSuppressed = false, track %d\n", track->name());
1071 }
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001072 } else
1073 LOGE("mA2dpDisableCount is already zero");
1074 }
1075#endif
1076}
1077
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -08001078int AudioFlinger::getTrackName()
1079{
1080 // Both mixers must have the same set of track used to avoid mismatches when
1081 // switching from A2DP output to hardware output
1082 int a2DpName;
1083 int hwName;
1084#ifdef WITH_A2DP
1085 a2DpName = mA2dpAudioMixer->getTrackName();
1086#endif
1087 hwName = mHardwareAudioMixer->getTrackName();
1088
1089 LOGW_IF((a2DpName != hwName), "getTrackName track name mismatch! A2DP %d, HW %d", a2DpName, hwName);
1090
1091 return hwName;
1092}
1093
1094void AudioFlinger::deleteTrackName(int name)
1095{
1096 // Both mixers must have the same set of track used to avoid mismatches when
1097 // switching from A2DP output to hardware output
1098 mHardwareAudioMixer->deleteTrackName(name);
1099#ifdef WITH_A2DP
1100 mA2dpAudioMixer->deleteTrackName(name);
1101#endif
1102}
1103
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001104// ----------------------------------------------------------------------------
1105
1106AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
1107 : RefBase(),
1108 mAudioFlinger(audioFlinger),
1109 mMemoryDealer(new MemoryDealer(1024*1024)),
1110 mPid(pid)
1111{
1112 // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
1113}
1114
1115AudioFlinger::Client::~Client()
1116{
1117 mAudioFlinger->removeClient(mPid);
1118}
1119
1120const sp<MemoryDealer>& AudioFlinger::Client::heap() const
1121{
1122 return mMemoryDealer;
1123}
1124
1125// ----------------------------------------------------------------------------
1126
1127AudioFlinger::TrackBase::TrackBase(
1128 const sp<AudioFlinger>& audioFlinger,
1129 const sp<Client>& client,
1130 int streamType,
1131 uint32_t sampleRate,
1132 int format,
1133 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001134 int frameCount,
1135 const sp<IMemory>& sharedBuffer)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001136 : RefBase(),
1137 mAudioFlinger(audioFlinger),
1138 mClient(client),
1139 mStreamType(streamType),
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001140 mFrameCount(0),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001141 mState(IDLE),
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001142 mClientTid(-1),
1143 mFormat(format),
1144 mFlags(0)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001145{
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -08001146 mName = audioFlinger->getTrackName();
1147 LOGV("TrackBase contructor name %d, calling thread %d", mName, IPCThreadState::self()->getCallingPid());
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001148 if (mName < 0) {
1149 LOGE("no more track names availlable");
1150 return;
1151 }
1152
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001153 LOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size());
1154
1155
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001156 // LOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001157 size_t size = sizeof(audio_track_cblk_t);
1158 size_t bufferSize = frameCount*channelCount*sizeof(int16_t);
1159 if (sharedBuffer == 0) {
1160 size += bufferSize;
1161 }
1162
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001163 mCblkMemory = client->heap()->allocate(size);
1164 if (mCblkMemory != 0) {
1165 mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer());
1166 if (mCblk) { // construct the shared structure in-place.
1167 new(mCblk) audio_track_cblk_t();
1168 // clear all buffers
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001169 mCblk->frameCount = frameCount;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001170 mCblk->sampleRate = sampleRate;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001171 mCblk->channels = channelCount;
1172 if (sharedBuffer == 0) {
1173 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
1174 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
1175 // Force underrun condition to avoid false underrun callback until first data is
1176 // written to buffer
1177 mCblk->flowControlFlag = 1;
1178 } else {
1179 mBuffer = sharedBuffer->pointer();
1180 }
1181 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001182 }
1183 } else {
1184 LOGE("not enough memory for AudioTrack size=%u", size);
1185 client->heap()->dump("AudioTrack");
1186 return;
1187 }
1188}
1189
1190AudioFlinger::TrackBase::~TrackBase()
1191{
1192 mCblk->~audio_track_cblk_t(); // destroy our shared-structure.
1193 mCblkMemory.clear(); // and free the shared memory
1194 mClient.clear();
1195}
1196
1197void AudioFlinger::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
1198{
1199 buffer->raw = 0;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001200 mFrameCount = buffer->frameCount;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001201 step();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001202 buffer->frameCount = 0;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001203}
1204
1205bool AudioFlinger::TrackBase::step() {
1206 bool result;
1207 audio_track_cblk_t* cblk = this->cblk();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001208
1209 result = cblk->stepServer(mFrameCount);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001210 if (!result) {
1211 LOGV("stepServer failed acquiring cblk mutex");
1212 mFlags |= STEPSERVER_FAILED;
1213 }
1214 return result;
1215}
1216
1217void AudioFlinger::TrackBase::reset() {
1218 audio_track_cblk_t* cblk = this->cblk();
1219
1220 cblk->user = 0;
1221 cblk->server = 0;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001222 cblk->userBase = 0;
1223 cblk->serverBase = 0;
1224 mFlags = 0;
1225 LOGV("TrackBase::reset");
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001226}
1227
1228sp<IMemory> AudioFlinger::TrackBase::getCblk() const
1229{
1230 return mCblkMemory;
1231}
1232
1233int AudioFlinger::TrackBase::sampleRate() const {
1234 return mCblk->sampleRate;
1235}
1236
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001237int AudioFlinger::TrackBase::channelCount() const {
1238 return mCblk->channels;
1239}
1240
1241void* AudioFlinger::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
1242 audio_track_cblk_t* cblk = this->cblk();
1243 int16_t *bufferStart = (int16_t *)mBuffer + (offset-cblk->serverBase)*cblk->channels;
1244 int16_t *bufferEnd = bufferStart + frames * cblk->channels;
1245
1246 // Check validity of returned pointer in case the track control block would have been corrupted.
1247 if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd) {
1248 LOGW("TrackBase::getBuffer buffer out of range:\n start: %p, end %p , mBuffer %p mBufferEnd %p\n \
1249 server %d, serverBase %d, user %d, userBase %d",
1250 bufferStart, bufferEnd, mBuffer, mBufferEnd,
1251 cblk->server, cblk->serverBase, cblk->user, cblk->userBase);
1252 return 0;
1253 }
1254
1255 return bufferStart;
1256}
1257
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001258// ----------------------------------------------------------------------------
1259
1260AudioFlinger::Track::Track(
1261 const sp<AudioFlinger>& audioFlinger,
1262 const sp<Client>& client,
1263 int streamType,
1264 uint32_t sampleRate,
1265 int format,
1266 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001267 int frameCount,
1268 const sp<IMemory>& sharedBuffer)
1269 : TrackBase(audioFlinger, client, streamType, sampleRate, format, channelCount, frameCount, sharedBuffer)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001270{
1271 mVolume[0] = 1.0f;
1272 mVolume[1] = 1.0f;
1273 mMute = false;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001274 mSharedBuffer = sharedBuffer;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001275}
1276
1277AudioFlinger::Track::~Track()
1278{
1279 wp<Track> weak(this); // never create a strong ref from the dtor
1280 mState = TERMINATED;
1281 mAudioFlinger->removeTrack(weak, mName);
1282}
1283
1284void AudioFlinger::Track::destroy()
1285{
1286 mAudioFlinger->destroyTrack(this);
1287}
1288
1289void AudioFlinger::Track::dump(char* buffer, size_t size)
1290{
1291 snprintf(buffer, size, " %5d %5d %3u %3u %3u %3u %1d %1d %1d %5u %5u %5u %04x %04x\n",
1292 mName - AudioMixer::TRACK0,
1293 mClient->pid(),
1294 mStreamType,
1295 mFormat,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001296 mCblk->channels,
1297 mFrameCount,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001298 mState,
1299 mMute,
1300 mFillingUpStatus,
1301 mCblk->sampleRate,
1302 mCblk->volume[0],
1303 mCblk->volume[1],
1304 mCblk->server,
1305 mCblk->user);
1306}
1307
1308status_t AudioFlinger::Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
1309{
1310 audio_track_cblk_t* cblk = this->cblk();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001311 uint32_t framesReady;
1312 uint32_t framesReq = buffer->frameCount;
1313
1314 // Check if last stepServer failed, try to step now
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001315 if (mFlags & TrackBase::STEPSERVER_FAILED) {
1316 if (!step()) goto getNextBuffer_exit;
1317 LOGV("stepServer recovered");
1318 mFlags &= ~TrackBase::STEPSERVER_FAILED;
1319 }
1320
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001321 framesReady = cblk->framesReady();
1322
1323 if (LIKELY(framesReady)) {
1324 uint32_t s = cblk->server;
1325 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
1326
1327 bufferEnd = (cblk->loopEnd < bufferEnd) ? cblk->loopEnd : bufferEnd;
1328 if (framesReq > framesReady) {
1329 framesReq = framesReady;
1330 }
1331 if (s + framesReq > bufferEnd) {
1332 framesReq = bufferEnd - s;
1333 }
1334
1335 buffer->raw = getBuffer(s, framesReq);
1336 if (buffer->raw == 0) goto getNextBuffer_exit;
1337
1338 buffer->frameCount = framesReq;
1339 return NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001340 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001341
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001342getNextBuffer_exit:
1343 buffer->raw = 0;
1344 buffer->frameCount = 0;
1345 return NOT_ENOUGH_DATA;
1346}
1347
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001348bool AudioFlinger::Track::isReady() const {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001349 if (mFillingUpStatus != FS_FILLING) return true;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001350
1351 if (mCblk->framesReady() >= mCblk->frameCount ||
1352 mCblk->forceReady) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001353 mFillingUpStatus = FS_FILLED;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001354 mCblk->forceReady = 0;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001355 return true;
1356 }
1357 return false;
1358}
1359
1360status_t AudioFlinger::Track::start()
1361{
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -08001362 LOGV("start(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001363 mAudioFlinger->addTrack(this);
1364 return NO_ERROR;
1365}
1366
1367void AudioFlinger::Track::stop()
1368{
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -08001369 LOGV("stop(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001370 Mutex::Autolock _l(mAudioFlinger->mLock);
1371 if (mState > STOPPED) {
1372 mState = STOPPED;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001373 // If the track is not active (PAUSED and buffers full), flush buffers
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001374 if (mAudioFlinger->mActiveTracks.indexOf(this) < 0) {
1375 reset();
1376 }
1377 LOGV("(> STOPPED) => STOPPED (%d)", mName);
1378 }
1379}
1380
1381void AudioFlinger::Track::pause()
1382{
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -08001383 LOGV("pause(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001384 Mutex::Autolock _l(mAudioFlinger->mLock);
1385 if (mState == ACTIVE || mState == RESUMING) {
1386 mState = PAUSING;
1387 LOGV("ACTIVE/RESUMING => PAUSING (%d)", mName);
1388 }
1389}
1390
1391void AudioFlinger::Track::flush()
1392{
1393 LOGV("flush(%d)", mName);
1394 Mutex::Autolock _l(mAudioFlinger->mLock);
1395 if (mState != STOPPED && mState != PAUSED && mState != PAUSING) {
1396 return;
1397 }
1398 // No point remaining in PAUSED state after a flush => go to
1399 // STOPPED state
1400 mState = STOPPED;
1401
1402 // NOTE: reset() will reset cblk->user and cblk->server with
1403 // the risk that at the same time, the AudioMixer is trying to read
1404 // data. In this case, getNextBuffer() would return a NULL pointer
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001405 // as audio buffer => the AudioMixer code MUST always test that pointer
1406 // returned by getNextBuffer() is not NULL!
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001407 reset();
1408}
1409
1410void AudioFlinger::Track::reset()
1411{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001412 // Do not reset twice to avoid discarding data written just after a flush and before
1413 // the audioflinger thread detects the track is stopped.
1414 if (!mResetDone) {
1415 TrackBase::reset();
1416 // Force underrun condition to avoid false underrun callback until first data is
1417 // written to buffer
1418 mCblk->flowControlFlag = 1;
1419 mCblk->forceReady = 0;
1420 mFillingUpStatus = FS_FILLING;
1421 mResetDone = true;
1422 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001423}
1424
1425void AudioFlinger::Track::mute(bool muted)
1426{
1427 mMute = muted;
1428}
1429
1430void AudioFlinger::Track::setVolume(float left, float right)
1431{
1432 mVolume[0] = left;
1433 mVolume[1] = right;
1434}
1435
1436// ----------------------------------------------------------------------------
1437
1438AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::Track>& track)
1439 : BnAudioTrack(),
1440 mTrack(track)
1441{
1442}
1443
1444AudioFlinger::TrackHandle::~TrackHandle() {
1445 // just stop the track on deletion, associated resources
1446 // will be freed from the main thread once all pending buffers have
1447 // been played. Unless it's not in the active track list, in which
1448 // case we free everything now...
1449 mTrack->destroy();
1450}
1451
1452status_t AudioFlinger::TrackHandle::start() {
1453 return mTrack->start();
1454}
1455
1456void AudioFlinger::TrackHandle::stop() {
1457 mTrack->stop();
1458}
1459
1460void AudioFlinger::TrackHandle::flush() {
1461 mTrack->flush();
1462}
1463
1464void AudioFlinger::TrackHandle::mute(bool e) {
1465 mTrack->mute(e);
1466}
1467
1468void AudioFlinger::TrackHandle::pause() {
1469 mTrack->pause();
1470}
1471
1472void AudioFlinger::TrackHandle::setVolume(float left, float right) {
1473 mTrack->setVolume(left, right);
1474}
1475
1476sp<IMemory> AudioFlinger::TrackHandle::getCblk() const {
1477 return mTrack->getCblk();
1478}
1479
1480status_t AudioFlinger::TrackHandle::onTransact(
1481 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1482{
1483 return BnAudioTrack::onTransact(code, data, reply, flags);
1484}
1485
1486// ----------------------------------------------------------------------------
1487
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001488sp<IAudioRecord> AudioFlinger::openRecord(
1489 pid_t pid,
1490 int streamType,
1491 uint32_t sampleRate,
1492 int format,
1493 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001494 int frameCount,
1495 uint32_t flags,
1496 status_t *status)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001497{
1498 sp<AudioRecordThread> thread;
1499 sp<RecordTrack> recordTrack;
1500 sp<RecordHandle> recordHandle;
1501 sp<Client> client;
1502 wp<Client> wclient;
1503 AudioStreamIn* input = 0;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001504 int inFrameCount;
1505 size_t inputBufferSize;
1506 status_t lStatus;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001507
1508 // check calling permissions
1509 if (!recordingAllowed()) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001510 lStatus = PERMISSION_DENIED;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001511 goto Exit;
1512 }
1513
1514 if (uint32_t(streamType) >= AudioRecord::NUM_STREAM_TYPES) {
1515 LOGE("invalid stream type");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001516 lStatus = BAD_VALUE;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001517 goto Exit;
1518 }
1519
1520 if (sampleRate > MAX_SAMPLE_RATE) {
1521 LOGE("Sample rate out of range");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001522 lStatus = BAD_VALUE;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001523 goto Exit;
1524 }
1525
1526 if (mSampleRate == 0) {
1527 LOGE("Audio driver not initialized");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001528 lStatus = NO_INIT;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001529 goto Exit;
1530 }
1531
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001532 if (mAudioRecordThread == 0) {
1533 LOGE("Audio record thread not started");
1534 lStatus = NO_INIT;
1535 goto Exit;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001536 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001537
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001538
1539 // Check that audio input stream accepts requested audio parameters
1540 inputBufferSize = mAudioHardware->getInputBufferSize(sampleRate, format, channelCount);
1541 if (inputBufferSize == 0) {
1542 lStatus = BAD_VALUE;
1543 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 -07001544 goto Exit;
1545 }
1546
1547 // add client to list
1548 {
1549 Mutex::Autolock _l(mLock);
1550 wclient = mClients.valueFor(pid);
1551 if (wclient != NULL) {
1552 client = wclient.promote();
1553 } else {
1554 client = new Client(this, pid);
1555 mClients.add(pid, client);
1556 }
1557 }
1558
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001559 // frameCount must be a multiple of input buffer size
1560 inFrameCount = inputBufferSize/channelCount/sizeof(short);
1561 frameCount = ((frameCount - 1)/inFrameCount + 1) * inFrameCount;
1562
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001563 // create new record track and pass to record thread
1564 recordTrack = new RecordTrack(this, client, streamType, sampleRate,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001565 format, channelCount, frameCount);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001566
1567 // return to handle to client
1568 recordHandle = new RecordHandle(recordTrack);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001569 lStatus = NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001570
1571Exit:
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001572 if (status) {
1573 *status = lStatus;
1574 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001575 return recordHandle;
1576}
1577
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001578status_t AudioFlinger::startRecord(RecordTrack* recordTrack) {
1579 if (mAudioRecordThread != 0) {
1580 return mAudioRecordThread->start(recordTrack);
1581 }
1582 return NO_INIT;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001583}
1584
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001585void AudioFlinger::stopRecord(RecordTrack* recordTrack) {
1586 if (mAudioRecordThread != 0) {
1587 mAudioRecordThread->stop(recordTrack);
1588 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001589}
1590
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001591
1592// ----------------------------------------------------------------------------
1593
1594AudioFlinger::RecordTrack::RecordTrack(
1595 const sp<AudioFlinger>& audioFlinger,
1596 const sp<Client>& client,
1597 int streamType,
1598 uint32_t sampleRate,
1599 int format,
1600 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001601 int frameCount)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001602 : TrackBase(audioFlinger, client, streamType, sampleRate, format,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001603 channelCount, frameCount, 0),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001604 mOverflow(false)
1605{
1606}
1607
1608AudioFlinger::RecordTrack::~RecordTrack()
1609{
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -08001610 mAudioFlinger->deleteTrackName(mName);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001611}
1612
1613status_t AudioFlinger::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
1614{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001615 audio_track_cblk_t* cblk = this->cblk();
1616 uint32_t framesAvail;
1617 uint32_t framesReq = buffer->frameCount;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001618
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001619 // Check if last stepServer failed, try to step now
1620 if (mFlags & TrackBase::STEPSERVER_FAILED) {
1621 if (!step()) goto getNextBuffer_exit;
1622 LOGV("stepServer recovered");
1623 mFlags &= ~TrackBase::STEPSERVER_FAILED;
1624 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001625
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001626 framesAvail = cblk->framesAvailable_l();
1627
1628 if (LIKELY(framesAvail)) {
1629 uint32_t s = cblk->server;
1630 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
1631
1632 if (framesReq > framesAvail) {
1633 framesReq = framesAvail;
1634 }
1635 if (s + framesReq > bufferEnd) {
1636 framesReq = bufferEnd - s;
1637 }
1638
1639 buffer->raw = getBuffer(s, framesReq);
1640 if (buffer->raw == 0) goto getNextBuffer_exit;
1641
1642 buffer->frameCount = framesReq;
1643 return NO_ERROR;
1644 }
1645
1646getNextBuffer_exit:
1647 buffer->raw = 0;
1648 buffer->frameCount = 0;
1649 return NOT_ENOUGH_DATA;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001650}
1651
1652status_t AudioFlinger::RecordTrack::start()
1653{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001654 return mAudioFlinger->startRecord(this);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001655}
1656
1657void AudioFlinger::RecordTrack::stop()
1658{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001659 mAudioFlinger->stopRecord(this);
1660 TrackBase::reset();
1661 // Force overerrun condition to avoid false overrun callback until first data is
1662 // read from buffer
1663 mCblk->flowControlFlag = 1;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001664}
1665
1666// ----------------------------------------------------------------------------
1667
1668AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::RecordTrack>& recordTrack)
1669 : BnAudioRecord(),
1670 mRecordTrack(recordTrack)
1671{
1672}
1673
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001674AudioFlinger::RecordHandle::~RecordHandle() {
1675 stop();
1676}
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001677
1678status_t AudioFlinger::RecordHandle::start() {
1679 LOGV("RecordHandle::start()");
1680 return mRecordTrack->start();
1681}
1682
1683void AudioFlinger::RecordHandle::stop() {
1684 LOGV("RecordHandle::stop()");
1685 mRecordTrack->stop();
1686}
1687
1688sp<IMemory> AudioFlinger::RecordHandle::getCblk() const {
1689 return mRecordTrack->getCblk();
1690}
1691
1692status_t AudioFlinger::RecordHandle::onTransact(
1693 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1694{
1695 return BnAudioRecord::onTransact(code, data, reply, flags);
1696}
1697
1698// ----------------------------------------------------------------------------
1699
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001700AudioFlinger::AudioRecordThread::AudioRecordThread(AudioHardwareInterface* audioHardware) :
1701 mAudioHardware(audioHardware),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001702 mActive(false)
1703{
1704}
1705
1706AudioFlinger::AudioRecordThread::~AudioRecordThread()
1707{
1708}
1709
1710bool AudioFlinger::AudioRecordThread::threadLoop()
1711{
1712 LOGV("AudioRecordThread: start record loop");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001713 AudioBufferProvider::Buffer buffer;
1714 int inBufferSize = 0;
1715 int inFrameCount = 0;
1716 AudioStreamIn* input = 0;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001717
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001718 mActive = 0;
1719
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001720 // start recording
1721 while (!exitPending()) {
1722 if (!mActive) {
1723 mLock.lock();
1724 if (!mActive && !exitPending()) {
1725 LOGV("AudioRecordThread: loop stopping");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001726 if (input) {
1727 delete input;
1728 input = 0;
1729 }
1730 mRecordTrack.clear();
1731
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001732 mWaitWorkCV.wait(mLock);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001733
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001734 LOGV("AudioRecordThread: loop starting");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001735 if (mRecordTrack != 0) {
1736 input = mAudioHardware->openInputStream(mRecordTrack->format(),
1737 mRecordTrack->channelCount(),
1738 mRecordTrack->sampleRate(),
1739 &mStartStatus);
1740 if (input != 0) {
1741 inBufferSize = input->bufferSize();
1742 inFrameCount = inBufferSize/input->frameSize();
1743 }
1744 } else {
1745 mStartStatus = NO_INIT;
1746 }
1747 if (mStartStatus !=NO_ERROR) {
1748 LOGW("record start failed, status %d", mStartStatus);
1749 mActive = false;
1750 mRecordTrack.clear();
1751 }
1752 mWaitWorkCV.signal();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001753 }
1754 mLock.unlock();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001755 } else if (mRecordTrack != 0){
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001756
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001757 buffer.frameCount = inFrameCount;
1758 if (LIKELY(mRecordTrack->getNextBuffer(&buffer) == NO_ERROR)) {
1759 LOGV("AudioRecordThread read: %d frames", buffer.frameCount);
1760 if (input->read(buffer.raw, inBufferSize) < 0) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001761 LOGE("Error reading audio input");
1762 sleep(1);
1763 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001764 mRecordTrack->releaseBuffer(&buffer);
1765 mRecordTrack->overflow();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001766 }
1767
1768 // client isn't retrieving buffers fast enough
1769 else {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001770 if (!mRecordTrack->setOverflow())
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001771 LOGW("AudioRecordThread: buffer overflow");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001772 // Release the processor for a while before asking for a new buffer.
1773 // This will give the application more chance to read from the buffer and
1774 // clear the overflow.
1775 usleep(5000);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001776 }
1777 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001778 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001779
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001780
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001781 if (input) {
1782 delete input;
1783 }
1784 mRecordTrack.clear();
1785
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001786 return false;
1787}
1788
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001789status_t AudioFlinger::AudioRecordThread::start(RecordTrack* recordTrack)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001790{
1791 LOGV("AudioRecordThread::start");
1792 AutoMutex lock(&mLock);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001793 mActive = true;
1794 // If starting the active track, just reset mActive in case a stop
1795 // was pending and exit
1796 if (recordTrack == mRecordTrack.get()) return NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001797
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001798 if (mRecordTrack != 0) return -EBUSY;
1799
1800 mRecordTrack = recordTrack;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001801
1802 // signal thread to start
1803 LOGV("Signal record thread");
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001804 mWaitWorkCV.signal();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001805 mWaitWorkCV.wait(mLock);
1806 LOGV("Record started, status %d", mStartStatus);
1807 return mStartStatus;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001808}
1809
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001810void AudioFlinger::AudioRecordThread::stop(RecordTrack* recordTrack) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001811 LOGV("AudioRecordThread::stop");
1812 AutoMutex lock(&mLock);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001813 if (mActive && (recordTrack == mRecordTrack.get())) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001814 mActive = false;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001815 }
1816}
1817
1818void AudioFlinger::AudioRecordThread::exit()
1819{
1820 LOGV("AudioRecordThread::exit");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001821 {
1822 AutoMutex lock(&mLock);
1823 requestExit();
1824 mWaitWorkCV.signal();
1825 }
1826 requestExitAndWait();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001827}
1828
1829
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001830status_t AudioFlinger::onTransact(
1831 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1832{
1833 return BnAudioFlinger::onTransact(code, data, reply, flags);
1834}
1835
1836// ----------------------------------------------------------------------------
1837void AudioFlinger::instantiate() {
1838 defaultServiceManager()->addService(
1839 String16("media.audio_flinger"), new AudioFlinger());
1840}
1841
1842}; // namespace android