blob: 53b18ad1a09797605fc068a29f1cdff367d2a3f0 [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
41#include <hardware/AudioHardwareInterface.h>
42
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),
103 mAudioMixer(0), mAudioHardware(0), mA2dpAudioInterface(0),
104 mHardwareOutput(0), mA2dpOutput(0), mOutput(0), mAudioRecordThread(0),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700105 mSampleRate(0), mFrameCount(0), mChannelCount(0), mFormat(0),
106 mMixBuffer(0), mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0),
107 mStandby(false), mInWrite(false)
108{
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) {
119 mSampleRate = mHardwareOutput->sampleRate();
120 mHardwareAudioMixer = new AudioMixer(getOutputFrameCount(mHardwareOutput), mSampleRate);
121 setOutput(mHardwareOutput);
122
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];
162 // FIXME: What property should this be???
163 property_get("ro.audio.silent", value, "0");
164 if (atoi(value)) {
165 LOGD("Silence is golden");
166 mMasterMute = true;
167 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700168}
169
170AudioFlinger::~AudioFlinger()
171{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800172 if (mAudioRecordThread != 0) {
173 mAudioRecordThread->exit();
174 mAudioRecordThread.clear();
175 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700176 delete mOutput;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800177 delete mA2dpOutput;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700178 delete mAudioHardware;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800179 delete mA2dpAudioInterface;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700180 delete [] mMixBuffer;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800181 delete mHardwareAudioMixer;
182 delete mA2dpAudioMixer;
183}
184
185void AudioFlinger::setOutput(AudioStreamOut* output)
186{
187 // lock on mOutputLock to prevent threadLoop() from starving us
188 Mutex::Autolock _l2(mOutputLock);
189
190 // to synchronize with threadLoop()
191 Mutex::Autolock _l(mLock);
192
193 if (mOutput != output) {
194 mSampleRate = output->sampleRate();
195 mChannelCount = output->channelCount();
196
197 // FIXME - Current mixer implementation only supports stereo output
198 if (mChannelCount == 1) {
199 LOGE("Invalid audio hardware channel count");
200 }
201 mFormat = output->format();
202 mFrameCount = getOutputFrameCount(output);
203
204 mAudioMixer = (output == mA2dpOutput ? mA2dpAudioMixer : mHardwareAudioMixer);
205 mOutput = output;
206 }
207}
208
209size_t AudioFlinger::getOutputFrameCount(AudioStreamOut* output)
210{
211 return output->bufferSize() / output->channelCount() / sizeof(int16_t);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700212}
213
214status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args)
215{
216 const size_t SIZE = 256;
217 char buffer[SIZE];
218 String8 result;
219
220 result.append("Clients:\n");
221 for (size_t i = 0; i < mClients.size(); ++i) {
222 wp<Client> wClient = mClients.valueAt(i);
223 if (wClient != 0) {
224 sp<Client> client = wClient.promote();
225 if (client != 0) {
226 snprintf(buffer, SIZE, " pid: %d\n", client->pid());
227 result.append(buffer);
228 }
229 }
230 }
231 write(fd, result.string(), result.size());
232 return NO_ERROR;
233}
234
235status_t AudioFlinger::dumpTracks(int fd, const Vector<String16>& args)
236{
237 const size_t SIZE = 256;
238 char buffer[SIZE];
239 String8 result;
240
241 result.append("Tracks:\n");
242 result.append(" Name Clien Typ Fmt Chn Buf S M F SRate LeftV RighV Serv User\n");
243 for (size_t i = 0; i < mTracks.size(); ++i) {
244 wp<Track> wTrack = mTracks[i];
245 if (wTrack != 0) {
246 sp<Track> track = wTrack.promote();
247 if (track != 0) {
248 track->dump(buffer, SIZE);
249 result.append(buffer);
250 }
251 }
252 }
253
254 result.append("Active Tracks:\n");
255 result.append(" Name Clien Typ Fmt Chn Buf S M F SRate LeftV RighV Serv User\n");
256 for (size_t i = 0; i < mActiveTracks.size(); ++i) {
257 wp<Track> wTrack = mTracks[i];
258 if (wTrack != 0) {
259 sp<Track> track = wTrack.promote();
260 if (track != 0) {
261 track->dump(buffer, SIZE);
262 result.append(buffer);
263 }
264 }
265 }
266 write(fd, result.string(), result.size());
267 return NO_ERROR;
268}
269
270status_t AudioFlinger::dumpInternals(int fd, const Vector<String16>& args)
271{
272 const size_t SIZE = 256;
273 char buffer[SIZE];
274 String8 result;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800275
276 snprintf(buffer, SIZE, "AudioMixer tracks: %08x\n", audioMixer()->trackNames());
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700277 result.append(buffer);
278 snprintf(buffer, SIZE, "last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime));
279 result.append(buffer);
280 snprintf(buffer, SIZE, "total writes: %d\n", mNumWrites);
281 result.append(buffer);
282 snprintf(buffer, SIZE, "delayed writes: %d\n", mNumDelayedWrites);
283 result.append(buffer);
284 snprintf(buffer, SIZE, "blocked in write: %d\n", mInWrite);
285 result.append(buffer);
286 snprintf(buffer, SIZE, "standby: %d\n", mStandby);
287 result.append(buffer);
288 snprintf(buffer, SIZE, "Hardware status: %d\n", mHardwareStatus);
289 result.append(buffer);
290 write(fd, result.string(), result.size());
291 return NO_ERROR;
292}
293
294status_t AudioFlinger::dumpPermissionDenial(int fd, const Vector<String16>& args)
295{
296 const size_t SIZE = 256;
297 char buffer[SIZE];
298 String8 result;
299 snprintf(buffer, SIZE, "Permission Denial: "
300 "can't dump AudioFlinger from pid=%d, uid=%d\n",
301 IPCThreadState::self()->getCallingPid(),
302 IPCThreadState::self()->getCallingUid());
303 result.append(buffer);
304 write(fd, result.string(), result.size());
305 return NO_ERROR;
306}
307
308status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
309{
310 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
311 dumpPermissionDenial(fd, args);
312 } else {
313 AutoMutex lock(&mLock);
314
315 dumpClients(fd, args);
316 dumpTracks(fd, args);
317 dumpInternals(fd, args);
318 if (mAudioHardware) {
319 mAudioHardware->dumpState(fd, args);
320 }
321 }
322 return NO_ERROR;
323}
324
325// Thread virtuals
326bool AudioFlinger::threadLoop()
327{
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700328 unsigned long sleepTime = kBufferRecoveryInUsecs;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700329 int16_t* curBuf = mMixBuffer;
330 Vector< sp<Track> > tracksToRemove;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800331 size_t enabledTracks = 0;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700332 nsecs_t standbyTime = systemTime();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800333 AudioMixer* mixer = 0;
334 size_t frameCount = 0;
335 int channelCount = 0;
336 uint32_t sampleRate = 0;
337 AudioStreamOut* output = 0;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700338
339 do {
340 enabledTracks = 0;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800341 { // scope for the mLock
342
343 // locking briefly on the secondary mOutputLock is necessary to avoid
344 // having this thread starve the thread that called setOutput()
345 mOutputLock.lock();
346 mOutputLock.unlock();
347
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700348 Mutex::Autolock _l(mLock);
349 const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
350
351 // put audio hardware into standby after short delay
352 if UNLIKELY(!activeTracks.size() && systemTime() > standbyTime) {
353 // wait until we have something to do...
354 LOGV("Audio hardware entering standby\n");
355 mHardwareStatus = AUDIO_HW_STANDBY;
356 if (!mStandby) {
357 mAudioHardware->standby();
358 mStandby = true;
359 }
360 mHardwareStatus = AUDIO_HW_IDLE;
361 // we're about to wait, flush the binder command buffer
362 IPCThreadState::self()->flushCommands();
363 mWaitWorkCV.wait(mLock);
364 LOGV("Audio hardware exiting standby\n");
365 standbyTime = systemTime() + kStandbyTimeInNsecs;
366 continue;
367 }
368
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800369 // get active mixer and output parameter while the lock is held and keep them
370 // consistent till the next loop.
371
372 mixer = audioMixer();
373 frameCount = mFrameCount;
374 channelCount = mChannelCount;
375 sampleRate = mSampleRate;
376 output = mOutput;
377
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700378 // find out which tracks need to be processed
379 size_t count = activeTracks.size();
380 for (size_t i=0 ; i<count ; i++) {
381 sp<Track> t = activeTracks[i].promote();
382 if (t == 0) continue;
383
384 Track* const track = t.get();
385 audio_track_cblk_t* cblk = track->cblk();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700386
387 // The first time a track is added we wait
388 // for all its buffers to be filled before processing it
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800389 mixer->setActiveTrack(track->name());
390 if (cblk->framesReady() && (track->isReady() || track->isStopped()) &&
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700391 !track->isPaused())
392 {
393 //LOGD("u=%08x, s=%08x [OK]", u, s);
394
395 // compute volume for this track
396 int16_t left, right;
397 if (track->isMuted() || mMasterMute || track->isPausing()) {
398 left = right = 0;
399 if (track->isPausing()) {
400 LOGV("paused(%d)", track->name());
401 track->setPaused();
402 }
403 } else {
404 float typeVolume = mStreamTypes[track->type()].volume;
405 float v = mMasterVolume * typeVolume;
406 float v_clamped = v * cblk->volume[0];
407 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
408 left = int16_t(v_clamped);
409 v_clamped = v * cblk->volume[1];
410 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
411 right = int16_t(v_clamped);
412 }
413
414 // XXX: these things DON'T need to be done each time
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800415 mixer->setBufferProvider(track);
416 mixer->enable(AudioMixer::MIXING);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700417
418 int param;
419 if ( track->mFillingUpStatus == Track::FS_FILLED) {
420 // no ramp for the first volume setting
421 track->mFillingUpStatus = Track::FS_ACTIVE;
422 if (track->mState == TrackBase::RESUMING) {
423 track->mState = TrackBase::ACTIVE;
424 param = AudioMixer::RAMP_VOLUME;
425 } else {
426 param = AudioMixer::VOLUME;
427 }
428 } else {
429 param = AudioMixer::RAMP_VOLUME;
430 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800431 mixer->setParameter(param, AudioMixer::VOLUME0, left);
432 mixer->setParameter(param, AudioMixer::VOLUME1, right);
433 mixer->setParameter(
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700434 AudioMixer::TRACK,
435 AudioMixer::FORMAT, track->format());
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800436 mixer->setParameter(
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700437 AudioMixer::TRACK,
438 AudioMixer::CHANNEL_COUNT, track->channelCount());
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800439 mixer->setParameter(
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700440 AudioMixer::RESAMPLE,
441 AudioMixer::SAMPLE_RATE,
442 int(cblk->sampleRate));
443
444 // reset retry count
445 track->mRetryCount = kMaxTrackRetries;
446 enabledTracks++;
447 } else {
448 //LOGD("u=%08x, s=%08x [NOT READY]", u, s);
449 if (track->isStopped()) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800450 track->reset();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700451 }
452 if (track->isTerminated() || track->isStopped() || track->isPaused()) {
453 // We have consumed all the buffers of this track.
454 // Remove it from the list of active tracks.
455 LOGV("remove(%d) from active list", track->name());
456 tracksToRemove.add(track);
457 } else {
458 // No buffers for this track. Give it a few chances to
459 // fill a buffer, then remove it from active list.
460 if (--(track->mRetryCount) <= 0) {
461 LOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
462 tracksToRemove.add(track);
463 }
464 }
465 // LOGV("disable(%d)", track->name());
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800466 mixer->disable(AudioMixer::MIXING);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700467 }
468 }
469
470 // remove all the tracks that need to be...
471 count = tracksToRemove.size();
472 if (UNLIKELY(count)) {
473 for (size_t i=0 ; i<count ; i++) {
474 const sp<Track>& track = tracksToRemove[i];
475 mActiveTracks.remove(track);
476 if (track->isTerminated()) {
477 mTracks.remove(track);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800478 mixer->deleteTrackName(track->mName);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700479 }
480 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800481 }
482 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700483 if (LIKELY(enabledTracks)) {
484 // mix buffers...
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800485 mixer->process(curBuf);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700486
487 // output audio to hardware
488 mLastWriteTime = systemTime();
489 mInWrite = true;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800490 size_t mixBufferSize = frameCount*channelCount*sizeof(int16_t);
491 output->write(curBuf, mixBufferSize);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700492 mNumWrites++;
493 mInWrite = false;
494 mStandby = false;
495 nsecs_t temp = systemTime();
496 standbyTime = temp + kStandbyTimeInNsecs;
497 nsecs_t delta = temp - mLastWriteTime;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800498 nsecs_t maxPeriod = seconds(frameCount) / sampleRate * 2;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700499 if (delta > maxPeriod) {
500 LOGW("write blocked for %llu msecs", ns2ms(delta));
501 mNumDelayedWrites++;
502 }
503 sleepTime = kBufferRecoveryInUsecs;
504 } else {
505 // There was nothing to mix this round, which means all
506 // active tracks were late. Sleep a little bit to give
507 // them another chance. If we're too late, the audio
508 // hardware will zero-fill for us.
509 LOGV("no buffers - usleep(%lu)", sleepTime);
510 usleep(sleepTime);
511 if (sleepTime < kMaxBufferRecoveryInUsecs) {
512 sleepTime += kBufferRecoveryInUsecs;
513 }
514 }
515
516 // finally let go of all our tracks, without the lock held
517 // since we can't guarantee the destructors won't acquire that
518 // same lock.
519 tracksToRemove.clear();
520 } while (true);
521
522 return false;
523}
524
525status_t AudioFlinger::readyToRun()
526{
527 if (mSampleRate == 0) {
528 LOGE("No working audio driver found.");
529 return NO_INIT;
530 }
531 LOGI("AudioFlinger's main thread ready to run.");
532 return NO_ERROR;
533}
534
535void AudioFlinger::onFirstRef()
536{
537 run("AudioFlinger", ANDROID_PRIORITY_URGENT_AUDIO);
538}
539
540// IAudioFlinger interface
541sp<IAudioTrack> AudioFlinger::createTrack(
542 pid_t pid,
543 int streamType,
544 uint32_t sampleRate,
545 int format,
546 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800547 int frameCount,
548 uint32_t flags,
549 const sp<IMemory>& sharedBuffer,
550 status_t *status)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700551{
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700552 sp<Track> track;
553 sp<TrackHandle> trackHandle;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700554 sp<Client> client;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800555 wp<Client> wclient;
556 status_t lStatus;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700557
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800558 if (streamType >= AudioTrack::NUM_STREAM_TYPES) {
559 LOGE("invalid stream type");
560 lStatus = BAD_VALUE;
561 goto Exit;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700562 }
563
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800564 // Resampler implementation limits input sampling rate to 2 x output sampling rate.
565 if (sampleRate > MAX_SAMPLE_RATE || sampleRate > mSampleRate*2) {
566 LOGE("Sample rate out of range: %d", sampleRate);
567 lStatus = BAD_VALUE;
568 goto Exit;
569 }
570
571 {
572 Mutex::Autolock _l(mLock);
573
574 if (mSampleRate == 0) {
575 LOGE("Audio driver not initialized.");
576 lStatus = NO_INIT;
577 goto Exit;
578 }
579
580 wclient = mClients.valueFor(pid);
581
582 if (wclient != NULL) {
583 client = wclient.promote();
584 } else {
585 client = new Client(this, pid);
586 mClients.add(pid, client);
587 }
588
589 track = new Track(this, client, streamType, sampleRate, format,
590 channelCount, frameCount, sharedBuffer);
591 mTracks.add(track);
592 trackHandle = new TrackHandle(track);
593
594 lStatus = NO_ERROR;
595 }
596
597Exit:
598 if(status) {
599 *status = lStatus;
600 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700601 return trackHandle;
602}
603
604uint32_t AudioFlinger::sampleRate() const
605{
606 return mSampleRate;
607}
608
609int AudioFlinger::channelCount() const
610{
611 return mChannelCount;
612}
613
614int AudioFlinger::format() const
615{
616 return mFormat;
617}
618
619size_t AudioFlinger::frameCount() const
620{
621 return mFrameCount;
622}
623
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800624uint32_t AudioFlinger::latency() const
625{
626 if (mOutput) {
627 return mOutput->latency();
628 }
629 else {
630 return 0;
631 }
632}
633
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700634status_t AudioFlinger::setMasterVolume(float value)
635{
636 // check calling permissions
637 if (!settingsAllowed()) {
638 return PERMISSION_DENIED;
639 }
640
641 // when hw supports master volume, don't scale in sw mixer
642 AutoMutex lock(mHardwareLock);
643 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
644 if (mAudioHardware->setMasterVolume(value) == NO_ERROR) {
645 mMasterVolume = 1.0f;
646 }
647 else {
648 mMasterVolume = value;
649 }
650 mHardwareStatus = AUDIO_HW_IDLE;
651 return NO_ERROR;
652}
653
654status_t AudioFlinger::setRouting(int mode, uint32_t routes, uint32_t mask)
655{
656 // check calling permissions
657 if (!settingsAllowed()) {
658 return PERMISSION_DENIED;
659 }
660 if ((mode < AudioSystem::MODE_CURRENT) || (mode >= AudioSystem::NUM_MODES)) {
661 LOGW("Illegal value: setRouting(%d, %u, %u)", mode, routes, mask);
662 return BAD_VALUE;
663 }
664
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800665#ifdef WITH_A2DP
666 LOGD("setRouting %d %d %d\n", mode, routes, mask);
667 if (mode == AudioSystem::MODE_NORMAL &&
668 (mask & AudioSystem::ROUTE_BLUETOOTH_A2DP)) {
669 if (routes & AudioSystem::ROUTE_BLUETOOTH_A2DP) {
670 LOGD("set output to A2DP\n");
671 setOutput(mA2dpOutput);
672 } else {
673 LOGD("set output to hardware audio\n");
674 setOutput(mHardwareOutput);
675 }
676 LOGD("setOutput done\n");
677 }
678#endif
679
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700680 AutoMutex lock(mHardwareLock);
681 mHardwareStatus = AUDIO_HW_GET_ROUTING;
682 uint32_t r;
683 uint32_t err = mAudioHardware->getRouting(mode, &r);
684 if (err == NO_ERROR) {
685 r = (r & ~mask) | (routes & mask);
686 mHardwareStatus = AUDIO_HW_SET_ROUTING;
687 err = mAudioHardware->setRouting(mode, r);
688 }
689 mHardwareStatus = AUDIO_HW_IDLE;
690 return err;
691}
692
693uint32_t AudioFlinger::getRouting(int mode) const
694{
695 uint32_t routes = 0;
696 if ((mode >= AudioSystem::MODE_CURRENT) && (mode < AudioSystem::NUM_MODES)) {
697 mHardwareStatus = AUDIO_HW_GET_ROUTING;
698 mAudioHardware->getRouting(mode, &routes);
699 mHardwareStatus = AUDIO_HW_IDLE;
700 } else {
701 LOGW("Illegal value: getRouting(%d)", mode);
702 }
703 return routes;
704}
705
706status_t AudioFlinger::setMode(int mode)
707{
708 // check calling permissions
709 if (!settingsAllowed()) {
710 return PERMISSION_DENIED;
711 }
712 if ((mode < 0) || (mode >= AudioSystem::NUM_MODES)) {
713 LOGW("Illegal value: setMode(%d)", mode);
714 return BAD_VALUE;
715 }
716
717 AutoMutex lock(mHardwareLock);
718 mHardwareStatus = AUDIO_HW_SET_MODE;
719 status_t ret = mAudioHardware->setMode(mode);
720 mHardwareStatus = AUDIO_HW_IDLE;
721 return ret;
722}
723
724int AudioFlinger::getMode() const
725{
726 int mode = AudioSystem::MODE_INVALID;
727 mHardwareStatus = AUDIO_HW_SET_MODE;
728 mAudioHardware->getMode(&mode);
729 mHardwareStatus = AUDIO_HW_IDLE;
730 return mode;
731}
732
733status_t AudioFlinger::setMicMute(bool state)
734{
735 // check calling permissions
736 if (!settingsAllowed()) {
737 return PERMISSION_DENIED;
738 }
739
740 AutoMutex lock(mHardwareLock);
741 mHardwareStatus = AUDIO_HW_SET_MIC_MUTE;
742 status_t ret = mAudioHardware->setMicMute(state);
743 mHardwareStatus = AUDIO_HW_IDLE;
744 return ret;
745}
746
747bool AudioFlinger::getMicMute() const
748{
749 bool state = AudioSystem::MODE_INVALID;
750 mHardwareStatus = AUDIO_HW_GET_MIC_MUTE;
751 mAudioHardware->getMicMute(&state);
752 mHardwareStatus = AUDIO_HW_IDLE;
753 return state;
754}
755
756status_t AudioFlinger::setMasterMute(bool muted)
757{
758 // check calling permissions
759 if (!settingsAllowed()) {
760 return PERMISSION_DENIED;
761 }
762
763 mMasterMute = muted;
764 return NO_ERROR;
765}
766
767float AudioFlinger::masterVolume() const
768{
769 return mMasterVolume;
770}
771
772bool AudioFlinger::masterMute() const
773{
774 return mMasterMute;
775}
776
777status_t AudioFlinger::setStreamVolume(int stream, float value)
778{
779 // check calling permissions
780 if (!settingsAllowed()) {
781 return PERMISSION_DENIED;
782 }
783
784 if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) {
785 return BAD_VALUE;
786 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800787
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700788 mStreamTypes[stream].volume = value;
789 status_t ret = NO_ERROR;
790 if (stream == AudioTrack::VOICE_CALL) {
791 AutoMutex lock(mHardwareLock);
792 mHardwareStatus = AUDIO_SET_VOICE_VOLUME;
793 ret = mAudioHardware->setVoiceVolume(value);
794 mHardwareStatus = AUDIO_HW_IDLE;
795 }
796 return ret;
797}
798
799status_t AudioFlinger::setStreamMute(int stream, bool muted)
800{
801 // check calling permissions
802 if (!settingsAllowed()) {
803 return PERMISSION_DENIED;
804 }
805
806 if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) {
807 return BAD_VALUE;
808 }
809 mStreamTypes[stream].mute = muted;
810 return NO_ERROR;
811}
812
813float AudioFlinger::streamVolume(int stream) const
814{
815 if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) {
816 return 0.0f;
817 }
818 return mStreamTypes[stream].volume;
819}
820
821bool AudioFlinger::streamMute(int stream) const
822{
823 if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) {
824 return true;
825 }
826 return mStreamTypes[stream].mute;
827}
828
829bool AudioFlinger::isMusicActive() const
830{
831 size_t count = mActiveTracks.size();
832 for (size_t i = 0 ; i < count ; ++i) {
833 sp<Track> t = mActiveTracks[i].promote();
834 if (t == 0) continue;
835 Track* const track = t.get();
836 if (t->mStreamType == AudioTrack::MUSIC)
837 return true;
838 }
839 return false;
840}
841
842status_t AudioFlinger::setParameter(const char* key, const char* value)
843{
844 status_t result;
845 AutoMutex lock(mHardwareLock);
846 mHardwareStatus = AUDIO_SET_PARAMETER;
847 result = mAudioHardware->setParameter(key, value);
848 mHardwareStatus = AUDIO_HW_IDLE;
849 return result;
850}
851
852void AudioFlinger::removeClient(pid_t pid)
853{
854 Mutex::Autolock _l(mLock);
855 mClients.removeItem(pid);
856}
857
858status_t AudioFlinger::addTrack(const sp<Track>& track)
859{
860 Mutex::Autolock _l(mLock);
861
862 // here the track could be either new, or restarted
863 // in both cases "unstop" the track
864 if (track->isPaused()) {
865 track->mState = TrackBase::RESUMING;
866 LOGV("PAUSED => RESUMING (%d)", track->name());
867 } else {
868 track->mState = TrackBase::ACTIVE;
869 LOGV("? => ACTIVE (%d)", track->name());
870 }
871 // set retry count for buffer fill
872 track->mRetryCount = kMaxTrackStartupRetries;
873 LOGV("mWaitWorkCV.broadcast");
874 mWaitWorkCV.broadcast();
875
876 if (mActiveTracks.indexOf(track) < 0) {
877 // the track is newly added, make sure it fills up all its
878 // buffers before playing. This is to ensure the client will
879 // effectively get the latency it requested.
880 track->mFillingUpStatus = Track::FS_FILLING;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800881 track->mResetDone = false;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700882 mActiveTracks.add(track);
883 return NO_ERROR;
884 }
885 return ALREADY_EXISTS;
886}
887
888void AudioFlinger::removeTrack(wp<Track> track, int name)
889{
890 Mutex::Autolock _l(mLock);
891 sp<Track> t = track.promote();
892 if (t!=NULL && (t->mState <= TrackBase::STOPPED)) {
893 remove_track_l(track, name);
894 }
895}
896
897void AudioFlinger::remove_track_l(wp<Track> track, int name)
898{
899 sp<Track> t = track.promote();
900 if (t!=NULL) {
901 t->reset();
902 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800903 audioMixer()->deleteTrackName(name);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700904 mActiveTracks.remove(track);
905 mWaitWorkCV.broadcast();
906}
907
908void AudioFlinger::destroyTrack(const sp<Track>& track)
909{
910 // NOTE: We're acquiring a strong reference on the track before
911 // acquiring the lock, this is to make sure removing it from
912 // mTracks won't cause the destructor to be called while the lock is
913 // held (note that technically, 'track' could be a reference to an item
914 // in mTracks, which is why we need to do this).
915 sp<Track> keep(track);
916 Mutex::Autolock _l(mLock);
917 track->mState = TrackBase::TERMINATED;
918 if (mActiveTracks.indexOf(track) < 0) {
919 LOGV("remove track (%d) and delete from mixer", track->name());
920 mTracks.remove(track);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800921 audioMixer()->deleteTrackName(keep->name());
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700922 }
923}
924
925// ----------------------------------------------------------------------------
926
927AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
928 : RefBase(),
929 mAudioFlinger(audioFlinger),
930 mMemoryDealer(new MemoryDealer(1024*1024)),
931 mPid(pid)
932{
933 // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
934}
935
936AudioFlinger::Client::~Client()
937{
938 mAudioFlinger->removeClient(mPid);
939}
940
941const sp<MemoryDealer>& AudioFlinger::Client::heap() const
942{
943 return mMemoryDealer;
944}
945
946// ----------------------------------------------------------------------------
947
948AudioFlinger::TrackBase::TrackBase(
949 const sp<AudioFlinger>& audioFlinger,
950 const sp<Client>& client,
951 int streamType,
952 uint32_t sampleRate,
953 int format,
954 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800955 int frameCount,
956 const sp<IMemory>& sharedBuffer)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700957 : RefBase(),
958 mAudioFlinger(audioFlinger),
959 mClient(client),
960 mStreamType(streamType),
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800961 mFrameCount(0),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700962 mState(IDLE),
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800963 mClientTid(-1),
964 mFormat(format),
965 mFlags(0)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700966{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800967 mName = audioFlinger->audioMixer()->getTrackName();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700968 if (mName < 0) {
969 LOGE("no more track names availlable");
970 return;
971 }
972
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800973 LOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size());
974
975
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700976 // LOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800977 size_t size = sizeof(audio_track_cblk_t);
978 size_t bufferSize = frameCount*channelCount*sizeof(int16_t);
979 if (sharedBuffer == 0) {
980 size += bufferSize;
981 }
982
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700983 mCblkMemory = client->heap()->allocate(size);
984 if (mCblkMemory != 0) {
985 mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer());
986 if (mCblk) { // construct the shared structure in-place.
987 new(mCblk) audio_track_cblk_t();
988 // clear all buffers
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800989 mCblk->frameCount = frameCount;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700990 mCblk->sampleRate = sampleRate;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800991 mCblk->channels = channelCount;
992 if (sharedBuffer == 0) {
993 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
994 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
995 // Force underrun condition to avoid false underrun callback until first data is
996 // written to buffer
997 mCblk->flowControlFlag = 1;
998 } else {
999 mBuffer = sharedBuffer->pointer();
1000 }
1001 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001002 }
1003 } else {
1004 LOGE("not enough memory for AudioTrack size=%u", size);
1005 client->heap()->dump("AudioTrack");
1006 return;
1007 }
1008}
1009
1010AudioFlinger::TrackBase::~TrackBase()
1011{
1012 mCblk->~audio_track_cblk_t(); // destroy our shared-structure.
1013 mCblkMemory.clear(); // and free the shared memory
1014 mClient.clear();
1015}
1016
1017void AudioFlinger::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
1018{
1019 buffer->raw = 0;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001020 mFrameCount = buffer->frameCount;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001021 step();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001022 buffer->frameCount = 0;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001023}
1024
1025bool AudioFlinger::TrackBase::step() {
1026 bool result;
1027 audio_track_cblk_t* cblk = this->cblk();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001028
1029 result = cblk->stepServer(mFrameCount);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001030 if (!result) {
1031 LOGV("stepServer failed acquiring cblk mutex");
1032 mFlags |= STEPSERVER_FAILED;
1033 }
1034 return result;
1035}
1036
1037void AudioFlinger::TrackBase::reset() {
1038 audio_track_cblk_t* cblk = this->cblk();
1039
1040 cblk->user = 0;
1041 cblk->server = 0;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001042 cblk->userBase = 0;
1043 cblk->serverBase = 0;
1044 mFlags = 0;
1045 LOGV("TrackBase::reset");
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001046}
1047
1048sp<IMemory> AudioFlinger::TrackBase::getCblk() const
1049{
1050 return mCblkMemory;
1051}
1052
1053int AudioFlinger::TrackBase::sampleRate() const {
1054 return mCblk->sampleRate;
1055}
1056
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001057int AudioFlinger::TrackBase::channelCount() const {
1058 return mCblk->channels;
1059}
1060
1061void* AudioFlinger::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
1062 audio_track_cblk_t* cblk = this->cblk();
1063 int16_t *bufferStart = (int16_t *)mBuffer + (offset-cblk->serverBase)*cblk->channels;
1064 int16_t *bufferEnd = bufferStart + frames * cblk->channels;
1065
1066 // Check validity of returned pointer in case the track control block would have been corrupted.
1067 if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd) {
1068 LOGW("TrackBase::getBuffer buffer out of range:\n start: %p, end %p , mBuffer %p mBufferEnd %p\n \
1069 server %d, serverBase %d, user %d, userBase %d",
1070 bufferStart, bufferEnd, mBuffer, mBufferEnd,
1071 cblk->server, cblk->serverBase, cblk->user, cblk->userBase);
1072 return 0;
1073 }
1074
1075 return bufferStart;
1076}
1077
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001078// ----------------------------------------------------------------------------
1079
1080AudioFlinger::Track::Track(
1081 const sp<AudioFlinger>& audioFlinger,
1082 const sp<Client>& client,
1083 int streamType,
1084 uint32_t sampleRate,
1085 int format,
1086 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001087 int frameCount,
1088 const sp<IMemory>& sharedBuffer)
1089 : TrackBase(audioFlinger, client, streamType, sampleRate, format, channelCount, frameCount, sharedBuffer)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001090{
1091 mVolume[0] = 1.0f;
1092 mVolume[1] = 1.0f;
1093 mMute = false;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001094 mSharedBuffer = sharedBuffer;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001095}
1096
1097AudioFlinger::Track::~Track()
1098{
1099 wp<Track> weak(this); // never create a strong ref from the dtor
1100 mState = TERMINATED;
1101 mAudioFlinger->removeTrack(weak, mName);
1102}
1103
1104void AudioFlinger::Track::destroy()
1105{
1106 mAudioFlinger->destroyTrack(this);
1107}
1108
1109void AudioFlinger::Track::dump(char* buffer, size_t size)
1110{
1111 snprintf(buffer, size, " %5d %5d %3u %3u %3u %3u %1d %1d %1d %5u %5u %5u %04x %04x\n",
1112 mName - AudioMixer::TRACK0,
1113 mClient->pid(),
1114 mStreamType,
1115 mFormat,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001116 mCblk->channels,
1117 mFrameCount,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001118 mState,
1119 mMute,
1120 mFillingUpStatus,
1121 mCblk->sampleRate,
1122 mCblk->volume[0],
1123 mCblk->volume[1],
1124 mCblk->server,
1125 mCblk->user);
1126}
1127
1128status_t AudioFlinger::Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
1129{
1130 audio_track_cblk_t* cblk = this->cblk();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001131 uint32_t framesReady;
1132 uint32_t framesReq = buffer->frameCount;
1133
1134 // Check if last stepServer failed, try to step now
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001135 if (mFlags & TrackBase::STEPSERVER_FAILED) {
1136 if (!step()) goto getNextBuffer_exit;
1137 LOGV("stepServer recovered");
1138 mFlags &= ~TrackBase::STEPSERVER_FAILED;
1139 }
1140
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001141 framesReady = cblk->framesReady();
1142
1143 if (LIKELY(framesReady)) {
1144 uint32_t s = cblk->server;
1145 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
1146
1147 bufferEnd = (cblk->loopEnd < bufferEnd) ? cblk->loopEnd : bufferEnd;
1148 if (framesReq > framesReady) {
1149 framesReq = framesReady;
1150 }
1151 if (s + framesReq > bufferEnd) {
1152 framesReq = bufferEnd - s;
1153 }
1154
1155 buffer->raw = getBuffer(s, framesReq);
1156 if (buffer->raw == 0) goto getNextBuffer_exit;
1157
1158 buffer->frameCount = framesReq;
1159 return NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001160 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001161
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001162getNextBuffer_exit:
1163 buffer->raw = 0;
1164 buffer->frameCount = 0;
1165 return NOT_ENOUGH_DATA;
1166}
1167
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001168bool AudioFlinger::Track::isReady() const {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001169 if (mFillingUpStatus != FS_FILLING) return true;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001170
1171 if (mCblk->framesReady() >= mCblk->frameCount ||
1172 mCblk->forceReady) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001173 mFillingUpStatus = FS_FILLED;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001174 mCblk->forceReady = 0;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001175 return true;
1176 }
1177 return false;
1178}
1179
1180status_t AudioFlinger::Track::start()
1181{
1182 LOGV("start(%d)", mName);
1183 mAudioFlinger->addTrack(this);
1184 return NO_ERROR;
1185}
1186
1187void AudioFlinger::Track::stop()
1188{
1189 LOGV("stop(%d)", mName);
1190 Mutex::Autolock _l(mAudioFlinger->mLock);
1191 if (mState > STOPPED) {
1192 mState = STOPPED;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001193 // If the track is not active (PAUSED and buffers full), flush buffers
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001194 if (mAudioFlinger->mActiveTracks.indexOf(this) < 0) {
1195 reset();
1196 }
1197 LOGV("(> STOPPED) => STOPPED (%d)", mName);
1198 }
1199}
1200
1201void AudioFlinger::Track::pause()
1202{
1203 LOGV("pause(%d)", mName);
1204 Mutex::Autolock _l(mAudioFlinger->mLock);
1205 if (mState == ACTIVE || mState == RESUMING) {
1206 mState = PAUSING;
1207 LOGV("ACTIVE/RESUMING => PAUSING (%d)", mName);
1208 }
1209}
1210
1211void AudioFlinger::Track::flush()
1212{
1213 LOGV("flush(%d)", mName);
1214 Mutex::Autolock _l(mAudioFlinger->mLock);
1215 if (mState != STOPPED && mState != PAUSED && mState != PAUSING) {
1216 return;
1217 }
1218 // No point remaining in PAUSED state after a flush => go to
1219 // STOPPED state
1220 mState = STOPPED;
1221
1222 // NOTE: reset() will reset cblk->user and cblk->server with
1223 // the risk that at the same time, the AudioMixer is trying to read
1224 // data. In this case, getNextBuffer() would return a NULL pointer
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001225 // as audio buffer => the AudioMixer code MUST always test that pointer
1226 // returned by getNextBuffer() is not NULL!
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001227 reset();
1228}
1229
1230void AudioFlinger::Track::reset()
1231{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001232 // Do not reset twice to avoid discarding data written just after a flush and before
1233 // the audioflinger thread detects the track is stopped.
1234 if (!mResetDone) {
1235 TrackBase::reset();
1236 // Force underrun condition to avoid false underrun callback until first data is
1237 // written to buffer
1238 mCblk->flowControlFlag = 1;
1239 mCblk->forceReady = 0;
1240 mFillingUpStatus = FS_FILLING;
1241 mResetDone = true;
1242 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001243}
1244
1245void AudioFlinger::Track::mute(bool muted)
1246{
1247 mMute = muted;
1248}
1249
1250void AudioFlinger::Track::setVolume(float left, float right)
1251{
1252 mVolume[0] = left;
1253 mVolume[1] = right;
1254}
1255
1256// ----------------------------------------------------------------------------
1257
1258AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::Track>& track)
1259 : BnAudioTrack(),
1260 mTrack(track)
1261{
1262}
1263
1264AudioFlinger::TrackHandle::~TrackHandle() {
1265 // just stop the track on deletion, associated resources
1266 // will be freed from the main thread once all pending buffers have
1267 // been played. Unless it's not in the active track list, in which
1268 // case we free everything now...
1269 mTrack->destroy();
1270}
1271
1272status_t AudioFlinger::TrackHandle::start() {
1273 return mTrack->start();
1274}
1275
1276void AudioFlinger::TrackHandle::stop() {
1277 mTrack->stop();
1278}
1279
1280void AudioFlinger::TrackHandle::flush() {
1281 mTrack->flush();
1282}
1283
1284void AudioFlinger::TrackHandle::mute(bool e) {
1285 mTrack->mute(e);
1286}
1287
1288void AudioFlinger::TrackHandle::pause() {
1289 mTrack->pause();
1290}
1291
1292void AudioFlinger::TrackHandle::setVolume(float left, float right) {
1293 mTrack->setVolume(left, right);
1294}
1295
1296sp<IMemory> AudioFlinger::TrackHandle::getCblk() const {
1297 return mTrack->getCblk();
1298}
1299
1300status_t AudioFlinger::TrackHandle::onTransact(
1301 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1302{
1303 return BnAudioTrack::onTransact(code, data, reply, flags);
1304}
1305
1306// ----------------------------------------------------------------------------
1307
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001308sp<IAudioRecord> AudioFlinger::openRecord(
1309 pid_t pid,
1310 int streamType,
1311 uint32_t sampleRate,
1312 int format,
1313 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001314 int frameCount,
1315 uint32_t flags,
1316 status_t *status)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001317{
1318 sp<AudioRecordThread> thread;
1319 sp<RecordTrack> recordTrack;
1320 sp<RecordHandle> recordHandle;
1321 sp<Client> client;
1322 wp<Client> wclient;
1323 AudioStreamIn* input = 0;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001324 int inFrameCount;
1325 size_t inputBufferSize;
1326 status_t lStatus;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001327
1328 // check calling permissions
1329 if (!recordingAllowed()) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001330 lStatus = PERMISSION_DENIED;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001331 goto Exit;
1332 }
1333
1334 if (uint32_t(streamType) >= AudioRecord::NUM_STREAM_TYPES) {
1335 LOGE("invalid stream type");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001336 lStatus = BAD_VALUE;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001337 goto Exit;
1338 }
1339
1340 if (sampleRate > MAX_SAMPLE_RATE) {
1341 LOGE("Sample rate out of range");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001342 lStatus = BAD_VALUE;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001343 goto Exit;
1344 }
1345
1346 if (mSampleRate == 0) {
1347 LOGE("Audio driver not initialized");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001348 lStatus = NO_INIT;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001349 goto Exit;
1350 }
1351
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001352 if (mAudioRecordThread == 0) {
1353 LOGE("Audio record thread not started");
1354 lStatus = NO_INIT;
1355 goto Exit;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001356 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001357
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001358
1359 // Check that audio input stream accepts requested audio parameters
1360 inputBufferSize = mAudioHardware->getInputBufferSize(sampleRate, format, channelCount);
1361 if (inputBufferSize == 0) {
1362 lStatus = BAD_VALUE;
1363 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 -07001364 goto Exit;
1365 }
1366
1367 // add client to list
1368 {
1369 Mutex::Autolock _l(mLock);
1370 wclient = mClients.valueFor(pid);
1371 if (wclient != NULL) {
1372 client = wclient.promote();
1373 } else {
1374 client = new Client(this, pid);
1375 mClients.add(pid, client);
1376 }
1377 }
1378
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001379 // frameCount must be a multiple of input buffer size
1380 inFrameCount = inputBufferSize/channelCount/sizeof(short);
1381 frameCount = ((frameCount - 1)/inFrameCount + 1) * inFrameCount;
1382
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001383 // create new record track and pass to record thread
1384 recordTrack = new RecordTrack(this, client, streamType, sampleRate,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001385 format, channelCount, frameCount);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001386
1387 // return to handle to client
1388 recordHandle = new RecordHandle(recordTrack);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001389 lStatus = NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001390
1391Exit:
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001392 if (status) {
1393 *status = lStatus;
1394 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001395 return recordHandle;
1396}
1397
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001398status_t AudioFlinger::startRecord(RecordTrack* recordTrack) {
1399 if (mAudioRecordThread != 0) {
1400 return mAudioRecordThread->start(recordTrack);
1401 }
1402 return NO_INIT;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001403}
1404
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001405void AudioFlinger::stopRecord(RecordTrack* recordTrack) {
1406 if (mAudioRecordThread != 0) {
1407 mAudioRecordThread->stop(recordTrack);
1408 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001409}
1410
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001411
1412// ----------------------------------------------------------------------------
1413
1414AudioFlinger::RecordTrack::RecordTrack(
1415 const sp<AudioFlinger>& audioFlinger,
1416 const sp<Client>& client,
1417 int streamType,
1418 uint32_t sampleRate,
1419 int format,
1420 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001421 int frameCount)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001422 : TrackBase(audioFlinger, client, streamType, sampleRate, format,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001423 channelCount, frameCount, 0),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001424 mOverflow(false)
1425{
1426}
1427
1428AudioFlinger::RecordTrack::~RecordTrack()
1429{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001430 mAudioFlinger->audioMixer()->deleteTrackName(mName);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001431}
1432
1433status_t AudioFlinger::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
1434{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001435 audio_track_cblk_t* cblk = this->cblk();
1436 uint32_t framesAvail;
1437 uint32_t framesReq = buffer->frameCount;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001438
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001439 // Check if last stepServer failed, try to step now
1440 if (mFlags & TrackBase::STEPSERVER_FAILED) {
1441 if (!step()) goto getNextBuffer_exit;
1442 LOGV("stepServer recovered");
1443 mFlags &= ~TrackBase::STEPSERVER_FAILED;
1444 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001445
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001446 framesAvail = cblk->framesAvailable_l();
1447
1448 if (LIKELY(framesAvail)) {
1449 uint32_t s = cblk->server;
1450 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
1451
1452 if (framesReq > framesAvail) {
1453 framesReq = framesAvail;
1454 }
1455 if (s + framesReq > bufferEnd) {
1456 framesReq = bufferEnd - s;
1457 }
1458
1459 buffer->raw = getBuffer(s, framesReq);
1460 if (buffer->raw == 0) goto getNextBuffer_exit;
1461
1462 buffer->frameCount = framesReq;
1463 return NO_ERROR;
1464 }
1465
1466getNextBuffer_exit:
1467 buffer->raw = 0;
1468 buffer->frameCount = 0;
1469 return NOT_ENOUGH_DATA;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001470}
1471
1472status_t AudioFlinger::RecordTrack::start()
1473{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001474 return mAudioFlinger->startRecord(this);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001475}
1476
1477void AudioFlinger::RecordTrack::stop()
1478{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001479 mAudioFlinger->stopRecord(this);
1480 TrackBase::reset();
1481 // Force overerrun condition to avoid false overrun callback until first data is
1482 // read from buffer
1483 mCblk->flowControlFlag = 1;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001484}
1485
1486// ----------------------------------------------------------------------------
1487
1488AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::RecordTrack>& recordTrack)
1489 : BnAudioRecord(),
1490 mRecordTrack(recordTrack)
1491{
1492}
1493
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001494AudioFlinger::RecordHandle::~RecordHandle() {
1495 stop();
1496}
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001497
1498status_t AudioFlinger::RecordHandle::start() {
1499 LOGV("RecordHandle::start()");
1500 return mRecordTrack->start();
1501}
1502
1503void AudioFlinger::RecordHandle::stop() {
1504 LOGV("RecordHandle::stop()");
1505 mRecordTrack->stop();
1506}
1507
1508sp<IMemory> AudioFlinger::RecordHandle::getCblk() const {
1509 return mRecordTrack->getCblk();
1510}
1511
1512status_t AudioFlinger::RecordHandle::onTransact(
1513 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1514{
1515 return BnAudioRecord::onTransact(code, data, reply, flags);
1516}
1517
1518// ----------------------------------------------------------------------------
1519
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001520AudioFlinger::AudioRecordThread::AudioRecordThread(AudioHardwareInterface* audioHardware) :
1521 mAudioHardware(audioHardware),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001522 mActive(false)
1523{
1524}
1525
1526AudioFlinger::AudioRecordThread::~AudioRecordThread()
1527{
1528}
1529
1530bool AudioFlinger::AudioRecordThread::threadLoop()
1531{
1532 LOGV("AudioRecordThread: start record loop");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001533 AudioBufferProvider::Buffer buffer;
1534 int inBufferSize = 0;
1535 int inFrameCount = 0;
1536 AudioStreamIn* input = 0;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001537
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001538 mActive = 0;
1539
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001540 // start recording
1541 while (!exitPending()) {
1542 if (!mActive) {
1543 mLock.lock();
1544 if (!mActive && !exitPending()) {
1545 LOGV("AudioRecordThread: loop stopping");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001546 if (input) {
1547 delete input;
1548 input = 0;
1549 }
1550 mRecordTrack.clear();
1551
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001552 mWaitWorkCV.wait(mLock);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001553
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001554 LOGV("AudioRecordThread: loop starting");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001555 if (mRecordTrack != 0) {
1556 input = mAudioHardware->openInputStream(mRecordTrack->format(),
1557 mRecordTrack->channelCount(),
1558 mRecordTrack->sampleRate(),
1559 &mStartStatus);
1560 if (input != 0) {
1561 inBufferSize = input->bufferSize();
1562 inFrameCount = inBufferSize/input->frameSize();
1563 }
1564 } else {
1565 mStartStatus = NO_INIT;
1566 }
1567 if (mStartStatus !=NO_ERROR) {
1568 LOGW("record start failed, status %d", mStartStatus);
1569 mActive = false;
1570 mRecordTrack.clear();
1571 }
1572 mWaitWorkCV.signal();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001573 }
1574 mLock.unlock();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001575 } else if (mRecordTrack != 0){
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001576
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001577 buffer.frameCount = inFrameCount;
1578 if (LIKELY(mRecordTrack->getNextBuffer(&buffer) == NO_ERROR)) {
1579 LOGV("AudioRecordThread read: %d frames", buffer.frameCount);
1580 if (input->read(buffer.raw, inBufferSize) < 0) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001581 LOGE("Error reading audio input");
1582 sleep(1);
1583 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001584 mRecordTrack->releaseBuffer(&buffer);
1585 mRecordTrack->overflow();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001586 }
1587
1588 // client isn't retrieving buffers fast enough
1589 else {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001590 if (!mRecordTrack->setOverflow())
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001591 LOGW("AudioRecordThread: buffer overflow");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001592 // Release the processor for a while before asking for a new buffer.
1593 // This will give the application more chance to read from the buffer and
1594 // clear the overflow.
1595 usleep(5000);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001596 }
1597 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001598 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001599
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001600
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001601 if (input) {
1602 delete input;
1603 }
1604 mRecordTrack.clear();
1605
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001606 return false;
1607}
1608
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001609status_t AudioFlinger::AudioRecordThread::start(RecordTrack* recordTrack)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001610{
1611 LOGV("AudioRecordThread::start");
1612 AutoMutex lock(&mLock);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001613 mActive = true;
1614 // If starting the active track, just reset mActive in case a stop
1615 // was pending and exit
1616 if (recordTrack == mRecordTrack.get()) return NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001617
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001618 if (mRecordTrack != 0) return -EBUSY;
1619
1620 mRecordTrack = recordTrack;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001621
1622 // signal thread to start
1623 LOGV("Signal record thread");
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001624 mWaitWorkCV.signal();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001625 mWaitWorkCV.wait(mLock);
1626 LOGV("Record started, status %d", mStartStatus);
1627 return mStartStatus;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001628}
1629
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001630void AudioFlinger::AudioRecordThread::stop(RecordTrack* recordTrack) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001631 LOGV("AudioRecordThread::stop");
1632 AutoMutex lock(&mLock);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001633 if (mActive && (recordTrack == mRecordTrack.get())) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001634 mActive = false;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001635 }
1636}
1637
1638void AudioFlinger::AudioRecordThread::exit()
1639{
1640 LOGV("AudioRecordThread::exit");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001641 {
1642 AutoMutex lock(&mLock);
1643 requestExit();
1644 mWaitWorkCV.signal();
1645 }
1646 requestExitAndWait();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001647}
1648
1649
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001650status_t AudioFlinger::onTransact(
1651 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1652{
1653 return BnAudioFlinger::onTransact(code, data, reply, flags);
1654}
1655
1656// ----------------------------------------------------------------------------
1657void AudioFlinger::instantiate() {
1658 defaultServiceManager()->addService(
1659 String16("media.audio_flinger"), new AudioFlinger());
1660}
1661
1662}; // namespace android