blob: c330bc8faba14f253a9bd2f7f174a81fa32c3c9d [file] [log] [blame]
The Android Open Source Project54b6cfa2008-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 Projectf013e1a2008-12-17 18:05:43 -080034#include <cutils/properties.h>
35
The Android Open Source Project54b6cfa2008-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 Project9266c552009-01-15 16:12:10 -080041#include <hardware_legacy/AudioHardwareInterface.h>
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070042
43#include "AudioMixer.h"
44#include "AudioFlinger.h"
45
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -080046#ifdef WITH_A2DP
47#include "A2dpAudioInterface.h"
48#endif
49
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070050namespace android {
51
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -080052//static const nsecs_t kStandbyTimeInNsecs = seconds(3);
The Android Open Source Project54b6cfa2008-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 Projectf013e1a2008-12-17 18:05:43 -0800102 mMasterVolume(0), mMasterMute(true), mHardwareAudioMixer(0), mA2dpAudioMixer(0),
The Android Open Source Projectb7986892009-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 Projectf1e484a2009-01-22 00:13:42 -0800107 mInWrite(false), mA2dpDisableCount(0), mA2dpSuppressed(false)
The Android Open Source Project54b6cfa2008-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 Projectf013e1a2008-12-17 18:05:43 -0800115 status_t status;
116 mHardwareOutput = mAudioHardware->openOutputStream(AudioSystem::PCM_16_BIT, 0, 0, &status);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700117 mHardwareStatus = AUDIO_HW_IDLE;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800118 if (mHardwareOutput) {
The Android Open Source Projectb7986892009-01-09 17:51:23 -0800119 mHardwareAudioMixer = new AudioMixer(getOutputFrameCount(mHardwareOutput), mHardwareOutput->sampleRate());
120 mRequestedOutput = mHardwareOutput;
121 doSetOutput(mHardwareOutput);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800122
The Android Open Source Project54b6cfa2008-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 Projectf013e1a2008-12-17 18:05:43 -0800131 LOGE("Failed to initialize output stream, status: %d", status);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700132 }
The Android Open Source Projectf013e1a2008-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 Project54b6cfa2008-10-21 07:00:00 -0700158 LOGE("Couldn't even initialize the stubbed audio hardware!");
159 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800160
161 char value[PROPERTY_VALUE_MAX];
The Android Open Source Projectf013e1a2008-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 Project54b6cfa2008-10-21 07:00:00 -0700167}
168
169AudioFlinger::~AudioFlinger()
170{
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800171 if (mAudioRecordThread != 0) {
172 mAudioRecordThread->exit();
173 mAudioRecordThread.clear();
174 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700175 delete mAudioHardware;
The Android Open Source Projectb7986892009-01-09 17:51:23 -0800176 // deleting mA2dpAudioInterface also deletes mA2dpOutput;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800177 delete mA2dpAudioInterface;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700178 delete [] mMixBuffer;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800179 delete mHardwareAudioMixer;
180 delete mA2dpAudioMixer;
181}
182
183void AudioFlinger::setOutput(AudioStreamOut* output)
184{
The Android Open Source Projectb7986892009-01-09 17:51:23 -0800185 mRequestedOutput = output;
186}
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800187
The Android Open Source Projectb7986892009-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 Projectf013e1a2008-12-17 18:05:43 -0800196 }
The Android Open Source Projectb7986892009-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 Projectf013e1a2008-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 Project54b6cfa2008-10-21 07:00:00 -0700206}
207
The Android Open Source Projectf1e484a2009-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 Project54b6cfa2008-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 Projectf013e1a2008-12-17 18:05:43 -0800290
291 snprintf(buffer, SIZE, "AudioMixer tracks: %08x\n", audioMixer()->trackNames());
The Android Open Source Project54b6cfa2008-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 Project54b6cfa2008-10-21 07:00:00 -0700343 unsigned long sleepTime = kBufferRecoveryInUsecs;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700344 int16_t* curBuf = mMixBuffer;
345 Vector< sp<Track> > tracksToRemove;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800346 size_t enabledTracks = 0;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700347 nsecs_t standbyTime = systemTime();
348
349 do {
350 enabledTracks = 0;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800351 { // scope for the mLock
352
The Android Open Source Project54b6cfa2008-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 Projectb7986892009-01-09 17:51:23 -0800362 mOutput->standby();
The Android Open Source Project54b6cfa2008-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 Projectb7986892009-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 Project54b6cfa2008-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 Project54b6cfa2008-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 Projectb7986892009-01-09 17:51:23 -0800395 mAudioMixer->setActiveTrack(track->name());
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800396 if (cblk->framesReady() && (track->isReady() || track->isStopped()) &&
The Android Open Source Project54b6cfa2008-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 Projectb7986892009-01-09 17:51:23 -0800421 mAudioMixer->setBufferProvider(track);
422 mAudioMixer->enable(AudioMixer::MIXING);
The Android Open Source Project54b6cfa2008-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 Projectb7986892009-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 Project54b6cfa2008-10-21 07:00:00 -0700440 AudioMixer::TRACK,
441 AudioMixer::FORMAT, track->format());
The Android Open Source Projectb7986892009-01-09 17:51:23 -0800442 mAudioMixer->setParameter(
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700443 AudioMixer::TRACK,
444 AudioMixer::CHANNEL_COUNT, track->channelCount());
The Android Open Source Projectb7986892009-01-09 17:51:23 -0800445 mAudioMixer->setParameter(
The Android Open Source Project54b6cfa2008-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 Projectf013e1a2008-12-17 18:05:43 -0800456 track->reset();
The Android Open Source Project54b6cfa2008-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 Projectb7986892009-01-09 17:51:23 -0800472 mAudioMixer->disable(AudioMixer::MIXING);
The Android Open Source Project54b6cfa2008-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 Projectf1e484a2009-01-22 00:13:42 -0800481 removeActiveTrack(track);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700482 if (track->isTerminated()) {
483 mTracks.remove(track);
The Android Open Source Projectb7986892009-01-09 17:51:23 -0800484 mAudioMixer->deleteTrackName(track->mName);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700485 }
486 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800487 }
488 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700489 if (LIKELY(enabledTracks)) {
490 // mix buffers...
The Android Open Source Projectb7986892009-01-09 17:51:23 -0800491 mAudioMixer->process(curBuf);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700492
493 // output audio to hardware
494 mLastWriteTime = systemTime();
495 mInWrite = true;
The Android Open Source Projectb7986892009-01-09 17:51:23 -0800496 size_t mixBufferSize = mFrameCount*mChannelCount*sizeof(int16_t);
497 mOutput->write(curBuf, mixBufferSize);
The Android Open Source Project54b6cfa2008-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 Projectb7986892009-01-09 17:51:23 -0800504 nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 2;
The Android Open Source Project54b6cfa2008-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 Projectf013e1a2008-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 Project54b6cfa2008-10-21 07:00:00 -0700557{
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700558 sp<Track> track;
559 sp<TrackHandle> trackHandle;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700560 sp<Client> client;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800561 wp<Client> wclient;
562 status_t lStatus;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700563
The Android Open Source Projectf013e1a2008-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 Project54b6cfa2008-10-21 07:00:00 -0700568 }
569
The Android Open Source Projectf013e1a2008-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 Project54b6cfa2008-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 Projectf013e1a2008-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 Project54b6cfa2008-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 Projectb7986892009-01-09 17:51:23 -0800662 status_t err = NO_ERROR;
663
The Android Open Source Project54b6cfa2008-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 Projectf013e1a2008-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 Projectf1e484a2009-01-22 00:13:42 -0800677 AutoMutex lock(&mLock);
678
679 bool enableA2dp = false;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800680 if (routes & AudioSystem::ROUTE_BLUETOOTH_A2DP) {
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -0800681 if (mA2dpDisableCount > 0)
682 mA2dpSuppressed = true;
683 else
684 enableA2dp = true;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800685 }
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -0800686 setA2dpEnabled(enableA2dp);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800687 LOGD("setOutput done\n");
688 }
689#endif
690
The Android Open Source Projectb7986892009-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 Project54b6cfa2008-10-21 07:00:00 -0700704 }
The Android Open Source Project54b6cfa2008-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 Projectf013e1a2008-12-17 18:05:43 -0800802
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700803 mStreamTypes[stream].volume = value;
804 status_t ret = NO_ERROR;
805 if (stream == AudioTrack::VOICE_CALL) {
806 AutoMutex lock(mHardwareLock);
807 mHardwareStatus = AUDIO_SET_VOICE_VOLUME;
808 ret = mAudioHardware->setVoiceVolume(value);
809 mHardwareStatus = AUDIO_HW_IDLE;
810 }
811 return ret;
812}
813
814status_t AudioFlinger::setStreamMute(int stream, bool muted)
815{
816 // check calling permissions
817 if (!settingsAllowed()) {
818 return PERMISSION_DENIED;
819 }
820
821 if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) {
822 return BAD_VALUE;
823 }
824 mStreamTypes[stream].mute = muted;
825 return NO_ERROR;
826}
827
828float AudioFlinger::streamVolume(int stream) const
829{
830 if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) {
831 return 0.0f;
832 }
833 return mStreamTypes[stream].volume;
834}
835
836bool AudioFlinger::streamMute(int stream) const
837{
838 if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) {
839 return true;
840 }
841 return mStreamTypes[stream].mute;
842}
843
844bool AudioFlinger::isMusicActive() const
845{
846 size_t count = mActiveTracks.size();
847 for (size_t i = 0 ; i < count ; ++i) {
848 sp<Track> t = mActiveTracks[i].promote();
849 if (t == 0) continue;
850 Track* const track = t.get();
851 if (t->mStreamType == AudioTrack::MUSIC)
852 return true;
853 }
854 return false;
855}
856
857status_t AudioFlinger::setParameter(const char* key, const char* value)
858{
The Android Open Source Project9266c552009-01-15 16:12:10 -0800859 status_t result, result2;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700860 AutoMutex lock(mHardwareLock);
861 mHardwareStatus = AUDIO_SET_PARAMETER;
862 result = mAudioHardware->setParameter(key, value);
The Android Open Source Project9266c552009-01-15 16:12:10 -0800863 if (mA2dpAudioInterface) {
864 result2 = mA2dpAudioInterface->setParameter(key, value);
865 if (result2)
866 result = result2;
867 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700868 mHardwareStatus = AUDIO_HW_IDLE;
869 return result;
870}
871
872void AudioFlinger::removeClient(pid_t pid)
873{
874 Mutex::Autolock _l(mLock);
875 mClients.removeItem(pid);
876}
877
878status_t AudioFlinger::addTrack(const sp<Track>& track)
879{
880 Mutex::Autolock _l(mLock);
881
882 // here the track could be either new, or restarted
883 // in both cases "unstop" the track
884 if (track->isPaused()) {
885 track->mState = TrackBase::RESUMING;
886 LOGV("PAUSED => RESUMING (%d)", track->name());
887 } else {
888 track->mState = TrackBase::ACTIVE;
889 LOGV("? => ACTIVE (%d)", track->name());
890 }
891 // set retry count for buffer fill
892 track->mRetryCount = kMaxTrackStartupRetries;
893 LOGV("mWaitWorkCV.broadcast");
894 mWaitWorkCV.broadcast();
895
896 if (mActiveTracks.indexOf(track) < 0) {
897 // the track is newly added, make sure it fills up all its
898 // buffers before playing. This is to ensure the client will
899 // effectively get the latency it requested.
900 track->mFillingUpStatus = Track::FS_FILLING;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800901 track->mResetDone = false;
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -0800902 addActiveTrack(track);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700903 return NO_ERROR;
904 }
905 return ALREADY_EXISTS;
906}
907
908void AudioFlinger::removeTrack(wp<Track> track, int name)
909{
910 Mutex::Autolock _l(mLock);
911 sp<Track> t = track.promote();
912 if (t!=NULL && (t->mState <= TrackBase::STOPPED)) {
913 remove_track_l(track, name);
914 }
915}
916
917void AudioFlinger::remove_track_l(wp<Track> track, int name)
918{
919 sp<Track> t = track.promote();
920 if (t!=NULL) {
921 t->reset();
922 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800923 audioMixer()->deleteTrackName(name);
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -0800924 removeActiveTrack(track);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700925 mWaitWorkCV.broadcast();
926}
927
928void AudioFlinger::destroyTrack(const sp<Track>& track)
929{
930 // NOTE: We're acquiring a strong reference on the track before
931 // acquiring the lock, this is to make sure removing it from
932 // mTracks won't cause the destructor to be called while the lock is
933 // held (note that technically, 'track' could be a reference to an item
934 // in mTracks, which is why we need to do this).
935 sp<Track> keep(track);
936 Mutex::Autolock _l(mLock);
937 track->mState = TrackBase::TERMINATED;
938 if (mActiveTracks.indexOf(track) < 0) {
939 LOGV("remove track (%d) and delete from mixer", track->name());
940 mTracks.remove(track);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800941 audioMixer()->deleteTrackName(keep->name());
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700942 }
943}
944
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -0800945void AudioFlinger::addActiveTrack(const wp<Track>& t)
946{
947 mActiveTracks.add(t);
948
949#ifdef WITH_A2DP
950 // disable A2DP for certain stream types
951 sp<Track> track = t.promote();
952 if (streamDisablesA2dp(track->type())) {
953 if (mA2dpDisableCount++ == 0 && isA2dpEnabled()) {
954 setA2dpEnabled(false);
955 mA2dpSuppressed = true;
956 LOGD("mA2dpSuppressed = true\n");
957 }
958 LOGD("mA2dpDisableCount incremented to %d\n", mA2dpDisableCount);
959 }
960#endif
961}
962
963void AudioFlinger::removeActiveTrack(const wp<Track>& t)
964{
965 mActiveTracks.remove(t);
966#ifdef WITH_A2DP
967 // disable A2DP for certain stream types
968 sp<Track> track = t.promote();
969 if (streamDisablesA2dp(track->type())) {
970 if (mA2dpDisableCount > 0) {
971 mA2dpDisableCount--;
972 if (mA2dpDisableCount == 0 && mA2dpSuppressed) {
973 setA2dpEnabled(true);
974 mA2dpSuppressed = false;
975 }
976 LOGD("mA2dpDisableCount decremented to %d\n", mA2dpDisableCount);
977 } else
978 LOGE("mA2dpDisableCount is already zero");
979 }
980#endif
981}
982
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700983// ----------------------------------------------------------------------------
984
985AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
986 : RefBase(),
987 mAudioFlinger(audioFlinger),
988 mMemoryDealer(new MemoryDealer(1024*1024)),
989 mPid(pid)
990{
991 // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
992}
993
994AudioFlinger::Client::~Client()
995{
996 mAudioFlinger->removeClient(mPid);
997}
998
999const sp<MemoryDealer>& AudioFlinger::Client::heap() const
1000{
1001 return mMemoryDealer;
1002}
1003
1004// ----------------------------------------------------------------------------
1005
1006AudioFlinger::TrackBase::TrackBase(
1007 const sp<AudioFlinger>& audioFlinger,
1008 const sp<Client>& client,
1009 int streamType,
1010 uint32_t sampleRate,
1011 int format,
1012 int channelCount,
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001013 int frameCount,
1014 const sp<IMemory>& sharedBuffer)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001015 : RefBase(),
1016 mAudioFlinger(audioFlinger),
1017 mClient(client),
1018 mStreamType(streamType),
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001019 mFrameCount(0),
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001020 mState(IDLE),
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001021 mClientTid(-1),
1022 mFormat(format),
1023 mFlags(0)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001024{
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001025 mName = audioFlinger->audioMixer()->getTrackName();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001026 if (mName < 0) {
1027 LOGE("no more track names availlable");
1028 return;
1029 }
1030
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001031 LOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size());
1032
1033
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001034 // LOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001035 size_t size = sizeof(audio_track_cblk_t);
1036 size_t bufferSize = frameCount*channelCount*sizeof(int16_t);
1037 if (sharedBuffer == 0) {
1038 size += bufferSize;
1039 }
1040
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001041 mCblkMemory = client->heap()->allocate(size);
1042 if (mCblkMemory != 0) {
1043 mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer());
1044 if (mCblk) { // construct the shared structure in-place.
1045 new(mCblk) audio_track_cblk_t();
1046 // clear all buffers
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001047 mCblk->frameCount = frameCount;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001048 mCblk->sampleRate = sampleRate;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001049 mCblk->channels = channelCount;
1050 if (sharedBuffer == 0) {
1051 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
1052 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
1053 // Force underrun condition to avoid false underrun callback until first data is
1054 // written to buffer
1055 mCblk->flowControlFlag = 1;
1056 } else {
1057 mBuffer = sharedBuffer->pointer();
1058 }
1059 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001060 }
1061 } else {
1062 LOGE("not enough memory for AudioTrack size=%u", size);
1063 client->heap()->dump("AudioTrack");
1064 return;
1065 }
1066}
1067
1068AudioFlinger::TrackBase::~TrackBase()
1069{
1070 mCblk->~audio_track_cblk_t(); // destroy our shared-structure.
1071 mCblkMemory.clear(); // and free the shared memory
1072 mClient.clear();
1073}
1074
1075void AudioFlinger::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
1076{
1077 buffer->raw = 0;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001078 mFrameCount = buffer->frameCount;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001079 step();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001080 buffer->frameCount = 0;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001081}
1082
1083bool AudioFlinger::TrackBase::step() {
1084 bool result;
1085 audio_track_cblk_t* cblk = this->cblk();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001086
1087 result = cblk->stepServer(mFrameCount);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001088 if (!result) {
1089 LOGV("stepServer failed acquiring cblk mutex");
1090 mFlags |= STEPSERVER_FAILED;
1091 }
1092 return result;
1093}
1094
1095void AudioFlinger::TrackBase::reset() {
1096 audio_track_cblk_t* cblk = this->cblk();
1097
1098 cblk->user = 0;
1099 cblk->server = 0;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001100 cblk->userBase = 0;
1101 cblk->serverBase = 0;
1102 mFlags = 0;
1103 LOGV("TrackBase::reset");
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001104}
1105
1106sp<IMemory> AudioFlinger::TrackBase::getCblk() const
1107{
1108 return mCblkMemory;
1109}
1110
1111int AudioFlinger::TrackBase::sampleRate() const {
1112 return mCblk->sampleRate;
1113}
1114
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001115int AudioFlinger::TrackBase::channelCount() const {
1116 return mCblk->channels;
1117}
1118
1119void* AudioFlinger::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
1120 audio_track_cblk_t* cblk = this->cblk();
1121 int16_t *bufferStart = (int16_t *)mBuffer + (offset-cblk->serverBase)*cblk->channels;
1122 int16_t *bufferEnd = bufferStart + frames * cblk->channels;
1123
1124 // Check validity of returned pointer in case the track control block would have been corrupted.
1125 if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd) {
1126 LOGW("TrackBase::getBuffer buffer out of range:\n start: %p, end %p , mBuffer %p mBufferEnd %p\n \
1127 server %d, serverBase %d, user %d, userBase %d",
1128 bufferStart, bufferEnd, mBuffer, mBufferEnd,
1129 cblk->server, cblk->serverBase, cblk->user, cblk->userBase);
1130 return 0;
1131 }
1132
1133 return bufferStart;
1134}
1135
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001136// ----------------------------------------------------------------------------
1137
1138AudioFlinger::Track::Track(
1139 const sp<AudioFlinger>& audioFlinger,
1140 const sp<Client>& client,
1141 int streamType,
1142 uint32_t sampleRate,
1143 int format,
1144 int channelCount,
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001145 int frameCount,
1146 const sp<IMemory>& sharedBuffer)
1147 : TrackBase(audioFlinger, client, streamType, sampleRate, format, channelCount, frameCount, sharedBuffer)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001148{
1149 mVolume[0] = 1.0f;
1150 mVolume[1] = 1.0f;
1151 mMute = false;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001152 mSharedBuffer = sharedBuffer;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001153}
1154
1155AudioFlinger::Track::~Track()
1156{
1157 wp<Track> weak(this); // never create a strong ref from the dtor
1158 mState = TERMINATED;
1159 mAudioFlinger->removeTrack(weak, mName);
1160}
1161
1162void AudioFlinger::Track::destroy()
1163{
1164 mAudioFlinger->destroyTrack(this);
1165}
1166
1167void AudioFlinger::Track::dump(char* buffer, size_t size)
1168{
1169 snprintf(buffer, size, " %5d %5d %3u %3u %3u %3u %1d %1d %1d %5u %5u %5u %04x %04x\n",
1170 mName - AudioMixer::TRACK0,
1171 mClient->pid(),
1172 mStreamType,
1173 mFormat,
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001174 mCblk->channels,
1175 mFrameCount,
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001176 mState,
1177 mMute,
1178 mFillingUpStatus,
1179 mCblk->sampleRate,
1180 mCblk->volume[0],
1181 mCblk->volume[1],
1182 mCblk->server,
1183 mCblk->user);
1184}
1185
1186status_t AudioFlinger::Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
1187{
1188 audio_track_cblk_t* cblk = this->cblk();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001189 uint32_t framesReady;
1190 uint32_t framesReq = buffer->frameCount;
1191
1192 // Check if last stepServer failed, try to step now
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001193 if (mFlags & TrackBase::STEPSERVER_FAILED) {
1194 if (!step()) goto getNextBuffer_exit;
1195 LOGV("stepServer recovered");
1196 mFlags &= ~TrackBase::STEPSERVER_FAILED;
1197 }
1198
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001199 framesReady = cblk->framesReady();
1200
1201 if (LIKELY(framesReady)) {
1202 uint32_t s = cblk->server;
1203 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
1204
1205 bufferEnd = (cblk->loopEnd < bufferEnd) ? cblk->loopEnd : bufferEnd;
1206 if (framesReq > framesReady) {
1207 framesReq = framesReady;
1208 }
1209 if (s + framesReq > bufferEnd) {
1210 framesReq = bufferEnd - s;
1211 }
1212
1213 buffer->raw = getBuffer(s, framesReq);
1214 if (buffer->raw == 0) goto getNextBuffer_exit;
1215
1216 buffer->frameCount = framesReq;
1217 return NO_ERROR;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001218 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001219
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001220getNextBuffer_exit:
1221 buffer->raw = 0;
1222 buffer->frameCount = 0;
1223 return NOT_ENOUGH_DATA;
1224}
1225
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001226bool AudioFlinger::Track::isReady() const {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001227 if (mFillingUpStatus != FS_FILLING) return true;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001228
1229 if (mCblk->framesReady() >= mCblk->frameCount ||
1230 mCblk->forceReady) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001231 mFillingUpStatus = FS_FILLED;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001232 mCblk->forceReady = 0;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001233 return true;
1234 }
1235 return false;
1236}
1237
1238status_t AudioFlinger::Track::start()
1239{
1240 LOGV("start(%d)", mName);
1241 mAudioFlinger->addTrack(this);
1242 return NO_ERROR;
1243}
1244
1245void AudioFlinger::Track::stop()
1246{
1247 LOGV("stop(%d)", mName);
1248 Mutex::Autolock _l(mAudioFlinger->mLock);
1249 if (mState > STOPPED) {
1250 mState = STOPPED;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001251 // If the track is not active (PAUSED and buffers full), flush buffers
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001252 if (mAudioFlinger->mActiveTracks.indexOf(this) < 0) {
1253 reset();
1254 }
1255 LOGV("(> STOPPED) => STOPPED (%d)", mName);
1256 }
1257}
1258
1259void AudioFlinger::Track::pause()
1260{
1261 LOGV("pause(%d)", mName);
1262 Mutex::Autolock _l(mAudioFlinger->mLock);
1263 if (mState == ACTIVE || mState == RESUMING) {
1264 mState = PAUSING;
1265 LOGV("ACTIVE/RESUMING => PAUSING (%d)", mName);
1266 }
1267}
1268
1269void AudioFlinger::Track::flush()
1270{
1271 LOGV("flush(%d)", mName);
1272 Mutex::Autolock _l(mAudioFlinger->mLock);
1273 if (mState != STOPPED && mState != PAUSED && mState != PAUSING) {
1274 return;
1275 }
1276 // No point remaining in PAUSED state after a flush => go to
1277 // STOPPED state
1278 mState = STOPPED;
1279
1280 // NOTE: reset() will reset cblk->user and cblk->server with
1281 // the risk that at the same time, the AudioMixer is trying to read
1282 // data. In this case, getNextBuffer() would return a NULL pointer
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001283 // as audio buffer => the AudioMixer code MUST always test that pointer
1284 // returned by getNextBuffer() is not NULL!
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001285 reset();
1286}
1287
1288void AudioFlinger::Track::reset()
1289{
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001290 // Do not reset twice to avoid discarding data written just after a flush and before
1291 // the audioflinger thread detects the track is stopped.
1292 if (!mResetDone) {
1293 TrackBase::reset();
1294 // Force underrun condition to avoid false underrun callback until first data is
1295 // written to buffer
1296 mCblk->flowControlFlag = 1;
1297 mCblk->forceReady = 0;
1298 mFillingUpStatus = FS_FILLING;
1299 mResetDone = true;
1300 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001301}
1302
1303void AudioFlinger::Track::mute(bool muted)
1304{
1305 mMute = muted;
1306}
1307
1308void AudioFlinger::Track::setVolume(float left, float right)
1309{
1310 mVolume[0] = left;
1311 mVolume[1] = right;
1312}
1313
1314// ----------------------------------------------------------------------------
1315
1316AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::Track>& track)
1317 : BnAudioTrack(),
1318 mTrack(track)
1319{
1320}
1321
1322AudioFlinger::TrackHandle::~TrackHandle() {
1323 // just stop the track on deletion, associated resources
1324 // will be freed from the main thread once all pending buffers have
1325 // been played. Unless it's not in the active track list, in which
1326 // case we free everything now...
1327 mTrack->destroy();
1328}
1329
1330status_t AudioFlinger::TrackHandle::start() {
1331 return mTrack->start();
1332}
1333
1334void AudioFlinger::TrackHandle::stop() {
1335 mTrack->stop();
1336}
1337
1338void AudioFlinger::TrackHandle::flush() {
1339 mTrack->flush();
1340}
1341
1342void AudioFlinger::TrackHandle::mute(bool e) {
1343 mTrack->mute(e);
1344}
1345
1346void AudioFlinger::TrackHandle::pause() {
1347 mTrack->pause();
1348}
1349
1350void AudioFlinger::TrackHandle::setVolume(float left, float right) {
1351 mTrack->setVolume(left, right);
1352}
1353
1354sp<IMemory> AudioFlinger::TrackHandle::getCblk() const {
1355 return mTrack->getCblk();
1356}
1357
1358status_t AudioFlinger::TrackHandle::onTransact(
1359 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1360{
1361 return BnAudioTrack::onTransact(code, data, reply, flags);
1362}
1363
1364// ----------------------------------------------------------------------------
1365
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001366sp<IAudioRecord> AudioFlinger::openRecord(
1367 pid_t pid,
1368 int streamType,
1369 uint32_t sampleRate,
1370 int format,
1371 int channelCount,
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001372 int frameCount,
1373 uint32_t flags,
1374 status_t *status)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001375{
1376 sp<AudioRecordThread> thread;
1377 sp<RecordTrack> recordTrack;
1378 sp<RecordHandle> recordHandle;
1379 sp<Client> client;
1380 wp<Client> wclient;
1381 AudioStreamIn* input = 0;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001382 int inFrameCount;
1383 size_t inputBufferSize;
1384 status_t lStatus;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001385
1386 // check calling permissions
1387 if (!recordingAllowed()) {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001388 lStatus = PERMISSION_DENIED;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001389 goto Exit;
1390 }
1391
1392 if (uint32_t(streamType) >= AudioRecord::NUM_STREAM_TYPES) {
1393 LOGE("invalid stream type");
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001394 lStatus = BAD_VALUE;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001395 goto Exit;
1396 }
1397
1398 if (sampleRate > MAX_SAMPLE_RATE) {
1399 LOGE("Sample rate out of range");
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001400 lStatus = BAD_VALUE;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001401 goto Exit;
1402 }
1403
1404 if (mSampleRate == 0) {
1405 LOGE("Audio driver not initialized");
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001406 lStatus = NO_INIT;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001407 goto Exit;
1408 }
1409
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001410 if (mAudioRecordThread == 0) {
1411 LOGE("Audio record thread not started");
1412 lStatus = NO_INIT;
1413 goto Exit;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001414 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001415
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001416
1417 // Check that audio input stream accepts requested audio parameters
1418 inputBufferSize = mAudioHardware->getInputBufferSize(sampleRate, format, channelCount);
1419 if (inputBufferSize == 0) {
1420 lStatus = BAD_VALUE;
1421 LOGE("Bad audio input parameters: sampling rate %u, format %d, channels %d", sampleRate, format, channelCount);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001422 goto Exit;
1423 }
1424
1425 // add client to list
1426 {
1427 Mutex::Autolock _l(mLock);
1428 wclient = mClients.valueFor(pid);
1429 if (wclient != NULL) {
1430 client = wclient.promote();
1431 } else {
1432 client = new Client(this, pid);
1433 mClients.add(pid, client);
1434 }
1435 }
1436
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001437 // frameCount must be a multiple of input buffer size
1438 inFrameCount = inputBufferSize/channelCount/sizeof(short);
1439 frameCount = ((frameCount - 1)/inFrameCount + 1) * inFrameCount;
1440
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001441 // create new record track and pass to record thread
1442 recordTrack = new RecordTrack(this, client, streamType, sampleRate,
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001443 format, channelCount, frameCount);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001444
1445 // return to handle to client
1446 recordHandle = new RecordHandle(recordTrack);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001447 lStatus = NO_ERROR;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001448
1449Exit:
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001450 if (status) {
1451 *status = lStatus;
1452 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001453 return recordHandle;
1454}
1455
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001456status_t AudioFlinger::startRecord(RecordTrack* recordTrack) {
1457 if (mAudioRecordThread != 0) {
1458 return mAudioRecordThread->start(recordTrack);
1459 }
1460 return NO_INIT;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001461}
1462
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001463void AudioFlinger::stopRecord(RecordTrack* recordTrack) {
1464 if (mAudioRecordThread != 0) {
1465 mAudioRecordThread->stop(recordTrack);
1466 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001467}
1468
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001469
1470// ----------------------------------------------------------------------------
1471
1472AudioFlinger::RecordTrack::RecordTrack(
1473 const sp<AudioFlinger>& audioFlinger,
1474 const sp<Client>& client,
1475 int streamType,
1476 uint32_t sampleRate,
1477 int format,
1478 int channelCount,
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001479 int frameCount)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001480 : TrackBase(audioFlinger, client, streamType, sampleRate, format,
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001481 channelCount, frameCount, 0),
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001482 mOverflow(false)
1483{
1484}
1485
1486AudioFlinger::RecordTrack::~RecordTrack()
1487{
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001488 mAudioFlinger->audioMixer()->deleteTrackName(mName);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001489}
1490
1491status_t AudioFlinger::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
1492{
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001493 audio_track_cblk_t* cblk = this->cblk();
1494 uint32_t framesAvail;
1495 uint32_t framesReq = buffer->frameCount;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001496
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001497 // Check if last stepServer failed, try to step now
1498 if (mFlags & TrackBase::STEPSERVER_FAILED) {
1499 if (!step()) goto getNextBuffer_exit;
1500 LOGV("stepServer recovered");
1501 mFlags &= ~TrackBase::STEPSERVER_FAILED;
1502 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001503
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001504 framesAvail = cblk->framesAvailable_l();
1505
1506 if (LIKELY(framesAvail)) {
1507 uint32_t s = cblk->server;
1508 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
1509
1510 if (framesReq > framesAvail) {
1511 framesReq = framesAvail;
1512 }
1513 if (s + framesReq > bufferEnd) {
1514 framesReq = bufferEnd - s;
1515 }
1516
1517 buffer->raw = getBuffer(s, framesReq);
1518 if (buffer->raw == 0) goto getNextBuffer_exit;
1519
1520 buffer->frameCount = framesReq;
1521 return NO_ERROR;
1522 }
1523
1524getNextBuffer_exit:
1525 buffer->raw = 0;
1526 buffer->frameCount = 0;
1527 return NOT_ENOUGH_DATA;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001528}
1529
1530status_t AudioFlinger::RecordTrack::start()
1531{
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001532 return mAudioFlinger->startRecord(this);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001533}
1534
1535void AudioFlinger::RecordTrack::stop()
1536{
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001537 mAudioFlinger->stopRecord(this);
1538 TrackBase::reset();
1539 // Force overerrun condition to avoid false overrun callback until first data is
1540 // read from buffer
1541 mCblk->flowControlFlag = 1;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001542}
1543
1544// ----------------------------------------------------------------------------
1545
1546AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::RecordTrack>& recordTrack)
1547 : BnAudioRecord(),
1548 mRecordTrack(recordTrack)
1549{
1550}
1551
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001552AudioFlinger::RecordHandle::~RecordHandle() {
1553 stop();
1554}
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001555
1556status_t AudioFlinger::RecordHandle::start() {
1557 LOGV("RecordHandle::start()");
1558 return mRecordTrack->start();
1559}
1560
1561void AudioFlinger::RecordHandle::stop() {
1562 LOGV("RecordHandle::stop()");
1563 mRecordTrack->stop();
1564}
1565
1566sp<IMemory> AudioFlinger::RecordHandle::getCblk() const {
1567 return mRecordTrack->getCblk();
1568}
1569
1570status_t AudioFlinger::RecordHandle::onTransact(
1571 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1572{
1573 return BnAudioRecord::onTransact(code, data, reply, flags);
1574}
1575
1576// ----------------------------------------------------------------------------
1577
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001578AudioFlinger::AudioRecordThread::AudioRecordThread(AudioHardwareInterface* audioHardware) :
1579 mAudioHardware(audioHardware),
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001580 mActive(false)
1581{
1582}
1583
1584AudioFlinger::AudioRecordThread::~AudioRecordThread()
1585{
1586}
1587
1588bool AudioFlinger::AudioRecordThread::threadLoop()
1589{
1590 LOGV("AudioRecordThread: start record loop");
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001591 AudioBufferProvider::Buffer buffer;
1592 int inBufferSize = 0;
1593 int inFrameCount = 0;
1594 AudioStreamIn* input = 0;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001595
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001596 mActive = 0;
1597
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001598 // start recording
1599 while (!exitPending()) {
1600 if (!mActive) {
1601 mLock.lock();
1602 if (!mActive && !exitPending()) {
1603 LOGV("AudioRecordThread: loop stopping");
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001604 if (input) {
1605 delete input;
1606 input = 0;
1607 }
1608 mRecordTrack.clear();
1609
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001610 mWaitWorkCV.wait(mLock);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001611
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001612 LOGV("AudioRecordThread: loop starting");
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001613 if (mRecordTrack != 0) {
1614 input = mAudioHardware->openInputStream(mRecordTrack->format(),
1615 mRecordTrack->channelCount(),
1616 mRecordTrack->sampleRate(),
1617 &mStartStatus);
1618 if (input != 0) {
1619 inBufferSize = input->bufferSize();
1620 inFrameCount = inBufferSize/input->frameSize();
1621 }
1622 } else {
1623 mStartStatus = NO_INIT;
1624 }
1625 if (mStartStatus !=NO_ERROR) {
1626 LOGW("record start failed, status %d", mStartStatus);
1627 mActive = false;
1628 mRecordTrack.clear();
1629 }
1630 mWaitWorkCV.signal();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001631 }
1632 mLock.unlock();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001633 } else if (mRecordTrack != 0){
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001634
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001635 buffer.frameCount = inFrameCount;
1636 if (LIKELY(mRecordTrack->getNextBuffer(&buffer) == NO_ERROR)) {
1637 LOGV("AudioRecordThread read: %d frames", buffer.frameCount);
1638 if (input->read(buffer.raw, inBufferSize) < 0) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001639 LOGE("Error reading audio input");
1640 sleep(1);
1641 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001642 mRecordTrack->releaseBuffer(&buffer);
1643 mRecordTrack->overflow();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001644 }
1645
1646 // client isn't retrieving buffers fast enough
1647 else {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001648 if (!mRecordTrack->setOverflow())
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001649 LOGW("AudioRecordThread: buffer overflow");
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001650 // Release the processor for a while before asking for a new buffer.
1651 // This will give the application more chance to read from the buffer and
1652 // clear the overflow.
1653 usleep(5000);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001654 }
1655 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001656 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001657
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001658
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001659 if (input) {
1660 delete input;
1661 }
1662 mRecordTrack.clear();
1663
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001664 return false;
1665}
1666
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001667status_t AudioFlinger::AudioRecordThread::start(RecordTrack* recordTrack)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001668{
1669 LOGV("AudioRecordThread::start");
1670 AutoMutex lock(&mLock);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001671 mActive = true;
1672 // If starting the active track, just reset mActive in case a stop
1673 // was pending and exit
1674 if (recordTrack == mRecordTrack.get()) return NO_ERROR;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001675
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001676 if (mRecordTrack != 0) return -EBUSY;
1677
1678 mRecordTrack = recordTrack;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001679
1680 // signal thread to start
1681 LOGV("Signal record thread");
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001682 mWaitWorkCV.signal();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001683 mWaitWorkCV.wait(mLock);
1684 LOGV("Record started, status %d", mStartStatus);
1685 return mStartStatus;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001686}
1687
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001688void AudioFlinger::AudioRecordThread::stop(RecordTrack* recordTrack) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001689 LOGV("AudioRecordThread::stop");
1690 AutoMutex lock(&mLock);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001691 if (mActive && (recordTrack == mRecordTrack.get())) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001692 mActive = false;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001693 }
1694}
1695
1696void AudioFlinger::AudioRecordThread::exit()
1697{
1698 LOGV("AudioRecordThread::exit");
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001699 {
1700 AutoMutex lock(&mLock);
1701 requestExit();
1702 mWaitWorkCV.signal();
1703 }
1704 requestExitAndWait();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001705}
1706
1707
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001708status_t AudioFlinger::onTransact(
1709 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1710{
1711 return BnAudioFlinger::onTransact(code, data, reply, flags);
1712}
1713
1714// ----------------------------------------------------------------------------
1715void AudioFlinger::instantiate() {
1716 defaultServiceManager()->addService(
1717 String16("media.audio_flinger"), new AudioFlinger());
1718}
1719
1720}; // namespace android