blob: 51b800c8c31b4c45b7aa1bdd405c1dfb8f8caf79 [file] [log] [blame]
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001/* //device/include/server/AudioFlinger/AudioFlinger.cpp
2**
3** Copyright 2007, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18
19#define LOG_TAG "AudioFlinger"
20//#define LOG_NDEBUG 0
21
22#include <math.h>
23#include <signal.h>
24#include <sys/time.h>
25#include <sys/resource.h>
26
27#include <utils/IServiceManager.h>
28#include <utils/Log.h>
29#include <utils/Parcel.h>
30#include <utils/IPCThreadState.h>
31#include <utils/String16.h>
32#include <utils/threads.h>
33
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -080034#include <cutils/properties.h>
35
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070036#include <media/AudioTrack.h>
37#include <media/AudioRecord.h>
38
39#include <private/media/AudioTrackShared.h>
40
The Android Open Source Project8a7a6752009-01-15 16:12:10 -080041#include <hardware_legacy/AudioHardwareInterface.h>
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070042
43#include "AudioMixer.h"
44#include "AudioFlinger.h"
45
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -080046#ifdef WITH_A2DP
47#include "A2dpAudioInterface.h"
48#endif
49
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070050namespace android {
51
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -080052//static const nsecs_t kStandbyTimeInNsecs = seconds(3);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070053static const unsigned long kBufferRecoveryInUsecs = 2000;
54static const unsigned long kMaxBufferRecoveryInUsecs = 20000;
55static const float MAX_GAIN = 4096.0f;
56
57// retry counts for buffer fill timeout
58// 50 * ~20msecs = 1 second
59static const int8_t kMaxTrackRetries = 50;
60static const int8_t kMaxTrackStartupRetries = 50;
61
62#define AUDIOFLINGER_SECURITY_ENABLED 1
63
64// ----------------------------------------------------------------------------
65
66static bool recordingAllowed() {
67#ifndef HAVE_ANDROID_OS
68 return true;
69#endif
70#if AUDIOFLINGER_SECURITY_ENABLED
71 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
72 bool ok = checkCallingPermission(String16("android.permission.RECORD_AUDIO"));
73 if (!ok) LOGE("Request requires android.permission.RECORD_AUDIO");
74 return ok;
75#else
76 if (!checkCallingPermission(String16("android.permission.RECORD_AUDIO")))
77 LOGW("WARNING: Need to add android.permission.RECORD_AUDIO to manifest");
78 return true;
79#endif
80}
81
82static bool settingsAllowed() {
83#ifndef HAVE_ANDROID_OS
84 return true;
85#endif
86#if AUDIOFLINGER_SECURITY_ENABLED
87 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
88 bool ok = checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS"));
89 if (!ok) LOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS");
90 return ok;
91#else
92 if (!checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS")))
93 LOGW("WARNING: Need to add android.permission.MODIFY_AUDIO_SETTINGS to manifest");
94 return true;
95#endif
96}
97
98// ----------------------------------------------------------------------------
99
100AudioFlinger::AudioFlinger()
101 : BnAudioFlinger(), Thread(false),
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800102 mMasterVolume(0), mMasterMute(true), mHardwareAudioMixer(0), mA2dpAudioMixer(0),
The Android Open Source Project27629322009-01-09 17:51:23 -0800103 mAudioMixer(0), mAudioHardware(0), mA2dpAudioInterface(0), mHardwareOutput(0),
104 mA2dpOutput(0), mOutput(0), mRequestedOutput(0), mAudioRecordThread(0),
105 mSampleRate(0), mFrameCount(0), mChannelCount(0), mFormat(0), mMixBuffer(0),
106 mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mStandby(false),
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{
The Android Open Source Project8a7a6752009-01-15 16:12:10 -0800835 status_t result, result2;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700836 AutoMutex lock(mHardwareLock);
837 mHardwareStatus = AUDIO_SET_PARAMETER;
838 result = mAudioHardware->setParameter(key, value);
The Android Open Source Project8a7a6752009-01-15 16:12:10 -0800839 if (mA2dpAudioInterface) {
840 result2 = mA2dpAudioInterface->setParameter(key, value);
841 if (result2)
842 result = result2;
843 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700844 mHardwareStatus = AUDIO_HW_IDLE;
845 return result;
846}
847
848void AudioFlinger::removeClient(pid_t pid)
849{
850 Mutex::Autolock _l(mLock);
851 mClients.removeItem(pid);
852}
853
854status_t AudioFlinger::addTrack(const sp<Track>& track)
855{
856 Mutex::Autolock _l(mLock);
857
858 // here the track could be either new, or restarted
859 // in both cases "unstop" the track
860 if (track->isPaused()) {
861 track->mState = TrackBase::RESUMING;
862 LOGV("PAUSED => RESUMING (%d)", track->name());
863 } else {
864 track->mState = TrackBase::ACTIVE;
865 LOGV("? => ACTIVE (%d)", track->name());
866 }
867 // set retry count for buffer fill
868 track->mRetryCount = kMaxTrackStartupRetries;
869 LOGV("mWaitWorkCV.broadcast");
870 mWaitWorkCV.broadcast();
871
872 if (mActiveTracks.indexOf(track) < 0) {
873 // the track is newly added, make sure it fills up all its
874 // buffers before playing. This is to ensure the client will
875 // effectively get the latency it requested.
876 track->mFillingUpStatus = Track::FS_FILLING;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800877 track->mResetDone = false;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700878 mActiveTracks.add(track);
879 return NO_ERROR;
880 }
881 return ALREADY_EXISTS;
882}
883
884void AudioFlinger::removeTrack(wp<Track> track, int name)
885{
886 Mutex::Autolock _l(mLock);
887 sp<Track> t = track.promote();
888 if (t!=NULL && (t->mState <= TrackBase::STOPPED)) {
889 remove_track_l(track, name);
890 }
891}
892
893void AudioFlinger::remove_track_l(wp<Track> track, int name)
894{
895 sp<Track> t = track.promote();
896 if (t!=NULL) {
897 t->reset();
898 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800899 audioMixer()->deleteTrackName(name);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700900 mActiveTracks.remove(track);
901 mWaitWorkCV.broadcast();
902}
903
904void AudioFlinger::destroyTrack(const sp<Track>& track)
905{
906 // NOTE: We're acquiring a strong reference on the track before
907 // acquiring the lock, this is to make sure removing it from
908 // mTracks won't cause the destructor to be called while the lock is
909 // held (note that technically, 'track' could be a reference to an item
910 // in mTracks, which is why we need to do this).
911 sp<Track> keep(track);
912 Mutex::Autolock _l(mLock);
913 track->mState = TrackBase::TERMINATED;
914 if (mActiveTracks.indexOf(track) < 0) {
915 LOGV("remove track (%d) and delete from mixer", track->name());
916 mTracks.remove(track);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800917 audioMixer()->deleteTrackName(keep->name());
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700918 }
919}
920
921// ----------------------------------------------------------------------------
922
923AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
924 : RefBase(),
925 mAudioFlinger(audioFlinger),
926 mMemoryDealer(new MemoryDealer(1024*1024)),
927 mPid(pid)
928{
929 // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
930}
931
932AudioFlinger::Client::~Client()
933{
934 mAudioFlinger->removeClient(mPid);
935}
936
937const sp<MemoryDealer>& AudioFlinger::Client::heap() const
938{
939 return mMemoryDealer;
940}
941
942// ----------------------------------------------------------------------------
943
944AudioFlinger::TrackBase::TrackBase(
945 const sp<AudioFlinger>& audioFlinger,
946 const sp<Client>& client,
947 int streamType,
948 uint32_t sampleRate,
949 int format,
950 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800951 int frameCount,
952 const sp<IMemory>& sharedBuffer)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700953 : RefBase(),
954 mAudioFlinger(audioFlinger),
955 mClient(client),
956 mStreamType(streamType),
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800957 mFrameCount(0),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700958 mState(IDLE),
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800959 mClientTid(-1),
960 mFormat(format),
961 mFlags(0)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700962{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800963 mName = audioFlinger->audioMixer()->getTrackName();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700964 if (mName < 0) {
965 LOGE("no more track names availlable");
966 return;
967 }
968
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800969 LOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size());
970
971
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700972 // LOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800973 size_t size = sizeof(audio_track_cblk_t);
974 size_t bufferSize = frameCount*channelCount*sizeof(int16_t);
975 if (sharedBuffer == 0) {
976 size += bufferSize;
977 }
978
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700979 mCblkMemory = client->heap()->allocate(size);
980 if (mCblkMemory != 0) {
981 mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer());
982 if (mCblk) { // construct the shared structure in-place.
983 new(mCblk) audio_track_cblk_t();
984 // clear all buffers
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800985 mCblk->frameCount = frameCount;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700986 mCblk->sampleRate = sampleRate;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800987 mCblk->channels = channelCount;
988 if (sharedBuffer == 0) {
989 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
990 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
991 // Force underrun condition to avoid false underrun callback until first data is
992 // written to buffer
993 mCblk->flowControlFlag = 1;
994 } else {
995 mBuffer = sharedBuffer->pointer();
996 }
997 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700998 }
999 } else {
1000 LOGE("not enough memory for AudioTrack size=%u", size);
1001 client->heap()->dump("AudioTrack");
1002 return;
1003 }
1004}
1005
1006AudioFlinger::TrackBase::~TrackBase()
1007{
1008 mCblk->~audio_track_cblk_t(); // destroy our shared-structure.
1009 mCblkMemory.clear(); // and free the shared memory
1010 mClient.clear();
1011}
1012
1013void AudioFlinger::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
1014{
1015 buffer->raw = 0;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001016 mFrameCount = buffer->frameCount;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001017 step();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001018 buffer->frameCount = 0;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001019}
1020
1021bool AudioFlinger::TrackBase::step() {
1022 bool result;
1023 audio_track_cblk_t* cblk = this->cblk();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001024
1025 result = cblk->stepServer(mFrameCount);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001026 if (!result) {
1027 LOGV("stepServer failed acquiring cblk mutex");
1028 mFlags |= STEPSERVER_FAILED;
1029 }
1030 return result;
1031}
1032
1033void AudioFlinger::TrackBase::reset() {
1034 audio_track_cblk_t* cblk = this->cblk();
1035
1036 cblk->user = 0;
1037 cblk->server = 0;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001038 cblk->userBase = 0;
1039 cblk->serverBase = 0;
1040 mFlags = 0;
1041 LOGV("TrackBase::reset");
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001042}
1043
1044sp<IMemory> AudioFlinger::TrackBase::getCblk() const
1045{
1046 return mCblkMemory;
1047}
1048
1049int AudioFlinger::TrackBase::sampleRate() const {
1050 return mCblk->sampleRate;
1051}
1052
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001053int AudioFlinger::TrackBase::channelCount() const {
1054 return mCblk->channels;
1055}
1056
1057void* AudioFlinger::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
1058 audio_track_cblk_t* cblk = this->cblk();
1059 int16_t *bufferStart = (int16_t *)mBuffer + (offset-cblk->serverBase)*cblk->channels;
1060 int16_t *bufferEnd = bufferStart + frames * cblk->channels;
1061
1062 // Check validity of returned pointer in case the track control block would have been corrupted.
1063 if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd) {
1064 LOGW("TrackBase::getBuffer buffer out of range:\n start: %p, end %p , mBuffer %p mBufferEnd %p\n \
1065 server %d, serverBase %d, user %d, userBase %d",
1066 bufferStart, bufferEnd, mBuffer, mBufferEnd,
1067 cblk->server, cblk->serverBase, cblk->user, cblk->userBase);
1068 return 0;
1069 }
1070
1071 return bufferStart;
1072}
1073
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001074// ----------------------------------------------------------------------------
1075
1076AudioFlinger::Track::Track(
1077 const sp<AudioFlinger>& audioFlinger,
1078 const sp<Client>& client,
1079 int streamType,
1080 uint32_t sampleRate,
1081 int format,
1082 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001083 int frameCount,
1084 const sp<IMemory>& sharedBuffer)
1085 : TrackBase(audioFlinger, client, streamType, sampleRate, format, channelCount, frameCount, sharedBuffer)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001086{
1087 mVolume[0] = 1.0f;
1088 mVolume[1] = 1.0f;
1089 mMute = false;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001090 mSharedBuffer = sharedBuffer;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001091}
1092
1093AudioFlinger::Track::~Track()
1094{
1095 wp<Track> weak(this); // never create a strong ref from the dtor
1096 mState = TERMINATED;
1097 mAudioFlinger->removeTrack(weak, mName);
1098}
1099
1100void AudioFlinger::Track::destroy()
1101{
1102 mAudioFlinger->destroyTrack(this);
1103}
1104
1105void AudioFlinger::Track::dump(char* buffer, size_t size)
1106{
1107 snprintf(buffer, size, " %5d %5d %3u %3u %3u %3u %1d %1d %1d %5u %5u %5u %04x %04x\n",
1108 mName - AudioMixer::TRACK0,
1109 mClient->pid(),
1110 mStreamType,
1111 mFormat,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001112 mCblk->channels,
1113 mFrameCount,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001114 mState,
1115 mMute,
1116 mFillingUpStatus,
1117 mCblk->sampleRate,
1118 mCblk->volume[0],
1119 mCblk->volume[1],
1120 mCblk->server,
1121 mCblk->user);
1122}
1123
1124status_t AudioFlinger::Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
1125{
1126 audio_track_cblk_t* cblk = this->cblk();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001127 uint32_t framesReady;
1128 uint32_t framesReq = buffer->frameCount;
1129
1130 // Check if last stepServer failed, try to step now
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001131 if (mFlags & TrackBase::STEPSERVER_FAILED) {
1132 if (!step()) goto getNextBuffer_exit;
1133 LOGV("stepServer recovered");
1134 mFlags &= ~TrackBase::STEPSERVER_FAILED;
1135 }
1136
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001137 framesReady = cblk->framesReady();
1138
1139 if (LIKELY(framesReady)) {
1140 uint32_t s = cblk->server;
1141 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
1142
1143 bufferEnd = (cblk->loopEnd < bufferEnd) ? cblk->loopEnd : bufferEnd;
1144 if (framesReq > framesReady) {
1145 framesReq = framesReady;
1146 }
1147 if (s + framesReq > bufferEnd) {
1148 framesReq = bufferEnd - s;
1149 }
1150
1151 buffer->raw = getBuffer(s, framesReq);
1152 if (buffer->raw == 0) goto getNextBuffer_exit;
1153
1154 buffer->frameCount = framesReq;
1155 return NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001156 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001157
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001158getNextBuffer_exit:
1159 buffer->raw = 0;
1160 buffer->frameCount = 0;
1161 return NOT_ENOUGH_DATA;
1162}
1163
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001164bool AudioFlinger::Track::isReady() const {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001165 if (mFillingUpStatus != FS_FILLING) return true;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001166
1167 if (mCblk->framesReady() >= mCblk->frameCount ||
1168 mCblk->forceReady) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001169 mFillingUpStatus = FS_FILLED;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001170 mCblk->forceReady = 0;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001171 return true;
1172 }
1173 return false;
1174}
1175
1176status_t AudioFlinger::Track::start()
1177{
1178 LOGV("start(%d)", mName);
1179 mAudioFlinger->addTrack(this);
1180 return NO_ERROR;
1181}
1182
1183void AudioFlinger::Track::stop()
1184{
1185 LOGV("stop(%d)", mName);
1186 Mutex::Autolock _l(mAudioFlinger->mLock);
1187 if (mState > STOPPED) {
1188 mState = STOPPED;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001189 // If the track is not active (PAUSED and buffers full), flush buffers
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001190 if (mAudioFlinger->mActiveTracks.indexOf(this) < 0) {
1191 reset();
1192 }
1193 LOGV("(> STOPPED) => STOPPED (%d)", mName);
1194 }
1195}
1196
1197void AudioFlinger::Track::pause()
1198{
1199 LOGV("pause(%d)", mName);
1200 Mutex::Autolock _l(mAudioFlinger->mLock);
1201 if (mState == ACTIVE || mState == RESUMING) {
1202 mState = PAUSING;
1203 LOGV("ACTIVE/RESUMING => PAUSING (%d)", mName);
1204 }
1205}
1206
1207void AudioFlinger::Track::flush()
1208{
1209 LOGV("flush(%d)", mName);
1210 Mutex::Autolock _l(mAudioFlinger->mLock);
1211 if (mState != STOPPED && mState != PAUSED && mState != PAUSING) {
1212 return;
1213 }
1214 // No point remaining in PAUSED state after a flush => go to
1215 // STOPPED state
1216 mState = STOPPED;
1217
1218 // NOTE: reset() will reset cblk->user and cblk->server with
1219 // the risk that at the same time, the AudioMixer is trying to read
1220 // data. In this case, getNextBuffer() would return a NULL pointer
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001221 // as audio buffer => the AudioMixer code MUST always test that pointer
1222 // returned by getNextBuffer() is not NULL!
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001223 reset();
1224}
1225
1226void AudioFlinger::Track::reset()
1227{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001228 // Do not reset twice to avoid discarding data written just after a flush and before
1229 // the audioflinger thread detects the track is stopped.
1230 if (!mResetDone) {
1231 TrackBase::reset();
1232 // Force underrun condition to avoid false underrun callback until first data is
1233 // written to buffer
1234 mCblk->flowControlFlag = 1;
1235 mCblk->forceReady = 0;
1236 mFillingUpStatus = FS_FILLING;
1237 mResetDone = true;
1238 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001239}
1240
1241void AudioFlinger::Track::mute(bool muted)
1242{
1243 mMute = muted;
1244}
1245
1246void AudioFlinger::Track::setVolume(float left, float right)
1247{
1248 mVolume[0] = left;
1249 mVolume[1] = right;
1250}
1251
1252// ----------------------------------------------------------------------------
1253
1254AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::Track>& track)
1255 : BnAudioTrack(),
1256 mTrack(track)
1257{
1258}
1259
1260AudioFlinger::TrackHandle::~TrackHandle() {
1261 // just stop the track on deletion, associated resources
1262 // will be freed from the main thread once all pending buffers have
1263 // been played. Unless it's not in the active track list, in which
1264 // case we free everything now...
1265 mTrack->destroy();
1266}
1267
1268status_t AudioFlinger::TrackHandle::start() {
1269 return mTrack->start();
1270}
1271
1272void AudioFlinger::TrackHandle::stop() {
1273 mTrack->stop();
1274}
1275
1276void AudioFlinger::TrackHandle::flush() {
1277 mTrack->flush();
1278}
1279
1280void AudioFlinger::TrackHandle::mute(bool e) {
1281 mTrack->mute(e);
1282}
1283
1284void AudioFlinger::TrackHandle::pause() {
1285 mTrack->pause();
1286}
1287
1288void AudioFlinger::TrackHandle::setVolume(float left, float right) {
1289 mTrack->setVolume(left, right);
1290}
1291
1292sp<IMemory> AudioFlinger::TrackHandle::getCblk() const {
1293 return mTrack->getCblk();
1294}
1295
1296status_t AudioFlinger::TrackHandle::onTransact(
1297 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1298{
1299 return BnAudioTrack::onTransact(code, data, reply, flags);
1300}
1301
1302// ----------------------------------------------------------------------------
1303
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001304sp<IAudioRecord> AudioFlinger::openRecord(
1305 pid_t pid,
1306 int streamType,
1307 uint32_t sampleRate,
1308 int format,
1309 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001310 int frameCount,
1311 uint32_t flags,
1312 status_t *status)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001313{
1314 sp<AudioRecordThread> thread;
1315 sp<RecordTrack> recordTrack;
1316 sp<RecordHandle> recordHandle;
1317 sp<Client> client;
1318 wp<Client> wclient;
1319 AudioStreamIn* input = 0;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001320 int inFrameCount;
1321 size_t inputBufferSize;
1322 status_t lStatus;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001323
1324 // check calling permissions
1325 if (!recordingAllowed()) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001326 lStatus = PERMISSION_DENIED;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001327 goto Exit;
1328 }
1329
1330 if (uint32_t(streamType) >= AudioRecord::NUM_STREAM_TYPES) {
1331 LOGE("invalid stream type");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001332 lStatus = BAD_VALUE;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001333 goto Exit;
1334 }
1335
1336 if (sampleRate > MAX_SAMPLE_RATE) {
1337 LOGE("Sample rate out of range");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001338 lStatus = BAD_VALUE;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001339 goto Exit;
1340 }
1341
1342 if (mSampleRate == 0) {
1343 LOGE("Audio driver not initialized");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001344 lStatus = NO_INIT;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001345 goto Exit;
1346 }
1347
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001348 if (mAudioRecordThread == 0) {
1349 LOGE("Audio record thread not started");
1350 lStatus = NO_INIT;
1351 goto Exit;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001352 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001353
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001354
1355 // Check that audio input stream accepts requested audio parameters
1356 inputBufferSize = mAudioHardware->getInputBufferSize(sampleRate, format, channelCount);
1357 if (inputBufferSize == 0) {
1358 lStatus = BAD_VALUE;
1359 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 -07001360 goto Exit;
1361 }
1362
1363 // add client to list
1364 {
1365 Mutex::Autolock _l(mLock);
1366 wclient = mClients.valueFor(pid);
1367 if (wclient != NULL) {
1368 client = wclient.promote();
1369 } else {
1370 client = new Client(this, pid);
1371 mClients.add(pid, client);
1372 }
1373 }
1374
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001375 // frameCount must be a multiple of input buffer size
1376 inFrameCount = inputBufferSize/channelCount/sizeof(short);
1377 frameCount = ((frameCount - 1)/inFrameCount + 1) * inFrameCount;
1378
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001379 // create new record track and pass to record thread
1380 recordTrack = new RecordTrack(this, client, streamType, sampleRate,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001381 format, channelCount, frameCount);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001382
1383 // return to handle to client
1384 recordHandle = new RecordHandle(recordTrack);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001385 lStatus = NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001386
1387Exit:
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001388 if (status) {
1389 *status = lStatus;
1390 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001391 return recordHandle;
1392}
1393
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001394status_t AudioFlinger::startRecord(RecordTrack* recordTrack) {
1395 if (mAudioRecordThread != 0) {
1396 return mAudioRecordThread->start(recordTrack);
1397 }
1398 return NO_INIT;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001399}
1400
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001401void AudioFlinger::stopRecord(RecordTrack* recordTrack) {
1402 if (mAudioRecordThread != 0) {
1403 mAudioRecordThread->stop(recordTrack);
1404 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001405}
1406
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001407
1408// ----------------------------------------------------------------------------
1409
1410AudioFlinger::RecordTrack::RecordTrack(
1411 const sp<AudioFlinger>& audioFlinger,
1412 const sp<Client>& client,
1413 int streamType,
1414 uint32_t sampleRate,
1415 int format,
1416 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001417 int frameCount)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001418 : TrackBase(audioFlinger, client, streamType, sampleRate, format,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001419 channelCount, frameCount, 0),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001420 mOverflow(false)
1421{
1422}
1423
1424AudioFlinger::RecordTrack::~RecordTrack()
1425{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001426 mAudioFlinger->audioMixer()->deleteTrackName(mName);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001427}
1428
1429status_t AudioFlinger::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
1430{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001431 audio_track_cblk_t* cblk = this->cblk();
1432 uint32_t framesAvail;
1433 uint32_t framesReq = buffer->frameCount;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001434
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001435 // Check if last stepServer failed, try to step now
1436 if (mFlags & TrackBase::STEPSERVER_FAILED) {
1437 if (!step()) goto getNextBuffer_exit;
1438 LOGV("stepServer recovered");
1439 mFlags &= ~TrackBase::STEPSERVER_FAILED;
1440 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001441
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001442 framesAvail = cblk->framesAvailable_l();
1443
1444 if (LIKELY(framesAvail)) {
1445 uint32_t s = cblk->server;
1446 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
1447
1448 if (framesReq > framesAvail) {
1449 framesReq = framesAvail;
1450 }
1451 if (s + framesReq > bufferEnd) {
1452 framesReq = bufferEnd - s;
1453 }
1454
1455 buffer->raw = getBuffer(s, framesReq);
1456 if (buffer->raw == 0) goto getNextBuffer_exit;
1457
1458 buffer->frameCount = framesReq;
1459 return NO_ERROR;
1460 }
1461
1462getNextBuffer_exit:
1463 buffer->raw = 0;
1464 buffer->frameCount = 0;
1465 return NOT_ENOUGH_DATA;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001466}
1467
1468status_t AudioFlinger::RecordTrack::start()
1469{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001470 return mAudioFlinger->startRecord(this);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001471}
1472
1473void AudioFlinger::RecordTrack::stop()
1474{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001475 mAudioFlinger->stopRecord(this);
1476 TrackBase::reset();
1477 // Force overerrun condition to avoid false overrun callback until first data is
1478 // read from buffer
1479 mCblk->flowControlFlag = 1;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001480}
1481
1482// ----------------------------------------------------------------------------
1483
1484AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::RecordTrack>& recordTrack)
1485 : BnAudioRecord(),
1486 mRecordTrack(recordTrack)
1487{
1488}
1489
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001490AudioFlinger::RecordHandle::~RecordHandle() {
1491 stop();
1492}
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001493
1494status_t AudioFlinger::RecordHandle::start() {
1495 LOGV("RecordHandle::start()");
1496 return mRecordTrack->start();
1497}
1498
1499void AudioFlinger::RecordHandle::stop() {
1500 LOGV("RecordHandle::stop()");
1501 mRecordTrack->stop();
1502}
1503
1504sp<IMemory> AudioFlinger::RecordHandle::getCblk() const {
1505 return mRecordTrack->getCblk();
1506}
1507
1508status_t AudioFlinger::RecordHandle::onTransact(
1509 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1510{
1511 return BnAudioRecord::onTransact(code, data, reply, flags);
1512}
1513
1514// ----------------------------------------------------------------------------
1515
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001516AudioFlinger::AudioRecordThread::AudioRecordThread(AudioHardwareInterface* audioHardware) :
1517 mAudioHardware(audioHardware),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001518 mActive(false)
1519{
1520}
1521
1522AudioFlinger::AudioRecordThread::~AudioRecordThread()
1523{
1524}
1525
1526bool AudioFlinger::AudioRecordThread::threadLoop()
1527{
1528 LOGV("AudioRecordThread: start record loop");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001529 AudioBufferProvider::Buffer buffer;
1530 int inBufferSize = 0;
1531 int inFrameCount = 0;
1532 AudioStreamIn* input = 0;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001533
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001534 mActive = 0;
1535
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001536 // start recording
1537 while (!exitPending()) {
1538 if (!mActive) {
1539 mLock.lock();
1540 if (!mActive && !exitPending()) {
1541 LOGV("AudioRecordThread: loop stopping");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001542 if (input) {
1543 delete input;
1544 input = 0;
1545 }
1546 mRecordTrack.clear();
1547
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001548 mWaitWorkCV.wait(mLock);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001549
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001550 LOGV("AudioRecordThread: loop starting");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001551 if (mRecordTrack != 0) {
1552 input = mAudioHardware->openInputStream(mRecordTrack->format(),
1553 mRecordTrack->channelCount(),
1554 mRecordTrack->sampleRate(),
1555 &mStartStatus);
1556 if (input != 0) {
1557 inBufferSize = input->bufferSize();
1558 inFrameCount = inBufferSize/input->frameSize();
1559 }
1560 } else {
1561 mStartStatus = NO_INIT;
1562 }
1563 if (mStartStatus !=NO_ERROR) {
1564 LOGW("record start failed, status %d", mStartStatus);
1565 mActive = false;
1566 mRecordTrack.clear();
1567 }
1568 mWaitWorkCV.signal();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001569 }
1570 mLock.unlock();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001571 } else if (mRecordTrack != 0){
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001572
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001573 buffer.frameCount = inFrameCount;
1574 if (LIKELY(mRecordTrack->getNextBuffer(&buffer) == NO_ERROR)) {
1575 LOGV("AudioRecordThread read: %d frames", buffer.frameCount);
1576 if (input->read(buffer.raw, inBufferSize) < 0) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001577 LOGE("Error reading audio input");
1578 sleep(1);
1579 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001580 mRecordTrack->releaseBuffer(&buffer);
1581 mRecordTrack->overflow();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001582 }
1583
1584 // client isn't retrieving buffers fast enough
1585 else {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001586 if (!mRecordTrack->setOverflow())
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001587 LOGW("AudioRecordThread: buffer overflow");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001588 // Release the processor for a while before asking for a new buffer.
1589 // This will give the application more chance to read from the buffer and
1590 // clear the overflow.
1591 usleep(5000);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001592 }
1593 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001594 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001595
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001596
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001597 if (input) {
1598 delete input;
1599 }
1600 mRecordTrack.clear();
1601
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001602 return false;
1603}
1604
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001605status_t AudioFlinger::AudioRecordThread::start(RecordTrack* recordTrack)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001606{
1607 LOGV("AudioRecordThread::start");
1608 AutoMutex lock(&mLock);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001609 mActive = true;
1610 // If starting the active track, just reset mActive in case a stop
1611 // was pending and exit
1612 if (recordTrack == mRecordTrack.get()) return NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001613
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001614 if (mRecordTrack != 0) return -EBUSY;
1615
1616 mRecordTrack = recordTrack;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001617
1618 // signal thread to start
1619 LOGV("Signal record thread");
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001620 mWaitWorkCV.signal();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001621 mWaitWorkCV.wait(mLock);
1622 LOGV("Record started, status %d", mStartStatus);
1623 return mStartStatus;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001624}
1625
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001626void AudioFlinger::AudioRecordThread::stop(RecordTrack* recordTrack) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001627 LOGV("AudioRecordThread::stop");
1628 AutoMutex lock(&mLock);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001629 if (mActive && (recordTrack == mRecordTrack.get())) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001630 mActive = false;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001631 }
1632}
1633
1634void AudioFlinger::AudioRecordThread::exit()
1635{
1636 LOGV("AudioRecordThread::exit");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001637 {
1638 AutoMutex lock(&mLock);
1639 requestExit();
1640 mWaitWorkCV.signal();
1641 }
1642 requestExitAndWait();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001643}
1644
1645
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001646status_t AudioFlinger::onTransact(
1647 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1648{
1649 return BnAudioFlinger::onTransact(code, data, reply, flags);
1650}
1651
1652// ----------------------------------------------------------------------------
1653void AudioFlinger::instantiate() {
1654 defaultServiceManager()->addService(
1655 String16("media.audio_flinger"), new AudioFlinger());
1656}
1657
1658}; // namespace android