blob: d4692ad3f13aa85fb1739cc5ba7c46aa6e22e4cd [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),
The Android Open Source Project27629322009-01-09 17:51:23 -0800103 mAudioMixer(0), mAudioHardware(0), mA2dpAudioInterface(0), mHardwareOutput(0),
104 mA2dpOutput(0), mOutput(0), mRequestedOutput(0), mAudioRecordThread(0),
105 mSampleRate(0), mFrameCount(0), mChannelCount(0), mFormat(0), mMixBuffer(0),
106 mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mStandby(false),
107 mInWrite(false)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700108{
109 mHardwareStatus = AUDIO_HW_IDLE;
110 mAudioHardware = AudioHardwareInterface::create();
111 mHardwareStatus = AUDIO_HW_INIT;
112 if (mAudioHardware->initCheck() == NO_ERROR) {
113 // open 16-bit output stream for s/w mixer
114 mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800115 status_t status;
116 mHardwareOutput = mAudioHardware->openOutputStream(AudioSystem::PCM_16_BIT, 0, 0, &status);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700117 mHardwareStatus = AUDIO_HW_IDLE;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800118 if (mHardwareOutput) {
The Android Open Source Project27629322009-01-09 17:51:23 -0800119 mHardwareAudioMixer = new AudioMixer(getOutputFrameCount(mHardwareOutput), mHardwareOutput->sampleRate());
120 mRequestedOutput = mHardwareOutput;
121 doSetOutput(mHardwareOutput);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800122
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700123 // FIXME - this should come from settings
124 setMasterVolume(1.0f);
125 setRouting(AudioSystem::MODE_NORMAL, AudioSystem::ROUTE_SPEAKER, AudioSystem::ROUTE_ALL);
126 setRouting(AudioSystem::MODE_RINGTONE, AudioSystem::ROUTE_SPEAKER, AudioSystem::ROUTE_ALL);
127 setRouting(AudioSystem::MODE_IN_CALL, AudioSystem::ROUTE_EARPIECE, AudioSystem::ROUTE_ALL);
128 setMode(AudioSystem::MODE_NORMAL);
129 mMasterMute = false;
130 } else {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800131 LOGE("Failed to initialize output stream, status: %d", status);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700132 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800133
134#ifdef WITH_A2DP
135 // Create A2DP interface
136 mA2dpAudioInterface = new A2dpAudioInterface();
137 mA2dpOutput = mA2dpAudioInterface->openOutputStream(AudioSystem::PCM_16_BIT, 0, 0, &status);
138 mA2dpAudioMixer = new AudioMixer(getOutputFrameCount(mA2dpOutput), mA2dpOutput->sampleRate());
139
140 // create a buffer big enough for both hardware and A2DP audio output.
141 size_t hwFrameCount = getOutputFrameCount(mHardwareOutput);
142 size_t a2dpFrameCount = getOutputFrameCount(mA2dpOutput);
143 size_t frameCount = (hwFrameCount > a2dpFrameCount ? hwFrameCount : a2dpFrameCount);
144#else
145 size_t frameCount = getOutputFrameCount(mHardwareOutput);
146#endif
147 // FIXME - Current mixer implementation only supports stereo output: Always
148 // Allocate a stereo buffer even if HW output is mono.
149 mMixBuffer = new int16_t[frameCount * 2];
150 memset(mMixBuffer, 0, frameCount * 2 * sizeof(int16_t));
151
152 // Start record thread
153 mAudioRecordThread = new AudioRecordThread(mAudioHardware);
154 if (mAudioRecordThread != 0) {
155 mAudioRecordThread->run("AudioRecordThread", PRIORITY_URGENT_AUDIO);
156 }
157 } else {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700158 LOGE("Couldn't even initialize the stubbed audio hardware!");
159 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800160
161 char value[PROPERTY_VALUE_MAX];
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800162 property_get("ro.audio.silent", value, "0");
163 if (atoi(value)) {
164 LOGD("Silence is golden");
165 mMasterMute = true;
166 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700167}
168
169AudioFlinger::~AudioFlinger()
170{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800171 if (mAudioRecordThread != 0) {
172 mAudioRecordThread->exit();
173 mAudioRecordThread.clear();
174 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700175 delete mAudioHardware;
The Android Open Source Project27629322009-01-09 17:51:23 -0800176 // deleting mA2dpAudioInterface also deletes mA2dpOutput;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800177 delete mA2dpAudioInterface;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700178 delete [] mMixBuffer;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800179 delete mHardwareAudioMixer;
180 delete mA2dpAudioMixer;
181}
182
183void AudioFlinger::setOutput(AudioStreamOut* output)
184{
The Android Open Source Project27629322009-01-09 17:51:23 -0800185 mRequestedOutput = output;
186}
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800187
The Android Open Source Project27629322009-01-09 17:51:23 -0800188void AudioFlinger::doSetOutput(AudioStreamOut* output)
189{
190 mSampleRate = output->sampleRate();
191 mChannelCount = output->channelCount();
192
193 // FIXME - Current mixer implementation only supports stereo output
194 if (mChannelCount == 1) {
195 LOGE("Invalid audio hardware channel count");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800196 }
The Android Open Source Project27629322009-01-09 17:51:23 -0800197 mFormat = output->format();
198 mFrameCount = getOutputFrameCount(output);
199 mAudioMixer = (output == mA2dpOutput ? mA2dpAudioMixer : mHardwareAudioMixer);
200 mOutput = output;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800201}
202
203size_t AudioFlinger::getOutputFrameCount(AudioStreamOut* output)
204{
205 return output->bufferSize() / output->channelCount() / sizeof(int16_t);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700206}
207
208status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args)
209{
210 const size_t SIZE = 256;
211 char buffer[SIZE];
212 String8 result;
213
214 result.append("Clients:\n");
215 for (size_t i = 0; i < mClients.size(); ++i) {
216 wp<Client> wClient = mClients.valueAt(i);
217 if (wClient != 0) {
218 sp<Client> client = wClient.promote();
219 if (client != 0) {
220 snprintf(buffer, SIZE, " pid: %d\n", client->pid());
221 result.append(buffer);
222 }
223 }
224 }
225 write(fd, result.string(), result.size());
226 return NO_ERROR;
227}
228
229status_t AudioFlinger::dumpTracks(int fd, const Vector<String16>& args)
230{
231 const size_t SIZE = 256;
232 char buffer[SIZE];
233 String8 result;
234
235 result.append("Tracks:\n");
236 result.append(" Name Clien Typ Fmt Chn Buf S M F SRate LeftV RighV Serv User\n");
237 for (size_t i = 0; i < mTracks.size(); ++i) {
238 wp<Track> wTrack = mTracks[i];
239 if (wTrack != 0) {
240 sp<Track> track = wTrack.promote();
241 if (track != 0) {
242 track->dump(buffer, SIZE);
243 result.append(buffer);
244 }
245 }
246 }
247
248 result.append("Active Tracks:\n");
249 result.append(" Name Clien Typ Fmt Chn Buf S M F SRate LeftV RighV Serv User\n");
250 for (size_t i = 0; i < mActiveTracks.size(); ++i) {
251 wp<Track> wTrack = mTracks[i];
252 if (wTrack != 0) {
253 sp<Track> track = wTrack.promote();
254 if (track != 0) {
255 track->dump(buffer, SIZE);
256 result.append(buffer);
257 }
258 }
259 }
260 write(fd, result.string(), result.size());
261 return NO_ERROR;
262}
263
264status_t AudioFlinger::dumpInternals(int fd, const Vector<String16>& args)
265{
266 const size_t SIZE = 256;
267 char buffer[SIZE];
268 String8 result;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800269
270 snprintf(buffer, SIZE, "AudioMixer tracks: %08x\n", audioMixer()->trackNames());
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700271 result.append(buffer);
272 snprintf(buffer, SIZE, "last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime));
273 result.append(buffer);
274 snprintf(buffer, SIZE, "total writes: %d\n", mNumWrites);
275 result.append(buffer);
276 snprintf(buffer, SIZE, "delayed writes: %d\n", mNumDelayedWrites);
277 result.append(buffer);
278 snprintf(buffer, SIZE, "blocked in write: %d\n", mInWrite);
279 result.append(buffer);
280 snprintf(buffer, SIZE, "standby: %d\n", mStandby);
281 result.append(buffer);
282 snprintf(buffer, SIZE, "Hardware status: %d\n", mHardwareStatus);
283 result.append(buffer);
284 write(fd, result.string(), result.size());
285 return NO_ERROR;
286}
287
288status_t AudioFlinger::dumpPermissionDenial(int fd, const Vector<String16>& args)
289{
290 const size_t SIZE = 256;
291 char buffer[SIZE];
292 String8 result;
293 snprintf(buffer, SIZE, "Permission Denial: "
294 "can't dump AudioFlinger from pid=%d, uid=%d\n",
295 IPCThreadState::self()->getCallingPid(),
296 IPCThreadState::self()->getCallingUid());
297 result.append(buffer);
298 write(fd, result.string(), result.size());
299 return NO_ERROR;
300}
301
302status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
303{
304 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
305 dumpPermissionDenial(fd, args);
306 } else {
307 AutoMutex lock(&mLock);
308
309 dumpClients(fd, args);
310 dumpTracks(fd, args);
311 dumpInternals(fd, args);
312 if (mAudioHardware) {
313 mAudioHardware->dumpState(fd, args);
314 }
315 }
316 return NO_ERROR;
317}
318
319// Thread virtuals
320bool AudioFlinger::threadLoop()
321{
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700322 unsigned long sleepTime = kBufferRecoveryInUsecs;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700323 int16_t* curBuf = mMixBuffer;
324 Vector< sp<Track> > tracksToRemove;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800325 size_t enabledTracks = 0;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700326 nsecs_t standbyTime = systemTime();
327
328 do {
329 enabledTracks = 0;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800330 { // scope for the mLock
331
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700332 Mutex::Autolock _l(mLock);
333 const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
334
335 // put audio hardware into standby after short delay
336 if UNLIKELY(!activeTracks.size() && systemTime() > standbyTime) {
337 // wait until we have something to do...
338 LOGV("Audio hardware entering standby\n");
339 mHardwareStatus = AUDIO_HW_STANDBY;
340 if (!mStandby) {
The Android Open Source Project27629322009-01-09 17:51:23 -0800341 mOutput->standby();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700342 mStandby = true;
343 }
344 mHardwareStatus = AUDIO_HW_IDLE;
345 // we're about to wait, flush the binder command buffer
346 IPCThreadState::self()->flushCommands();
347 mWaitWorkCV.wait(mLock);
348 LOGV("Audio hardware exiting standby\n");
349 standbyTime = systemTime() + kStandbyTimeInNsecs;
350 continue;
351 }
352
The Android Open Source Project27629322009-01-09 17:51:23 -0800353 // check for change in output
354 if (mRequestedOutput != mOutput) {
355
356 // put current output into standby mode
357 if (mOutput) mOutput->standby();
358
359 // change output
360 doSetOutput(mRequestedOutput);
361 }
362
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700363 // find out which tracks need to be processed
364 size_t count = activeTracks.size();
365 for (size_t i=0 ; i<count ; i++) {
366 sp<Track> t = activeTracks[i].promote();
367 if (t == 0) continue;
368
369 Track* const track = t.get();
370 audio_track_cblk_t* cblk = track->cblk();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700371
372 // The first time a track is added we wait
373 // for all its buffers to be filled before processing it
The Android Open Source Project27629322009-01-09 17:51:23 -0800374 mAudioMixer->setActiveTrack(track->name());
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800375 if (cblk->framesReady() && (track->isReady() || track->isStopped()) &&
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700376 !track->isPaused())
377 {
378 //LOGD("u=%08x, s=%08x [OK]", u, s);
379
380 // compute volume for this track
381 int16_t left, right;
382 if (track->isMuted() || mMasterMute || track->isPausing()) {
383 left = right = 0;
384 if (track->isPausing()) {
385 LOGV("paused(%d)", track->name());
386 track->setPaused();
387 }
388 } else {
389 float typeVolume = mStreamTypes[track->type()].volume;
390 float v = mMasterVolume * typeVolume;
391 float v_clamped = v * cblk->volume[0];
392 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
393 left = int16_t(v_clamped);
394 v_clamped = v * cblk->volume[1];
395 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
396 right = int16_t(v_clamped);
397 }
398
399 // XXX: these things DON'T need to be done each time
The Android Open Source Project27629322009-01-09 17:51:23 -0800400 mAudioMixer->setBufferProvider(track);
401 mAudioMixer->enable(AudioMixer::MIXING);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700402
403 int param;
404 if ( track->mFillingUpStatus == Track::FS_FILLED) {
405 // no ramp for the first volume setting
406 track->mFillingUpStatus = Track::FS_ACTIVE;
407 if (track->mState == TrackBase::RESUMING) {
408 track->mState = TrackBase::ACTIVE;
409 param = AudioMixer::RAMP_VOLUME;
410 } else {
411 param = AudioMixer::VOLUME;
412 }
413 } else {
414 param = AudioMixer::RAMP_VOLUME;
415 }
The Android Open Source Project27629322009-01-09 17:51:23 -0800416 mAudioMixer->setParameter(param, AudioMixer::VOLUME0, left);
417 mAudioMixer->setParameter(param, AudioMixer::VOLUME1, right);
418 mAudioMixer->setParameter(
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700419 AudioMixer::TRACK,
420 AudioMixer::FORMAT, track->format());
The Android Open Source Project27629322009-01-09 17:51:23 -0800421 mAudioMixer->setParameter(
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700422 AudioMixer::TRACK,
423 AudioMixer::CHANNEL_COUNT, track->channelCount());
The Android Open Source Project27629322009-01-09 17:51:23 -0800424 mAudioMixer->setParameter(
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700425 AudioMixer::RESAMPLE,
426 AudioMixer::SAMPLE_RATE,
427 int(cblk->sampleRate));
428
429 // reset retry count
430 track->mRetryCount = kMaxTrackRetries;
431 enabledTracks++;
432 } else {
433 //LOGD("u=%08x, s=%08x [NOT READY]", u, s);
434 if (track->isStopped()) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800435 track->reset();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700436 }
437 if (track->isTerminated() || track->isStopped() || track->isPaused()) {
438 // We have consumed all the buffers of this track.
439 // Remove it from the list of active tracks.
440 LOGV("remove(%d) from active list", track->name());
441 tracksToRemove.add(track);
442 } else {
443 // No buffers for this track. Give it a few chances to
444 // fill a buffer, then remove it from active list.
445 if (--(track->mRetryCount) <= 0) {
446 LOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
447 tracksToRemove.add(track);
448 }
449 }
450 // LOGV("disable(%d)", track->name());
The Android Open Source Project27629322009-01-09 17:51:23 -0800451 mAudioMixer->disable(AudioMixer::MIXING);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700452 }
453 }
454
455 // remove all the tracks that need to be...
456 count = tracksToRemove.size();
457 if (UNLIKELY(count)) {
458 for (size_t i=0 ; i<count ; i++) {
459 const sp<Track>& track = tracksToRemove[i];
460 mActiveTracks.remove(track);
461 if (track->isTerminated()) {
462 mTracks.remove(track);
The Android Open Source Project27629322009-01-09 17:51:23 -0800463 mAudioMixer->deleteTrackName(track->mName);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700464 }
465 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800466 }
467 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700468 if (LIKELY(enabledTracks)) {
469 // mix buffers...
The Android Open Source Project27629322009-01-09 17:51:23 -0800470 mAudioMixer->process(curBuf);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700471
472 // output audio to hardware
473 mLastWriteTime = systemTime();
474 mInWrite = true;
The Android Open Source Project27629322009-01-09 17:51:23 -0800475 size_t mixBufferSize = mFrameCount*mChannelCount*sizeof(int16_t);
476 mOutput->write(curBuf, mixBufferSize);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700477 mNumWrites++;
478 mInWrite = false;
479 mStandby = false;
480 nsecs_t temp = systemTime();
481 standbyTime = temp + kStandbyTimeInNsecs;
482 nsecs_t delta = temp - mLastWriteTime;
The Android Open Source Project27629322009-01-09 17:51:23 -0800483 nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 2;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700484 if (delta > maxPeriod) {
485 LOGW("write blocked for %llu msecs", ns2ms(delta));
486 mNumDelayedWrites++;
487 }
488 sleepTime = kBufferRecoveryInUsecs;
489 } else {
490 // There was nothing to mix this round, which means all
491 // active tracks were late. Sleep a little bit to give
492 // them another chance. If we're too late, the audio
493 // hardware will zero-fill for us.
494 LOGV("no buffers - usleep(%lu)", sleepTime);
495 usleep(sleepTime);
496 if (sleepTime < kMaxBufferRecoveryInUsecs) {
497 sleepTime += kBufferRecoveryInUsecs;
498 }
499 }
500
501 // finally let go of all our tracks, without the lock held
502 // since we can't guarantee the destructors won't acquire that
503 // same lock.
504 tracksToRemove.clear();
505 } while (true);
506
507 return false;
508}
509
510status_t AudioFlinger::readyToRun()
511{
512 if (mSampleRate == 0) {
513 LOGE("No working audio driver found.");
514 return NO_INIT;
515 }
516 LOGI("AudioFlinger's main thread ready to run.");
517 return NO_ERROR;
518}
519
520void AudioFlinger::onFirstRef()
521{
522 run("AudioFlinger", ANDROID_PRIORITY_URGENT_AUDIO);
523}
524
525// IAudioFlinger interface
526sp<IAudioTrack> AudioFlinger::createTrack(
527 pid_t pid,
528 int streamType,
529 uint32_t sampleRate,
530 int format,
531 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800532 int frameCount,
533 uint32_t flags,
534 const sp<IMemory>& sharedBuffer,
535 status_t *status)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700536{
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700537 sp<Track> track;
538 sp<TrackHandle> trackHandle;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700539 sp<Client> client;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800540 wp<Client> wclient;
541 status_t lStatus;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700542
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800543 if (streamType >= AudioTrack::NUM_STREAM_TYPES) {
544 LOGE("invalid stream type");
545 lStatus = BAD_VALUE;
546 goto Exit;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700547 }
548
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800549 // Resampler implementation limits input sampling rate to 2 x output sampling rate.
550 if (sampleRate > MAX_SAMPLE_RATE || sampleRate > mSampleRate*2) {
551 LOGE("Sample rate out of range: %d", sampleRate);
552 lStatus = BAD_VALUE;
553 goto Exit;
554 }
555
556 {
557 Mutex::Autolock _l(mLock);
558
559 if (mSampleRate == 0) {
560 LOGE("Audio driver not initialized.");
561 lStatus = NO_INIT;
562 goto Exit;
563 }
564
565 wclient = mClients.valueFor(pid);
566
567 if (wclient != NULL) {
568 client = wclient.promote();
569 } else {
570 client = new Client(this, pid);
571 mClients.add(pid, client);
572 }
573
574 track = new Track(this, client, streamType, sampleRate, format,
575 channelCount, frameCount, sharedBuffer);
576 mTracks.add(track);
577 trackHandle = new TrackHandle(track);
578
579 lStatus = NO_ERROR;
580 }
581
582Exit:
583 if(status) {
584 *status = lStatus;
585 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700586 return trackHandle;
587}
588
589uint32_t AudioFlinger::sampleRate() const
590{
591 return mSampleRate;
592}
593
594int AudioFlinger::channelCount() const
595{
596 return mChannelCount;
597}
598
599int AudioFlinger::format() const
600{
601 return mFormat;
602}
603
604size_t AudioFlinger::frameCount() const
605{
606 return mFrameCount;
607}
608
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800609uint32_t AudioFlinger::latency() const
610{
611 if (mOutput) {
612 return mOutput->latency();
613 }
614 else {
615 return 0;
616 }
617}
618
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700619status_t AudioFlinger::setMasterVolume(float value)
620{
621 // check calling permissions
622 if (!settingsAllowed()) {
623 return PERMISSION_DENIED;
624 }
625
626 // when hw supports master volume, don't scale in sw mixer
627 AutoMutex lock(mHardwareLock);
628 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
629 if (mAudioHardware->setMasterVolume(value) == NO_ERROR) {
630 mMasterVolume = 1.0f;
631 }
632 else {
633 mMasterVolume = value;
634 }
635 mHardwareStatus = AUDIO_HW_IDLE;
636 return NO_ERROR;
637}
638
639status_t AudioFlinger::setRouting(int mode, uint32_t routes, uint32_t mask)
640{
The Android Open Source Project27629322009-01-09 17:51:23 -0800641 status_t err = NO_ERROR;
642
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700643 // check calling permissions
644 if (!settingsAllowed()) {
645 return PERMISSION_DENIED;
646 }
647 if ((mode < AudioSystem::MODE_CURRENT) || (mode >= AudioSystem::NUM_MODES)) {
648 LOGW("Illegal value: setRouting(%d, %u, %u)", mode, routes, mask);
649 return BAD_VALUE;
650 }
651
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800652#ifdef WITH_A2DP
653 LOGD("setRouting %d %d %d\n", mode, routes, mask);
654 if (mode == AudioSystem::MODE_NORMAL &&
655 (mask & AudioSystem::ROUTE_BLUETOOTH_A2DP)) {
656 if (routes & AudioSystem::ROUTE_BLUETOOTH_A2DP) {
657 LOGD("set output to A2DP\n");
658 setOutput(mA2dpOutput);
659 } else {
660 LOGD("set output to hardware audio\n");
661 setOutput(mHardwareOutput);
662 }
663 LOGD("setOutput done\n");
664 }
665#endif
666
The Android Open Source Project27629322009-01-09 17:51:23 -0800667 // do nothing if only A2DP routing is affected
668 mask &= ~AudioSystem::ROUTE_BLUETOOTH_A2DP;
669 if (mask) {
670 AutoMutex lock(mHardwareLock);
671 mHardwareStatus = AUDIO_HW_GET_ROUTING;
672 uint32_t r;
673 err = mAudioHardware->getRouting(mode, &r);
674 if (err == NO_ERROR) {
675 r = (r & ~mask) | (routes & mask);
676 mHardwareStatus = AUDIO_HW_SET_ROUTING;
677 err = mAudioHardware->setRouting(mode, r);
678 }
679 mHardwareStatus = AUDIO_HW_IDLE;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700680 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700681 return err;
682}
683
684uint32_t AudioFlinger::getRouting(int mode) const
685{
686 uint32_t routes = 0;
687 if ((mode >= AudioSystem::MODE_CURRENT) && (mode < AudioSystem::NUM_MODES)) {
688 mHardwareStatus = AUDIO_HW_GET_ROUTING;
689 mAudioHardware->getRouting(mode, &routes);
690 mHardwareStatus = AUDIO_HW_IDLE;
691 } else {
692 LOGW("Illegal value: getRouting(%d)", mode);
693 }
694 return routes;
695}
696
697status_t AudioFlinger::setMode(int mode)
698{
699 // check calling permissions
700 if (!settingsAllowed()) {
701 return PERMISSION_DENIED;
702 }
703 if ((mode < 0) || (mode >= AudioSystem::NUM_MODES)) {
704 LOGW("Illegal value: setMode(%d)", mode);
705 return BAD_VALUE;
706 }
707
708 AutoMutex lock(mHardwareLock);
709 mHardwareStatus = AUDIO_HW_SET_MODE;
710 status_t ret = mAudioHardware->setMode(mode);
711 mHardwareStatus = AUDIO_HW_IDLE;
712 return ret;
713}
714
715int AudioFlinger::getMode() const
716{
717 int mode = AudioSystem::MODE_INVALID;
718 mHardwareStatus = AUDIO_HW_SET_MODE;
719 mAudioHardware->getMode(&mode);
720 mHardwareStatus = AUDIO_HW_IDLE;
721 return mode;
722}
723
724status_t AudioFlinger::setMicMute(bool state)
725{
726 // check calling permissions
727 if (!settingsAllowed()) {
728 return PERMISSION_DENIED;
729 }
730
731 AutoMutex lock(mHardwareLock);
732 mHardwareStatus = AUDIO_HW_SET_MIC_MUTE;
733 status_t ret = mAudioHardware->setMicMute(state);
734 mHardwareStatus = AUDIO_HW_IDLE;
735 return ret;
736}
737
738bool AudioFlinger::getMicMute() const
739{
740 bool state = AudioSystem::MODE_INVALID;
741 mHardwareStatus = AUDIO_HW_GET_MIC_MUTE;
742 mAudioHardware->getMicMute(&state);
743 mHardwareStatus = AUDIO_HW_IDLE;
744 return state;
745}
746
747status_t AudioFlinger::setMasterMute(bool muted)
748{
749 // check calling permissions
750 if (!settingsAllowed()) {
751 return PERMISSION_DENIED;
752 }
753
754 mMasterMute = muted;
755 return NO_ERROR;
756}
757
758float AudioFlinger::masterVolume() const
759{
760 return mMasterVolume;
761}
762
763bool AudioFlinger::masterMute() const
764{
765 return mMasterMute;
766}
767
768status_t AudioFlinger::setStreamVolume(int stream, float value)
769{
770 // check calling permissions
771 if (!settingsAllowed()) {
772 return PERMISSION_DENIED;
773 }
774
775 if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) {
776 return BAD_VALUE;
777 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800778
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700779 mStreamTypes[stream].volume = value;
780 status_t ret = NO_ERROR;
781 if (stream == AudioTrack::VOICE_CALL) {
782 AutoMutex lock(mHardwareLock);
783 mHardwareStatus = AUDIO_SET_VOICE_VOLUME;
784 ret = mAudioHardware->setVoiceVolume(value);
785 mHardwareStatus = AUDIO_HW_IDLE;
786 }
787 return ret;
788}
789
790status_t AudioFlinger::setStreamMute(int stream, bool muted)
791{
792 // check calling permissions
793 if (!settingsAllowed()) {
794 return PERMISSION_DENIED;
795 }
796
797 if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) {
798 return BAD_VALUE;
799 }
800 mStreamTypes[stream].mute = muted;
801 return NO_ERROR;
802}
803
804float AudioFlinger::streamVolume(int stream) const
805{
806 if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) {
807 return 0.0f;
808 }
809 return mStreamTypes[stream].volume;
810}
811
812bool AudioFlinger::streamMute(int stream) const
813{
814 if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) {
815 return true;
816 }
817 return mStreamTypes[stream].mute;
818}
819
820bool AudioFlinger::isMusicActive() const
821{
822 size_t count = mActiveTracks.size();
823 for (size_t i = 0 ; i < count ; ++i) {
824 sp<Track> t = mActiveTracks[i].promote();
825 if (t == 0) continue;
826 Track* const track = t.get();
827 if (t->mStreamType == AudioTrack::MUSIC)
828 return true;
829 }
830 return false;
831}
832
833status_t AudioFlinger::setParameter(const char* key, const char* value)
834{
835 status_t result;
836 AutoMutex lock(mHardwareLock);
837 mHardwareStatus = AUDIO_SET_PARAMETER;
838 result = mAudioHardware->setParameter(key, value);
839 mHardwareStatus = AUDIO_HW_IDLE;
840 return result;
841}
842
843void AudioFlinger::removeClient(pid_t pid)
844{
845 Mutex::Autolock _l(mLock);
846 mClients.removeItem(pid);
847}
848
849status_t AudioFlinger::addTrack(const sp<Track>& track)
850{
851 Mutex::Autolock _l(mLock);
852
853 // here the track could be either new, or restarted
854 // in both cases "unstop" the track
855 if (track->isPaused()) {
856 track->mState = TrackBase::RESUMING;
857 LOGV("PAUSED => RESUMING (%d)", track->name());
858 } else {
859 track->mState = TrackBase::ACTIVE;
860 LOGV("? => ACTIVE (%d)", track->name());
861 }
862 // set retry count for buffer fill
863 track->mRetryCount = kMaxTrackStartupRetries;
864 LOGV("mWaitWorkCV.broadcast");
865 mWaitWorkCV.broadcast();
866
867 if (mActiveTracks.indexOf(track) < 0) {
868 // the track is newly added, make sure it fills up all its
869 // buffers before playing. This is to ensure the client will
870 // effectively get the latency it requested.
871 track->mFillingUpStatus = Track::FS_FILLING;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800872 track->mResetDone = false;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700873 mActiveTracks.add(track);
874 return NO_ERROR;
875 }
876 return ALREADY_EXISTS;
877}
878
879void AudioFlinger::removeTrack(wp<Track> track, int name)
880{
881 Mutex::Autolock _l(mLock);
882 sp<Track> t = track.promote();
883 if (t!=NULL && (t->mState <= TrackBase::STOPPED)) {
884 remove_track_l(track, name);
885 }
886}
887
888void AudioFlinger::remove_track_l(wp<Track> track, int name)
889{
890 sp<Track> t = track.promote();
891 if (t!=NULL) {
892 t->reset();
893 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800894 audioMixer()->deleteTrackName(name);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700895 mActiveTracks.remove(track);
896 mWaitWorkCV.broadcast();
897}
898
899void AudioFlinger::destroyTrack(const sp<Track>& track)
900{
901 // NOTE: We're acquiring a strong reference on the track before
902 // acquiring the lock, this is to make sure removing it from
903 // mTracks won't cause the destructor to be called while the lock is
904 // held (note that technically, 'track' could be a reference to an item
905 // in mTracks, which is why we need to do this).
906 sp<Track> keep(track);
907 Mutex::Autolock _l(mLock);
908 track->mState = TrackBase::TERMINATED;
909 if (mActiveTracks.indexOf(track) < 0) {
910 LOGV("remove track (%d) and delete from mixer", track->name());
911 mTracks.remove(track);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800912 audioMixer()->deleteTrackName(keep->name());
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700913 }
914}
915
916// ----------------------------------------------------------------------------
917
918AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
919 : RefBase(),
920 mAudioFlinger(audioFlinger),
921 mMemoryDealer(new MemoryDealer(1024*1024)),
922 mPid(pid)
923{
924 // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
925}
926
927AudioFlinger::Client::~Client()
928{
929 mAudioFlinger->removeClient(mPid);
930}
931
932const sp<MemoryDealer>& AudioFlinger::Client::heap() const
933{
934 return mMemoryDealer;
935}
936
937// ----------------------------------------------------------------------------
938
939AudioFlinger::TrackBase::TrackBase(
940 const sp<AudioFlinger>& audioFlinger,
941 const sp<Client>& client,
942 int streamType,
943 uint32_t sampleRate,
944 int format,
945 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800946 int frameCount,
947 const sp<IMemory>& sharedBuffer)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700948 : RefBase(),
949 mAudioFlinger(audioFlinger),
950 mClient(client),
951 mStreamType(streamType),
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800952 mFrameCount(0),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700953 mState(IDLE),
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800954 mClientTid(-1),
955 mFormat(format),
956 mFlags(0)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700957{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800958 mName = audioFlinger->audioMixer()->getTrackName();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700959 if (mName < 0) {
960 LOGE("no more track names availlable");
961 return;
962 }
963
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800964 LOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size());
965
966
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700967 // LOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800968 size_t size = sizeof(audio_track_cblk_t);
969 size_t bufferSize = frameCount*channelCount*sizeof(int16_t);
970 if (sharedBuffer == 0) {
971 size += bufferSize;
972 }
973
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700974 mCblkMemory = client->heap()->allocate(size);
975 if (mCblkMemory != 0) {
976 mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer());
977 if (mCblk) { // construct the shared structure in-place.
978 new(mCblk) audio_track_cblk_t();
979 // clear all buffers
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800980 mCblk->frameCount = frameCount;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700981 mCblk->sampleRate = sampleRate;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800982 mCblk->channels = channelCount;
983 if (sharedBuffer == 0) {
984 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
985 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
986 // Force underrun condition to avoid false underrun callback until first data is
987 // written to buffer
988 mCblk->flowControlFlag = 1;
989 } else {
990 mBuffer = sharedBuffer->pointer();
991 }
992 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700993 }
994 } else {
995 LOGE("not enough memory for AudioTrack size=%u", size);
996 client->heap()->dump("AudioTrack");
997 return;
998 }
999}
1000
1001AudioFlinger::TrackBase::~TrackBase()
1002{
1003 mCblk->~audio_track_cblk_t(); // destroy our shared-structure.
1004 mCblkMemory.clear(); // and free the shared memory
1005 mClient.clear();
1006}
1007
1008void AudioFlinger::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
1009{
1010 buffer->raw = 0;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001011 mFrameCount = buffer->frameCount;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001012 step();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001013 buffer->frameCount = 0;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001014}
1015
1016bool AudioFlinger::TrackBase::step() {
1017 bool result;
1018 audio_track_cblk_t* cblk = this->cblk();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001019
1020 result = cblk->stepServer(mFrameCount);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001021 if (!result) {
1022 LOGV("stepServer failed acquiring cblk mutex");
1023 mFlags |= STEPSERVER_FAILED;
1024 }
1025 return result;
1026}
1027
1028void AudioFlinger::TrackBase::reset() {
1029 audio_track_cblk_t* cblk = this->cblk();
1030
1031 cblk->user = 0;
1032 cblk->server = 0;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001033 cblk->userBase = 0;
1034 cblk->serverBase = 0;
1035 mFlags = 0;
1036 LOGV("TrackBase::reset");
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001037}
1038
1039sp<IMemory> AudioFlinger::TrackBase::getCblk() const
1040{
1041 return mCblkMemory;
1042}
1043
1044int AudioFlinger::TrackBase::sampleRate() const {
1045 return mCblk->sampleRate;
1046}
1047
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001048int AudioFlinger::TrackBase::channelCount() const {
1049 return mCblk->channels;
1050}
1051
1052void* AudioFlinger::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
1053 audio_track_cblk_t* cblk = this->cblk();
1054 int16_t *bufferStart = (int16_t *)mBuffer + (offset-cblk->serverBase)*cblk->channels;
1055 int16_t *bufferEnd = bufferStart + frames * cblk->channels;
1056
1057 // Check validity of returned pointer in case the track control block would have been corrupted.
1058 if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd) {
1059 LOGW("TrackBase::getBuffer buffer out of range:\n start: %p, end %p , mBuffer %p mBufferEnd %p\n \
1060 server %d, serverBase %d, user %d, userBase %d",
1061 bufferStart, bufferEnd, mBuffer, mBufferEnd,
1062 cblk->server, cblk->serverBase, cblk->user, cblk->userBase);
1063 return 0;
1064 }
1065
1066 return bufferStart;
1067}
1068
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001069// ----------------------------------------------------------------------------
1070
1071AudioFlinger::Track::Track(
1072 const sp<AudioFlinger>& audioFlinger,
1073 const sp<Client>& client,
1074 int streamType,
1075 uint32_t sampleRate,
1076 int format,
1077 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001078 int frameCount,
1079 const sp<IMemory>& sharedBuffer)
1080 : TrackBase(audioFlinger, client, streamType, sampleRate, format, channelCount, frameCount, sharedBuffer)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001081{
1082 mVolume[0] = 1.0f;
1083 mVolume[1] = 1.0f;
1084 mMute = false;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001085 mSharedBuffer = sharedBuffer;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001086}
1087
1088AudioFlinger::Track::~Track()
1089{
1090 wp<Track> weak(this); // never create a strong ref from the dtor
1091 mState = TERMINATED;
1092 mAudioFlinger->removeTrack(weak, mName);
1093}
1094
1095void AudioFlinger::Track::destroy()
1096{
1097 mAudioFlinger->destroyTrack(this);
1098}
1099
1100void AudioFlinger::Track::dump(char* buffer, size_t size)
1101{
1102 snprintf(buffer, size, " %5d %5d %3u %3u %3u %3u %1d %1d %1d %5u %5u %5u %04x %04x\n",
1103 mName - AudioMixer::TRACK0,
1104 mClient->pid(),
1105 mStreamType,
1106 mFormat,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001107 mCblk->channels,
1108 mFrameCount,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001109 mState,
1110 mMute,
1111 mFillingUpStatus,
1112 mCblk->sampleRate,
1113 mCblk->volume[0],
1114 mCblk->volume[1],
1115 mCblk->server,
1116 mCblk->user);
1117}
1118
1119status_t AudioFlinger::Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
1120{
1121 audio_track_cblk_t* cblk = this->cblk();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001122 uint32_t framesReady;
1123 uint32_t framesReq = buffer->frameCount;
1124
1125 // Check if last stepServer failed, try to step now
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001126 if (mFlags & TrackBase::STEPSERVER_FAILED) {
1127 if (!step()) goto getNextBuffer_exit;
1128 LOGV("stepServer recovered");
1129 mFlags &= ~TrackBase::STEPSERVER_FAILED;
1130 }
1131
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001132 framesReady = cblk->framesReady();
1133
1134 if (LIKELY(framesReady)) {
1135 uint32_t s = cblk->server;
1136 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
1137
1138 bufferEnd = (cblk->loopEnd < bufferEnd) ? cblk->loopEnd : bufferEnd;
1139 if (framesReq > framesReady) {
1140 framesReq = framesReady;
1141 }
1142 if (s + framesReq > bufferEnd) {
1143 framesReq = bufferEnd - s;
1144 }
1145
1146 buffer->raw = getBuffer(s, framesReq);
1147 if (buffer->raw == 0) goto getNextBuffer_exit;
1148
1149 buffer->frameCount = framesReq;
1150 return NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001151 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001152
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001153getNextBuffer_exit:
1154 buffer->raw = 0;
1155 buffer->frameCount = 0;
1156 return NOT_ENOUGH_DATA;
1157}
1158
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001159bool AudioFlinger::Track::isReady() const {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001160 if (mFillingUpStatus != FS_FILLING) return true;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001161
1162 if (mCblk->framesReady() >= mCblk->frameCount ||
1163 mCblk->forceReady) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001164 mFillingUpStatus = FS_FILLED;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001165 mCblk->forceReady = 0;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001166 return true;
1167 }
1168 return false;
1169}
1170
1171status_t AudioFlinger::Track::start()
1172{
1173 LOGV("start(%d)", mName);
1174 mAudioFlinger->addTrack(this);
1175 return NO_ERROR;
1176}
1177
1178void AudioFlinger::Track::stop()
1179{
1180 LOGV("stop(%d)", mName);
1181 Mutex::Autolock _l(mAudioFlinger->mLock);
1182 if (mState > STOPPED) {
1183 mState = STOPPED;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001184 // If the track is not active (PAUSED and buffers full), flush buffers
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001185 if (mAudioFlinger->mActiveTracks.indexOf(this) < 0) {
1186 reset();
1187 }
1188 LOGV("(> STOPPED) => STOPPED (%d)", mName);
1189 }
1190}
1191
1192void AudioFlinger::Track::pause()
1193{
1194 LOGV("pause(%d)", mName);
1195 Mutex::Autolock _l(mAudioFlinger->mLock);
1196 if (mState == ACTIVE || mState == RESUMING) {
1197 mState = PAUSING;
1198 LOGV("ACTIVE/RESUMING => PAUSING (%d)", mName);
1199 }
1200}
1201
1202void AudioFlinger::Track::flush()
1203{
1204 LOGV("flush(%d)", mName);
1205 Mutex::Autolock _l(mAudioFlinger->mLock);
1206 if (mState != STOPPED && mState != PAUSED && mState != PAUSING) {
1207 return;
1208 }
1209 // No point remaining in PAUSED state after a flush => go to
1210 // STOPPED state
1211 mState = STOPPED;
1212
1213 // NOTE: reset() will reset cblk->user and cblk->server with
1214 // the risk that at the same time, the AudioMixer is trying to read
1215 // data. In this case, getNextBuffer() would return a NULL pointer
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001216 // as audio buffer => the AudioMixer code MUST always test that pointer
1217 // returned by getNextBuffer() is not NULL!
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001218 reset();
1219}
1220
1221void AudioFlinger::Track::reset()
1222{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001223 // Do not reset twice to avoid discarding data written just after a flush and before
1224 // the audioflinger thread detects the track is stopped.
1225 if (!mResetDone) {
1226 TrackBase::reset();
1227 // Force underrun condition to avoid false underrun callback until first data is
1228 // written to buffer
1229 mCblk->flowControlFlag = 1;
1230 mCblk->forceReady = 0;
1231 mFillingUpStatus = FS_FILLING;
1232 mResetDone = true;
1233 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001234}
1235
1236void AudioFlinger::Track::mute(bool muted)
1237{
1238 mMute = muted;
1239}
1240
1241void AudioFlinger::Track::setVolume(float left, float right)
1242{
1243 mVolume[0] = left;
1244 mVolume[1] = right;
1245}
1246
1247// ----------------------------------------------------------------------------
1248
1249AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::Track>& track)
1250 : BnAudioTrack(),
1251 mTrack(track)
1252{
1253}
1254
1255AudioFlinger::TrackHandle::~TrackHandle() {
1256 // just stop the track on deletion, associated resources
1257 // will be freed from the main thread once all pending buffers have
1258 // been played. Unless it's not in the active track list, in which
1259 // case we free everything now...
1260 mTrack->destroy();
1261}
1262
1263status_t AudioFlinger::TrackHandle::start() {
1264 return mTrack->start();
1265}
1266
1267void AudioFlinger::TrackHandle::stop() {
1268 mTrack->stop();
1269}
1270
1271void AudioFlinger::TrackHandle::flush() {
1272 mTrack->flush();
1273}
1274
1275void AudioFlinger::TrackHandle::mute(bool e) {
1276 mTrack->mute(e);
1277}
1278
1279void AudioFlinger::TrackHandle::pause() {
1280 mTrack->pause();
1281}
1282
1283void AudioFlinger::TrackHandle::setVolume(float left, float right) {
1284 mTrack->setVolume(left, right);
1285}
1286
1287sp<IMemory> AudioFlinger::TrackHandle::getCblk() const {
1288 return mTrack->getCblk();
1289}
1290
1291status_t AudioFlinger::TrackHandle::onTransact(
1292 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1293{
1294 return BnAudioTrack::onTransact(code, data, reply, flags);
1295}
1296
1297// ----------------------------------------------------------------------------
1298
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001299sp<IAudioRecord> AudioFlinger::openRecord(
1300 pid_t pid,
1301 int streamType,
1302 uint32_t sampleRate,
1303 int format,
1304 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001305 int frameCount,
1306 uint32_t flags,
1307 status_t *status)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001308{
1309 sp<AudioRecordThread> thread;
1310 sp<RecordTrack> recordTrack;
1311 sp<RecordHandle> recordHandle;
1312 sp<Client> client;
1313 wp<Client> wclient;
1314 AudioStreamIn* input = 0;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001315 int inFrameCount;
1316 size_t inputBufferSize;
1317 status_t lStatus;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001318
1319 // check calling permissions
1320 if (!recordingAllowed()) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001321 lStatus = PERMISSION_DENIED;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001322 goto Exit;
1323 }
1324
1325 if (uint32_t(streamType) >= AudioRecord::NUM_STREAM_TYPES) {
1326 LOGE("invalid stream type");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001327 lStatus = BAD_VALUE;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001328 goto Exit;
1329 }
1330
1331 if (sampleRate > MAX_SAMPLE_RATE) {
1332 LOGE("Sample rate out of range");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001333 lStatus = BAD_VALUE;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001334 goto Exit;
1335 }
1336
1337 if (mSampleRate == 0) {
1338 LOGE("Audio driver not initialized");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001339 lStatus = NO_INIT;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001340 goto Exit;
1341 }
1342
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001343 if (mAudioRecordThread == 0) {
1344 LOGE("Audio record thread not started");
1345 lStatus = NO_INIT;
1346 goto Exit;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001347 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001348
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001349
1350 // Check that audio input stream accepts requested audio parameters
1351 inputBufferSize = mAudioHardware->getInputBufferSize(sampleRate, format, channelCount);
1352 if (inputBufferSize == 0) {
1353 lStatus = BAD_VALUE;
1354 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 -07001355 goto Exit;
1356 }
1357
1358 // add client to list
1359 {
1360 Mutex::Autolock _l(mLock);
1361 wclient = mClients.valueFor(pid);
1362 if (wclient != NULL) {
1363 client = wclient.promote();
1364 } else {
1365 client = new Client(this, pid);
1366 mClients.add(pid, client);
1367 }
1368 }
1369
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001370 // frameCount must be a multiple of input buffer size
1371 inFrameCount = inputBufferSize/channelCount/sizeof(short);
1372 frameCount = ((frameCount - 1)/inFrameCount + 1) * inFrameCount;
1373
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001374 // create new record track and pass to record thread
1375 recordTrack = new RecordTrack(this, client, streamType, sampleRate,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001376 format, channelCount, frameCount);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001377
1378 // return to handle to client
1379 recordHandle = new RecordHandle(recordTrack);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001380 lStatus = NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001381
1382Exit:
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001383 if (status) {
1384 *status = lStatus;
1385 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001386 return recordHandle;
1387}
1388
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001389status_t AudioFlinger::startRecord(RecordTrack* recordTrack) {
1390 if (mAudioRecordThread != 0) {
1391 return mAudioRecordThread->start(recordTrack);
1392 }
1393 return NO_INIT;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001394}
1395
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001396void AudioFlinger::stopRecord(RecordTrack* recordTrack) {
1397 if (mAudioRecordThread != 0) {
1398 mAudioRecordThread->stop(recordTrack);
1399 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001400}
1401
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001402
1403// ----------------------------------------------------------------------------
1404
1405AudioFlinger::RecordTrack::RecordTrack(
1406 const sp<AudioFlinger>& audioFlinger,
1407 const sp<Client>& client,
1408 int streamType,
1409 uint32_t sampleRate,
1410 int format,
1411 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001412 int frameCount)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001413 : TrackBase(audioFlinger, client, streamType, sampleRate, format,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001414 channelCount, frameCount, 0),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001415 mOverflow(false)
1416{
1417}
1418
1419AudioFlinger::RecordTrack::~RecordTrack()
1420{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001421 mAudioFlinger->audioMixer()->deleteTrackName(mName);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001422}
1423
1424status_t AudioFlinger::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
1425{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001426 audio_track_cblk_t* cblk = this->cblk();
1427 uint32_t framesAvail;
1428 uint32_t framesReq = buffer->frameCount;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001429
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001430 // Check if last stepServer failed, try to step now
1431 if (mFlags & TrackBase::STEPSERVER_FAILED) {
1432 if (!step()) goto getNextBuffer_exit;
1433 LOGV("stepServer recovered");
1434 mFlags &= ~TrackBase::STEPSERVER_FAILED;
1435 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001436
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001437 framesAvail = cblk->framesAvailable_l();
1438
1439 if (LIKELY(framesAvail)) {
1440 uint32_t s = cblk->server;
1441 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
1442
1443 if (framesReq > framesAvail) {
1444 framesReq = framesAvail;
1445 }
1446 if (s + framesReq > bufferEnd) {
1447 framesReq = bufferEnd - s;
1448 }
1449
1450 buffer->raw = getBuffer(s, framesReq);
1451 if (buffer->raw == 0) goto getNextBuffer_exit;
1452
1453 buffer->frameCount = framesReq;
1454 return NO_ERROR;
1455 }
1456
1457getNextBuffer_exit:
1458 buffer->raw = 0;
1459 buffer->frameCount = 0;
1460 return NOT_ENOUGH_DATA;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001461}
1462
1463status_t AudioFlinger::RecordTrack::start()
1464{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001465 return mAudioFlinger->startRecord(this);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001466}
1467
1468void AudioFlinger::RecordTrack::stop()
1469{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001470 mAudioFlinger->stopRecord(this);
1471 TrackBase::reset();
1472 // Force overerrun condition to avoid false overrun callback until first data is
1473 // read from buffer
1474 mCblk->flowControlFlag = 1;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001475}
1476
1477// ----------------------------------------------------------------------------
1478
1479AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::RecordTrack>& recordTrack)
1480 : BnAudioRecord(),
1481 mRecordTrack(recordTrack)
1482{
1483}
1484
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001485AudioFlinger::RecordHandle::~RecordHandle() {
1486 stop();
1487}
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001488
1489status_t AudioFlinger::RecordHandle::start() {
1490 LOGV("RecordHandle::start()");
1491 return mRecordTrack->start();
1492}
1493
1494void AudioFlinger::RecordHandle::stop() {
1495 LOGV("RecordHandle::stop()");
1496 mRecordTrack->stop();
1497}
1498
1499sp<IMemory> AudioFlinger::RecordHandle::getCblk() const {
1500 return mRecordTrack->getCblk();
1501}
1502
1503status_t AudioFlinger::RecordHandle::onTransact(
1504 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1505{
1506 return BnAudioRecord::onTransact(code, data, reply, flags);
1507}
1508
1509// ----------------------------------------------------------------------------
1510
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001511AudioFlinger::AudioRecordThread::AudioRecordThread(AudioHardwareInterface* audioHardware) :
1512 mAudioHardware(audioHardware),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001513 mActive(false)
1514{
1515}
1516
1517AudioFlinger::AudioRecordThread::~AudioRecordThread()
1518{
1519}
1520
1521bool AudioFlinger::AudioRecordThread::threadLoop()
1522{
1523 LOGV("AudioRecordThread: start record loop");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001524 AudioBufferProvider::Buffer buffer;
1525 int inBufferSize = 0;
1526 int inFrameCount = 0;
1527 AudioStreamIn* input = 0;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001528
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001529 mActive = 0;
1530
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001531 // start recording
1532 while (!exitPending()) {
1533 if (!mActive) {
1534 mLock.lock();
1535 if (!mActive && !exitPending()) {
1536 LOGV("AudioRecordThread: loop stopping");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001537 if (input) {
1538 delete input;
1539 input = 0;
1540 }
1541 mRecordTrack.clear();
1542
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001543 mWaitWorkCV.wait(mLock);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001544
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001545 LOGV("AudioRecordThread: loop starting");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001546 if (mRecordTrack != 0) {
1547 input = mAudioHardware->openInputStream(mRecordTrack->format(),
1548 mRecordTrack->channelCount(),
1549 mRecordTrack->sampleRate(),
1550 &mStartStatus);
1551 if (input != 0) {
1552 inBufferSize = input->bufferSize();
1553 inFrameCount = inBufferSize/input->frameSize();
1554 }
1555 } else {
1556 mStartStatus = NO_INIT;
1557 }
1558 if (mStartStatus !=NO_ERROR) {
1559 LOGW("record start failed, status %d", mStartStatus);
1560 mActive = false;
1561 mRecordTrack.clear();
1562 }
1563 mWaitWorkCV.signal();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001564 }
1565 mLock.unlock();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001566 } else if (mRecordTrack != 0){
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001567
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001568 buffer.frameCount = inFrameCount;
1569 if (LIKELY(mRecordTrack->getNextBuffer(&buffer) == NO_ERROR)) {
1570 LOGV("AudioRecordThread read: %d frames", buffer.frameCount);
1571 if (input->read(buffer.raw, inBufferSize) < 0) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001572 LOGE("Error reading audio input");
1573 sleep(1);
1574 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001575 mRecordTrack->releaseBuffer(&buffer);
1576 mRecordTrack->overflow();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001577 }
1578
1579 // client isn't retrieving buffers fast enough
1580 else {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001581 if (!mRecordTrack->setOverflow())
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001582 LOGW("AudioRecordThread: buffer overflow");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001583 // Release the processor for a while before asking for a new buffer.
1584 // This will give the application more chance to read from the buffer and
1585 // clear the overflow.
1586 usleep(5000);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001587 }
1588 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001589 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001590
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001591
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001592 if (input) {
1593 delete input;
1594 }
1595 mRecordTrack.clear();
1596
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001597 return false;
1598}
1599
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001600status_t AudioFlinger::AudioRecordThread::start(RecordTrack* recordTrack)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001601{
1602 LOGV("AudioRecordThread::start");
1603 AutoMutex lock(&mLock);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001604 mActive = true;
1605 // If starting the active track, just reset mActive in case a stop
1606 // was pending and exit
1607 if (recordTrack == mRecordTrack.get()) return NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001608
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001609 if (mRecordTrack != 0) return -EBUSY;
1610
1611 mRecordTrack = recordTrack;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001612
1613 // signal thread to start
1614 LOGV("Signal record thread");
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001615 mWaitWorkCV.signal();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001616 mWaitWorkCV.wait(mLock);
1617 LOGV("Record started, status %d", mStartStatus);
1618 return mStartStatus;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001619}
1620
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001621void AudioFlinger::AudioRecordThread::stop(RecordTrack* recordTrack) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001622 LOGV("AudioRecordThread::stop");
1623 AutoMutex lock(&mLock);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001624 if (mActive && (recordTrack == mRecordTrack.get())) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001625 mActive = false;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001626 }
1627}
1628
1629void AudioFlinger::AudioRecordThread::exit()
1630{
1631 LOGV("AudioRecordThread::exit");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001632 {
1633 AutoMutex lock(&mLock);
1634 requestExit();
1635 mWaitWorkCV.signal();
1636 }
1637 requestExitAndWait();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001638}
1639
1640
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001641status_t AudioFlinger::onTransact(
1642 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1643{
1644 return BnAudioFlinger::onTransact(code, data, reply, flags);
1645}
1646
1647// ----------------------------------------------------------------------------
1648void AudioFlinger::instantiate() {
1649 defaultServiceManager()->addService(
1650 String16("media.audio_flinger"), new AudioFlinger());
1651}
1652
1653}; // namespace android