blob: d347f14caeeeae9392bd584bd71f6e678160b56c [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 Projectac65e0b2009-02-13 12:57:50 -080050// ----------------------------------------------------------------------------
51// the sim build doesn't have gettid
52
53#ifndef HAVE_GETTID
54# define gettid getpid
55#endif
56
57// ----------------------------------------------------------------------------
58
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070059namespace android {
60
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -080061//static const nsecs_t kStandbyTimeInNsecs = seconds(3);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070062static const unsigned long kBufferRecoveryInUsecs = 2000;
63static const unsigned long kMaxBufferRecoveryInUsecs = 20000;
64static const float MAX_GAIN = 4096.0f;
65
66// retry counts for buffer fill timeout
67// 50 * ~20msecs = 1 second
68static const int8_t kMaxTrackRetries = 50;
69static const int8_t kMaxTrackStartupRetries = 50;
70
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -080071static const int kStartSleepTime = 30000;
72static const int kStopSleepTime = 30000;
73
74// Maximum number of pending buffers allocated by OutputTrack::write()
75static const uint8_t kMaxOutputTrackBuffers = 5;
76
77
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070078#define AUDIOFLINGER_SECURITY_ENABLED 1
79
80// ----------------------------------------------------------------------------
81
82static bool recordingAllowed() {
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.RECORD_AUDIO"));
89 if (!ok) LOGE("Request requires android.permission.RECORD_AUDIO");
90 return ok;
91#else
92 if (!checkCallingPermission(String16("android.permission.RECORD_AUDIO")))
93 LOGW("WARNING: Need to add android.permission.RECORD_AUDIO to manifest");
94 return true;
95#endif
96}
97
98static bool settingsAllowed() {
99#ifndef HAVE_ANDROID_OS
100 return true;
101#endif
102#if AUDIOFLINGER_SECURITY_ENABLED
103 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
104 bool ok = checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS"));
105 if (!ok) LOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS");
106 return ok;
107#else
108 if (!checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS")))
109 LOGW("WARNING: Need to add android.permission.MODIFY_AUDIO_SETTINGS to manifest");
110 return true;
111#endif
112}
113
114// ----------------------------------------------------------------------------
115
116AudioFlinger::AudioFlinger()
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800117 : BnAudioFlinger(),
118 mAudioHardware(0), mA2dpAudioInterface(0),
119 mA2dpEnabled(false), mA2dpEnabledReq(false),
120 mForcedSpeakerCount(0), mForcedRoute(0), mRouteRestoreTime(0), mMusicMuteSaved(false)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700121{
122 mHardwareStatus = AUDIO_HW_IDLE;
123 mAudioHardware = AudioHardwareInterface::create();
124 mHardwareStatus = AUDIO_HW_INIT;
125 if (mAudioHardware->initCheck() == NO_ERROR) {
126 // open 16-bit output stream for s/w mixer
127 mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800128 status_t status;
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800129 AudioStreamOut *hwOutput = mAudioHardware->openOutputStream(AudioSystem::PCM_16_BIT, 0, 0, &status);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700130 mHardwareStatus = AUDIO_HW_IDLE;
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800131 if (hwOutput) {
132 mHardwareMixerThread = new MixerThread(this, hwOutput, AudioSystem::AUDIO_OUTPUT_HARDWARE);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700133 } else {
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800134 LOGE("Failed to initialize hardware output stream, status: %d", status);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700135 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800136
137#ifdef WITH_A2DP
138 // Create A2DP interface
139 mA2dpAudioInterface = new A2dpAudioInterface();
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800140 AudioStreamOut *a2dpOutput = mA2dpAudioInterface->openOutputStream(AudioSystem::PCM_16_BIT, 0, 0, &status);
141 if (a2dpOutput) {
142 mA2dpMixerThread = new MixerThread(this, a2dpOutput, AudioSystem::AUDIO_OUTPUT_A2DP);
143 if (hwOutput) {
144 uint32_t frameCount = ((a2dpOutput->bufferSize()/a2dpOutput->frameSize()) * hwOutput->sampleRate()) / a2dpOutput->sampleRate();
145 MixerThread::OutputTrack *a2dpOutTrack = new MixerThread::OutputTrack(mA2dpMixerThread,
146 hwOutput->sampleRate(),
147 AudioSystem::PCM_16_BIT,
148 hwOutput->channelCount(),
149 frameCount);
150 mHardwareMixerThread->setOuputTrack(a2dpOutTrack);
151 }
152 } else {
153 LOGE("Failed to initialize A2DP output stream, status: %d", status);
154 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800155#endif
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800156
157 // FIXME - this should come from settings
158 setRouting(AudioSystem::MODE_NORMAL, AudioSystem::ROUTE_SPEAKER, AudioSystem::ROUTE_ALL);
159 setRouting(AudioSystem::MODE_RINGTONE, AudioSystem::ROUTE_SPEAKER, AudioSystem::ROUTE_ALL);
160 setRouting(AudioSystem::MODE_IN_CALL, AudioSystem::ROUTE_EARPIECE, AudioSystem::ROUTE_ALL);
161 setMode(AudioSystem::MODE_NORMAL);
162
163 setMasterVolume(1.0f);
164 setMasterMute(false);
165
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800166 // Start record thread
167 mAudioRecordThread = new AudioRecordThread(mAudioHardware);
168 if (mAudioRecordThread != 0) {
169 mAudioRecordThread->run("AudioRecordThread", PRIORITY_URGENT_AUDIO);
170 }
171 } else {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700172 LOGE("Couldn't even initialize the stubbed audio hardware!");
173 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800174
175 char value[PROPERTY_VALUE_MAX];
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800176 property_get("ro.audio.silent", value, "0");
177 if (atoi(value)) {
178 LOGD("Silence is golden");
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800179 setMasterMute(true);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800180 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700181}
182
183AudioFlinger::~AudioFlinger()
184{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800185 if (mAudioRecordThread != 0) {
186 mAudioRecordThread->exit();
187 mAudioRecordThread.clear();
188 }
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800189 mHardwareMixerThread.clear();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700190 delete mAudioHardware;
The Android Open Source Project27629322009-01-09 17:51:23 -0800191 // deleting mA2dpAudioInterface also deletes mA2dpOutput;
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800192#ifdef WITH_A2DP
193 mA2dpMixerThread.clear();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800194 delete mA2dpAudioInterface;
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800195#endif
The Android Open Source Project27629322009-01-09 17:51:23 -0800196}
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800197
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700198
The Android Open Source Projecte41dd752009-01-22 00:13:42 -0800199#ifdef WITH_A2DP
The Android Open Source Projecte41dd752009-01-22 00:13:42 -0800200void AudioFlinger::setA2dpEnabled(bool enable)
201{
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800202 LOGV_IF(enable, "set output to A2DP\n");
203 LOGV_IF(!enable, "set output to hardware audio\n");
204
205 mA2dpEnabledReq = enable;
206 mA2dpMixerThread->wakeUp();
The Android Open Source Projecte41dd752009-01-22 00:13:42 -0800207}
208#endif // WITH_A2DP
209
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800210bool AudioFlinger::streamForcedToSpeaker(int streamType)
211{
212 // NOTE that streams listed here must not be routed to A2DP by default:
213 // AudioSystem::routedToA2dpOutput(streamType) == false
214 return (streamType == AudioSystem::RING ||
215 streamType == AudioSystem::ALARM ||
216 streamType == AudioSystem::NOTIFICATION);
217}
218
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700219status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args)
220{
221 const size_t SIZE = 256;
222 char buffer[SIZE];
223 String8 result;
224
225 result.append("Clients:\n");
226 for (size_t i = 0; i < mClients.size(); ++i) {
227 wp<Client> wClient = mClients.valueAt(i);
228 if (wClient != 0) {
229 sp<Client> client = wClient.promote();
230 if (client != 0) {
231 snprintf(buffer, SIZE, " pid: %d\n", client->pid());
232 result.append(buffer);
233 }
234 }
235 }
236 write(fd, result.string(), result.size());
237 return NO_ERROR;
238}
239
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700240
241status_t AudioFlinger::dumpInternals(int fd, const Vector<String16>& args)
242{
243 const size_t SIZE = 256;
244 char buffer[SIZE];
245 String8 result;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800246
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700247 snprintf(buffer, SIZE, "Hardware status: %d\n", mHardwareStatus);
248 result.append(buffer);
249 write(fd, result.string(), result.size());
250 return NO_ERROR;
251}
252
253status_t AudioFlinger::dumpPermissionDenial(int fd, const Vector<String16>& args)
254{
255 const size_t SIZE = 256;
256 char buffer[SIZE];
257 String8 result;
258 snprintf(buffer, SIZE, "Permission Denial: "
259 "can't dump AudioFlinger from pid=%d, uid=%d\n",
260 IPCThreadState::self()->getCallingPid(),
261 IPCThreadState::self()->getCallingUid());
262 result.append(buffer);
263 write(fd, result.string(), result.size());
264 return NO_ERROR;
265}
266
267status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
268{
269 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
270 dumpPermissionDenial(fd, args);
271 } else {
272 AutoMutex lock(&mLock);
273
274 dumpClients(fd, args);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700275 dumpInternals(fd, args);
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800276 mHardwareMixerThread->dump(fd, args);
277#ifdef WITH_A2DP
278 mA2dpMixerThread->dump(fd, args);
279#endif
280
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700281 if (mAudioHardware) {
282 mAudioHardware->dumpState(fd, args);
283 }
284 }
285 return NO_ERROR;
286}
287
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700288// IAudioFlinger interface
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800289
290
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700291sp<IAudioTrack> AudioFlinger::createTrack(
292 pid_t pid,
293 int streamType,
294 uint32_t sampleRate,
295 int format,
296 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800297 int frameCount,
298 uint32_t flags,
299 const sp<IMemory>& sharedBuffer,
300 status_t *status)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700301{
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800302 sp<MixerThread::Track> track;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700303 sp<TrackHandle> trackHandle;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700304 sp<Client> client;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800305 wp<Client> wclient;
306 status_t lStatus;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700307
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800308 if (streamType >= AudioSystem::NUM_STREAM_TYPES) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800309 LOGE("invalid stream type");
310 lStatus = BAD_VALUE;
311 goto Exit;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700312 }
313
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800314 {
315 Mutex::Autolock _l(mLock);
316
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800317 wclient = mClients.valueFor(pid);
318
319 if (wclient != NULL) {
320 client = wclient.promote();
321 } else {
322 client = new Client(this, pid);
323 mClients.add(pid, client);
324 }
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800325#ifdef WITH_A2DP
326 if (isA2dpEnabled() && AudioSystem::routedToA2dpOutput(streamType)) {
327 track = mA2dpMixerThread->createTrack(client, streamType, sampleRate, format,
328 channelCount, frameCount, sharedBuffer, &lStatus);
329 } else
330#endif
331 {
332 track = mHardwareMixerThread->createTrack(client, streamType, sampleRate, format,
333 channelCount, frameCount, sharedBuffer, &lStatus);
334 }
335 if (track != NULL) {
336 trackHandle = new TrackHandle(track);
337 lStatus = NO_ERROR;
338 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800339 }
340
341Exit:
342 if(status) {
343 *status = lStatus;
344 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700345 return trackHandle;
346}
347
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800348uint32_t AudioFlinger::sampleRate(int output) const
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700349{
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800350#ifdef WITH_A2DP
351 if (output == AudioSystem::AUDIO_OUTPUT_A2DP) {
352 return mA2dpMixerThread->sampleRate();
353 }
354#endif
355 return mHardwareMixerThread->sampleRate();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700356}
357
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800358int AudioFlinger::channelCount(int output) const
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700359{
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800360#ifdef WITH_A2DP
361 if (output == AudioSystem::AUDIO_OUTPUT_A2DP) {
362 return mA2dpMixerThread->channelCount();
363 }
364#endif
365 return mHardwareMixerThread->channelCount();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700366}
367
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800368int AudioFlinger::format(int output) const
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700369{
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800370#ifdef WITH_A2DP
371 if (output == AudioSystem::AUDIO_OUTPUT_A2DP) {
372 return mA2dpMixerThread->format();
373 }
374#endif
375 return mHardwareMixerThread->format();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700376}
377
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800378size_t AudioFlinger::frameCount(int output) const
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700379{
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800380#ifdef WITH_A2DP
381 if (output == AudioSystem::AUDIO_OUTPUT_A2DP) {
382 return mA2dpMixerThread->frameCount();
383 }
384#endif
385 return mHardwareMixerThread->frameCount();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700386}
387
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800388uint32_t AudioFlinger::latency(int output) const
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800389{
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800390#ifdef WITH_A2DP
391 if (output == AudioSystem::AUDIO_OUTPUT_A2DP) {
392 return mA2dpMixerThread->latency();
393 }
394#endif
395 return mHardwareMixerThread->latency();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800396}
397
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700398status_t AudioFlinger::setMasterVolume(float value)
399{
400 // check calling permissions
401 if (!settingsAllowed()) {
402 return PERMISSION_DENIED;
403 }
404
405 // when hw supports master volume, don't scale in sw mixer
406 AutoMutex lock(mHardwareLock);
407 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
408 if (mAudioHardware->setMasterVolume(value) == NO_ERROR) {
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800409 value = 1.0f;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700410 }
411 mHardwareStatus = AUDIO_HW_IDLE;
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800412 mHardwareMixerThread->setMasterVolume(value);
413#ifdef WITH_A2DP
414 mA2dpMixerThread->setMasterVolume(value);
415#endif
416
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700417 return NO_ERROR;
418}
419
420status_t AudioFlinger::setRouting(int mode, uint32_t routes, uint32_t mask)
421{
The Android Open Source Project27629322009-01-09 17:51:23 -0800422 status_t err = NO_ERROR;
423
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700424 // check calling permissions
425 if (!settingsAllowed()) {
426 return PERMISSION_DENIED;
427 }
428 if ((mode < AudioSystem::MODE_CURRENT) || (mode >= AudioSystem::NUM_MODES)) {
429 LOGW("Illegal value: setRouting(%d, %u, %u)", mode, routes, mask);
430 return BAD_VALUE;
431 }
432
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800433#ifdef WITH_A2DP
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800434 LOGD("setRouting %d %d %d, tid %d, calling tid %d\n", mode, routes, mask, gettid(), IPCThreadState::self()->getCallingPid());
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800435 if (mode == AudioSystem::MODE_NORMAL &&
436 (mask & AudioSystem::ROUTE_BLUETOOTH_A2DP)) {
The Android Open Source Projecte41dd752009-01-22 00:13:42 -0800437 AutoMutex lock(&mLock);
438
439 bool enableA2dp = false;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800440 if (routes & AudioSystem::ROUTE_BLUETOOTH_A2DP) {
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800441 enableA2dp = true;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800442 }
The Android Open Source Projecte41dd752009-01-22 00:13:42 -0800443 setA2dpEnabled(enableA2dp);
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800444 LOGV("setOutput done\n");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800445 }
446#endif
447
The Android Open Source Project27629322009-01-09 17:51:23 -0800448 // do nothing if only A2DP routing is affected
449 mask &= ~AudioSystem::ROUTE_BLUETOOTH_A2DP;
450 if (mask) {
451 AutoMutex lock(mHardwareLock);
452 mHardwareStatus = AUDIO_HW_GET_ROUTING;
453 uint32_t r;
454 err = mAudioHardware->getRouting(mode, &r);
455 if (err == NO_ERROR) {
456 r = (r & ~mask) | (routes & mask);
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800457 if (mode == AudioSystem::MODE_NORMAL ||
458 (mode == AudioSystem::MODE_CURRENT && getMode() == AudioSystem::MODE_NORMAL)) {
459 mSavedRoute = r;
460 r |= mForcedRoute;
461 LOGV("setRouting mSavedRoute %08x mForcedRoute %08x\n", mSavedRoute, mForcedRoute);
462 }
The Android Open Source Project27629322009-01-09 17:51:23 -0800463 mHardwareStatus = AUDIO_HW_SET_ROUTING;
464 err = mAudioHardware->setRouting(mode, r);
465 }
466 mHardwareStatus = AUDIO_HW_IDLE;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700467 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700468 return err;
469}
470
471uint32_t AudioFlinger::getRouting(int mode) const
472{
473 uint32_t routes = 0;
474 if ((mode >= AudioSystem::MODE_CURRENT) && (mode < AudioSystem::NUM_MODES)) {
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800475 if (mode == AudioSystem::MODE_NORMAL ||
476 (mode == AudioSystem::MODE_CURRENT && getMode() == AudioSystem::MODE_NORMAL)) {
477 routes = mSavedRoute;
478 } else {
479 mHardwareStatus = AUDIO_HW_GET_ROUTING;
480 mAudioHardware->getRouting(mode, &routes);
481 mHardwareStatus = AUDIO_HW_IDLE;
482 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700483 } else {
484 LOGW("Illegal value: getRouting(%d)", mode);
485 }
486 return routes;
487}
488
489status_t AudioFlinger::setMode(int mode)
490{
491 // check calling permissions
492 if (!settingsAllowed()) {
493 return PERMISSION_DENIED;
494 }
495 if ((mode < 0) || (mode >= AudioSystem::NUM_MODES)) {
496 LOGW("Illegal value: setMode(%d)", mode);
497 return BAD_VALUE;
498 }
499
500 AutoMutex lock(mHardwareLock);
501 mHardwareStatus = AUDIO_HW_SET_MODE;
502 status_t ret = mAudioHardware->setMode(mode);
503 mHardwareStatus = AUDIO_HW_IDLE;
504 return ret;
505}
506
507int AudioFlinger::getMode() const
508{
509 int mode = AudioSystem::MODE_INVALID;
510 mHardwareStatus = AUDIO_HW_SET_MODE;
511 mAudioHardware->getMode(&mode);
512 mHardwareStatus = AUDIO_HW_IDLE;
513 return mode;
514}
515
516status_t AudioFlinger::setMicMute(bool state)
517{
518 // check calling permissions
519 if (!settingsAllowed()) {
520 return PERMISSION_DENIED;
521 }
522
523 AutoMutex lock(mHardwareLock);
524 mHardwareStatus = AUDIO_HW_SET_MIC_MUTE;
525 status_t ret = mAudioHardware->setMicMute(state);
526 mHardwareStatus = AUDIO_HW_IDLE;
527 return ret;
528}
529
530bool AudioFlinger::getMicMute() const
531{
532 bool state = AudioSystem::MODE_INVALID;
533 mHardwareStatus = AUDIO_HW_GET_MIC_MUTE;
534 mAudioHardware->getMicMute(&state);
535 mHardwareStatus = AUDIO_HW_IDLE;
536 return state;
537}
538
539status_t AudioFlinger::setMasterMute(bool muted)
540{
541 // check calling permissions
542 if (!settingsAllowed()) {
543 return PERMISSION_DENIED;
544 }
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800545 mHardwareMixerThread->setMasterMute(muted);
546#ifdef WITH_A2DP
547 mA2dpMixerThread->setMasterMute(muted);
548#endif
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700549 return NO_ERROR;
550}
551
552float AudioFlinger::masterVolume() const
553{
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800554 return mHardwareMixerThread->masterVolume();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700555}
556
557bool AudioFlinger::masterMute() const
558{
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800559 return mHardwareMixerThread->masterMute();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700560}
561
562status_t AudioFlinger::setStreamVolume(int stream, float value)
563{
564 // check calling permissions
565 if (!settingsAllowed()) {
566 return PERMISSION_DENIED;
567 }
568
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800569 if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700570 return BAD_VALUE;
571 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800572
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800573 mHardwareMixerThread->setStreamVolume(stream, value);
574#ifdef WITH_A2DP
575 mA2dpMixerThread->setStreamVolume(stream, value);
576#endif
577
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700578 status_t ret = NO_ERROR;
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800579 if (stream == AudioSystem::VOICE_CALL ||
580 stream == AudioSystem::BLUETOOTH_SCO) {
581
582 if (stream == AudioSystem::VOICE_CALL) {
583 value = (float)AudioSystem::logToLinear(value)/100.0f;
584 } else { // (type == AudioSystem::BLUETOOTH_SCO)
585 value = 1.0f;
586 }
587
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700588 AutoMutex lock(mHardwareLock);
589 mHardwareStatus = AUDIO_SET_VOICE_VOLUME;
590 ret = mAudioHardware->setVoiceVolume(value);
591 mHardwareStatus = AUDIO_HW_IDLE;
592 }
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800593
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700594 return ret;
595}
596
597status_t AudioFlinger::setStreamMute(int stream, bool muted)
598{
599 // check calling permissions
600 if (!settingsAllowed()) {
601 return PERMISSION_DENIED;
602 }
603
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800604 if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700605 return BAD_VALUE;
606 }
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800607
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800608#ifdef WITH_A2DP
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800609 mA2dpMixerThread->setStreamMute(stream, muted);
610#endif
611 if (stream == AudioSystem::MUSIC)
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800612 {
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800613 AutoMutex lock(&mHardwareLock);
614 if (mForcedRoute != 0)
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800615 mMusicMuteSaved = muted;
616 else
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800617 mHardwareMixerThread->setStreamMute(stream, muted);
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800618 } else {
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800619 mHardwareMixerThread->setStreamMute(stream, muted);
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800620 }
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800621
622
623
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700624 return NO_ERROR;
625}
626
627float AudioFlinger::streamVolume(int stream) const
628{
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800629 if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700630 return 0.0f;
631 }
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800632 return mHardwareMixerThread->streamVolume(stream);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700633}
634
635bool AudioFlinger::streamMute(int stream) const
636{
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800637 if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700638 return true;
639 }
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800640
641 if (stream == AudioSystem::MUSIC && mForcedRoute != 0)
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800642 {
643 return mMusicMuteSaved;
644 }
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800645 return mHardwareMixerThread->streamMute(stream);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700646}
647
648bool AudioFlinger::isMusicActive() const
649{
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800650 #ifdef WITH_A2DP
651 if (isA2dpEnabled()) {
652 return mA2dpMixerThread->isMusicActive();
653 }
654 #endif
655 return mHardwareMixerThread->isMusicActive();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700656}
657
658status_t AudioFlinger::setParameter(const char* key, const char* value)
659{
The Android Open Source Project8a7a6752009-01-15 16:12:10 -0800660 status_t result, result2;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700661 AutoMutex lock(mHardwareLock);
662 mHardwareStatus = AUDIO_SET_PARAMETER;
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800663
664 LOGV("setParameter() key %s, value %s, tid %d, calling tid %d", key, value, gettid(), IPCThreadState::self()->getCallingPid());
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700665 result = mAudioHardware->setParameter(key, value);
The Android Open Source Project8a7a6752009-01-15 16:12:10 -0800666 if (mA2dpAudioInterface) {
667 result2 = mA2dpAudioInterface->setParameter(key, value);
668 if (result2)
669 result = result2;
670 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700671 mHardwareStatus = AUDIO_HW_IDLE;
672 return result;
673}
674
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800675size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
676{
677 return mAudioHardware->getInputBufferSize(sampleRate, format, channelCount);
678}
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800679
680void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
681{
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800682
683 LOGV("registerClient() %p, tid %d, calling tid %d", client.get(), gettid(), IPCThreadState::self()->getCallingPid());
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800684 Mutex::Autolock _l(mLock);
685
686 sp<IBinder> binder = client->asBinder();
687 if (mNotificationClients.indexOf(binder) < 0) {
688 LOGV("Adding notification client %p", binder.get());
689 binder->linkToDeath(this);
690 mNotificationClients.add(binder);
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800691 client->a2dpEnabledChanged(isA2dpEnabled());
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800692 }
693}
694
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800695void AudioFlinger::binderDied(const wp<IBinder>& who) {
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800696
697 LOGV("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(), IPCThreadState::self()->getCallingPid());
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800698 Mutex::Autolock _l(mLock);
699
700 IBinder *binder = who.unsafe_get();
701
702 if (binder != NULL) {
703 int index = mNotificationClients.indexOf(binder);
704 if (index >= 0) {
705 LOGV("Removing notification client %p", binder);
706 mNotificationClients.removeAt(index);
707 }
708 }
709}
710
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800711void AudioFlinger::handleOutputSwitch()
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800712{
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800713 if (mA2dpEnabled != mA2dpEnabledReq)
714 {
715 Mutex::Autolock _l(mLock);
716
717 if (mA2dpEnabled != mA2dpEnabledReq)
718 {
719 mA2dpEnabled = mA2dpEnabledReq;
720 SortedVector < sp<MixerThread::Track> > tracks;
721 SortedVector < wp<MixerThread::Track> > activeTracks;
722
723 // We hold mA2dpMixerThread mLock already
724 Mutex::Autolock _l(mHardwareMixerThread->mLock);
725
726 // Transfer tracks playing on MUSIC stream from one mixer to the other
727 if (mA2dpEnabled) {
728 mHardwareMixerThread->getTracks(tracks, activeTracks);
729 mA2dpMixerThread->putTracks(tracks, activeTracks);
730 } else {
731 mA2dpMixerThread->getTracks(tracks, activeTracks);
732 mHardwareMixerThread->putTracks(tracks, activeTracks);
733 }
734
735 // Notify AudioSystem of the A2DP activation/deactivation
736 size_t size = mNotificationClients.size();
737 for (size_t i = 0; i < size; i++) {
738 sp<IBinder> binder = mNotificationClients.itemAt(i).promote();
739 if (binder != NULL) {
740 LOGV("Notifying output change to client %p", binder.get());
741 sp<IAudioFlingerClient> client = interface_cast<IAudioFlingerClient> (binder);
742 client->a2dpEnabledChanged(mA2dpEnabled);
743 }
744 }
745
746 mHardwareMixerThread->wakeUp();
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800747 }
748 }
749}
750
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700751void AudioFlinger::removeClient(pid_t pid)
752{
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800753 LOGV("removeClient() pid %d, tid %d, calling tid %d", pid, gettid(), IPCThreadState::self()->getCallingPid());
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700754 Mutex::Autolock _l(mLock);
755 mClients.removeItem(pid);
756}
757
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800758void AudioFlinger::wakeUp()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700759{
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -0800760 mHardwareMixerThread->wakeUp();
761#ifdef WITH_A2DP
762 mA2dpMixerThread->wakeUp();
763#endif // WITH_A2DP
764}
765
766bool AudioFlinger::isA2dpEnabled() const
767{
768 return mA2dpEnabledReq;
769}
770
771void AudioFlinger::handleForcedSpeakerRoute(int command)
772{
773 switch(command) {
774 case ACTIVE_TRACK_ADDED:
775 {
776 AutoMutex lock(mHardwareLock);
777 if (mForcedSpeakerCount++ == 0) {
778 mRouteRestoreTime = 0;
779 mMusicMuteSaved = mHardwareMixerThread->streamMute(AudioSystem::MUSIC);
780 if (mForcedRoute == 0 && !(mSavedRoute & AudioSystem::ROUTE_SPEAKER)) {
781 LOGV("Route forced to Speaker ON %08x", mSavedRoute | AudioSystem::ROUTE_SPEAKER);
782 mHardwareMixerThread->setStreamMute(AudioSystem::MUSIC, true);
783 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
784 mAudioHardware->setMasterVolume(0);
785 usleep(mHardwareMixerThread->latency()*1000);
786 mHardwareStatus = AUDIO_HW_SET_ROUTING;
787 mAudioHardware->setRouting(AudioSystem::MODE_NORMAL, mSavedRoute | AudioSystem::ROUTE_SPEAKER);
788 mHardwareStatus = AUDIO_HW_IDLE;
789 // delay track start so that audio hardware has time to siwtch routes
790 usleep(kStartSleepTime);
791 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
792 mAudioHardware->setMasterVolume(mHardwareMixerThread->masterVolume());
793 mHardwareStatus = AUDIO_HW_IDLE;
794 }
795 mForcedRoute = AudioSystem::ROUTE_SPEAKER;
796 }
797 LOGV("mForcedSpeakerCount incremented to %d", mForcedSpeakerCount);
798 }
799 break;
800 case ACTIVE_TRACK_REMOVED:
801 {
802 AutoMutex lock(mHardwareLock);
803 if (mForcedSpeakerCount > 0){
804 if (--mForcedSpeakerCount == 0) {
805 mRouteRestoreTime = systemTime() + milliseconds(kStopSleepTime/1000);
806 }
807 LOGV("mForcedSpeakerCount decremented to %d", mForcedSpeakerCount);
808 } else {
809 LOGE("mForcedSpeakerCount is already zero");
810 }
811 }
812 break;
813 case CHECK_ROUTE_RESTORE_TIME:
814 case FORCE_ROUTE_RESTORE:
815 if (mRouteRestoreTime) {
816 AutoMutex lock(mHardwareLock);
817 if (mRouteRestoreTime &&
818 (systemTime() > mRouteRestoreTime || command == FORCE_ROUTE_RESTORE)) {
819 mHardwareMixerThread->setStreamMute(AudioSystem::MUSIC, mMusicMuteSaved);
820 mForcedRoute = 0;
821 if (!(mSavedRoute & AudioSystem::ROUTE_SPEAKER)) {
822 mHardwareStatus = AUDIO_HW_SET_ROUTING;
823 mAudioHardware->setRouting(AudioSystem::MODE_NORMAL, mSavedRoute);
824 mHardwareStatus = AUDIO_HW_IDLE;
825 LOGV("Route forced to Speaker OFF %08x", mSavedRoute);
826 }
827 mRouteRestoreTime = 0;
828 }
829 }
830 break;
831 }
832}
833
834
835// ----------------------------------------------------------------------------
836
837AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int outputType)
838 : Thread(false),
839 mAudioFlinger(audioFlinger), mAudioMixer(0), mOutput(output), mOutputType(outputType),
840 mSampleRate(0), mFrameCount(0), mChannelCount(0), mFormat(0), mMixBuffer(0),
841 mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mStandby(false),
842 mInWrite(false)
843{
844 mSampleRate = output->sampleRate();
845 mChannelCount = output->channelCount();
846
847 // FIXME - Current mixer implementation only supports stereo output
848 if (mChannelCount == 1) {
849 LOGE("Invalid audio hardware channel count");
850 }
851
852 mFormat = output->format();
853 mFrameCount = output->bufferSize() / output->channelCount() / sizeof(int16_t);
854 mAudioMixer = new AudioMixer(mFrameCount, output->sampleRate());
855
856 // FIXME - Current mixer implementation only supports stereo output: Always
857 // Allocate a stereo buffer even if HW output is mono.
858 mMixBuffer = new int16_t[mFrameCount * 2];
859 memset(mMixBuffer, 0, mFrameCount * 2 * sizeof(int16_t));
860}
861
862AudioFlinger::MixerThread::~MixerThread()
863{
864 delete [] mMixBuffer;
865 delete mAudioMixer;
866}
867
868status_t AudioFlinger::MixerThread::dump(int fd, const Vector<String16>& args)
869{
870 dumpInternals(fd, args);
871 dumpTracks(fd, args);
872 return NO_ERROR;
873}
874
875status_t AudioFlinger::MixerThread::dumpTracks(int fd, const Vector<String16>& args)
876{
877 const size_t SIZE = 256;
878 char buffer[SIZE];
879 String8 result;
880
881 snprintf(buffer, SIZE, "Output %d mixer thread tracks\n", mOutputType);
882 result.append(buffer);
883 result.append(" Name Clien Typ Fmt Chn Buf S M F SRate LeftV RighV Serv User\n");
884 for (size_t i = 0; i < mTracks.size(); ++i) {
885 wp<Track> wTrack = mTracks[i];
886 if (wTrack != 0) {
887 sp<Track> track = wTrack.promote();
888 if (track != 0) {
889 track->dump(buffer, SIZE);
890 result.append(buffer);
891 }
892 }
893 }
894
895 snprintf(buffer, SIZE, "Output %d mixer thread active tracks\n", mOutputType);
896 result.append(buffer);
897 result.append(" Name Clien Typ Fmt Chn Buf S M F SRate LeftV RighV Serv User\n");
898 for (size_t i = 0; i < mActiveTracks.size(); ++i) {
899 wp<Track> wTrack = mTracks[i];
900 if (wTrack != 0) {
901 sp<Track> track = wTrack.promote();
902 if (track != 0) {
903 track->dump(buffer, SIZE);
904 result.append(buffer);
905 }
906 }
907 }
908 write(fd, result.string(), result.size());
909 return NO_ERROR;
910}
911
912status_t AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>& args)
913{
914 const size_t SIZE = 256;
915 char buffer[SIZE];
916 String8 result;
917
918 snprintf(buffer, SIZE, "Output %d mixer thread internals\n", mOutputType);
919 result.append(buffer);
920 snprintf(buffer, SIZE, "AudioMixer tracks: %08x\n", mAudioMixer->trackNames());
921 result.append(buffer);
922 snprintf(buffer, SIZE, "last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime));
923 result.append(buffer);
924 snprintf(buffer, SIZE, "total writes: %d\n", mNumWrites);
925 result.append(buffer);
926 snprintf(buffer, SIZE, "delayed writes: %d\n", mNumDelayedWrites);
927 result.append(buffer);
928 snprintf(buffer, SIZE, "blocked in write: %d\n", mInWrite);
929 result.append(buffer);
930 snprintf(buffer, SIZE, "standby: %d\n", mStandby);
931 result.append(buffer);
932 write(fd, result.string(), result.size());
933 return NO_ERROR;
934}
935
936// Thread virtuals
937bool AudioFlinger::MixerThread::threadLoop()
938{
939 unsigned long sleepTime = kBufferRecoveryInUsecs;
940 int16_t* curBuf = mMixBuffer;
941 Vector< sp<Track> > tracksToRemove;
942 size_t enabledTracks = 0;
943 nsecs_t standbyTime = systemTime();
944 size_t mixBufferSize = mFrameCount*mChannelCount*sizeof(int16_t);
945 nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 2;
946
947#ifdef WITH_A2DP
948 bool outputTrackActive = false;
949#endif
950
951 do {
952 enabledTracks = 0;
953 { // scope for the mLock
954
955 Mutex::Autolock _l(mLock);
956
957#ifdef WITH_A2DP
958 if (mOutputType == AudioSystem::AUDIO_OUTPUT_A2DP) {
959 mAudioFlinger->handleOutputSwitch();
960 }
961 if (mOutputTrack != NULL && !mAudioFlinger->isA2dpEnabled()) {
962 if (outputTrackActive) {
963 mOutputTrack->stop();
964 outputTrackActive = false;
965 }
966 }
967#endif
968
969 const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
970
971 // put audio hardware into standby after short delay
972 if UNLIKELY(!activeTracks.size() && systemTime() > standbyTime) {
973 // wait until we have something to do...
974 LOGV("Audio hardware entering standby, output %d\n", mOutputType);
975// mAudioFlinger->mHardwareStatus = AUDIO_HW_STANDBY;
976 if (!mStandby) {
977 mOutput->standby();
978 mStandby = true;
979 }
980
981#ifdef WITH_A2DP
982 if (outputTrackActive) {
983 mOutputTrack->stop();
984 outputTrackActive = false;
985 }
986#endif
987 if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) {
988 mAudioFlinger->handleForcedSpeakerRoute(FORCE_ROUTE_RESTORE);
989 }
990// mHardwareStatus = AUDIO_HW_IDLE;
991 // we're about to wait, flush the binder command buffer
992 IPCThreadState::self()->flushCommands();
993 mWaitWorkCV.wait(mLock);
994 LOGV("Audio hardware exiting standby, output %d\n", mOutputType);
995 standbyTime = systemTime() + kStandbyTimeInNsecs;
996 continue;
997 }
998
999 // Forced route to speaker is handled by hardware mixer thread
1000 if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) {
1001 mAudioFlinger->handleForcedSpeakerRoute(CHECK_ROUTE_RESTORE_TIME);
1002 }
1003
1004 // find out which tracks need to be processed
1005 size_t count = activeTracks.size();
1006 for (size_t i=0 ; i<count ; i++) {
1007 sp<Track> t = activeTracks[i].promote();
1008 if (t == 0) continue;
1009
1010 Track* const track = t.get();
1011 audio_track_cblk_t* cblk = track->cblk();
1012
1013 // The first time a track is added we wait
1014 // for all its buffers to be filled before processing it
1015 mAudioMixer->setActiveTrack(track->name());
1016 if (cblk->framesReady() && (track->isReady() || track->isStopped()) &&
1017 !track->isPaused())
1018 {
1019 //LOGV("track %d u=%08x, s=%08x [OK]", track->name(), cblk->user, cblk->server);
1020
1021 // compute volume for this track
1022 int16_t left, right;
1023 if (track->isMuted() || mMasterMute || track->isPausing()) {
1024 left = right = 0;
1025 if (track->isPausing()) {
1026 LOGV("paused(%d)", track->name());
1027 track->setPaused();
1028 }
1029 } else {
1030 float typeVolume = mStreamTypes[track->type()].volume;
1031 float v = mMasterVolume * typeVolume;
1032 float v_clamped = v * cblk->volume[0];
1033 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
1034 left = int16_t(v_clamped);
1035 v_clamped = v * cblk->volume[1];
1036 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
1037 right = int16_t(v_clamped);
1038 }
1039
1040 // XXX: these things DON'T need to be done each time
1041 mAudioMixer->setBufferProvider(track);
1042 mAudioMixer->enable(AudioMixer::MIXING);
1043
1044 int param;
1045 if ( track->mFillingUpStatus == Track::FS_FILLED) {
1046 // no ramp for the first volume setting
1047 track->mFillingUpStatus = Track::FS_ACTIVE;
1048 if (track->mState == TrackBase::RESUMING) {
1049 track->mState = TrackBase::ACTIVE;
1050 param = AudioMixer::RAMP_VOLUME;
1051 } else {
1052 param = AudioMixer::VOLUME;
1053 }
1054 } else {
1055 param = AudioMixer::RAMP_VOLUME;
1056 }
1057 mAudioMixer->setParameter(param, AudioMixer::VOLUME0, left);
1058 mAudioMixer->setParameter(param, AudioMixer::VOLUME1, right);
1059 mAudioMixer->setParameter(
1060 AudioMixer::TRACK,
1061 AudioMixer::FORMAT, track->format());
1062 mAudioMixer->setParameter(
1063 AudioMixer::TRACK,
1064 AudioMixer::CHANNEL_COUNT, track->channelCount());
1065 mAudioMixer->setParameter(
1066 AudioMixer::RESAMPLE,
1067 AudioMixer::SAMPLE_RATE,
1068 int(cblk->sampleRate));
1069
1070 // reset retry count
1071 track->mRetryCount = kMaxTrackRetries;
1072 enabledTracks++;
1073 } else {
1074 //LOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
1075 if (track->isStopped()) {
1076 track->reset();
1077 }
1078 if (track->isTerminated() || track->isStopped() || track->isPaused()) {
1079 // We have consumed all the buffers of this track.
1080 // Remove it from the list of active tracks.
1081 LOGV("remove(%d) from active list", track->name());
1082 tracksToRemove.add(track);
1083 } else {
1084 // No buffers for this track. Give it a few chances to
1085 // fill a buffer, then remove it from active list.
1086 if (--(track->mRetryCount) <= 0) {
1087 LOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
1088 tracksToRemove.add(track);
1089 }
1090 }
1091 // LOGV("disable(%d)", track->name());
1092 mAudioMixer->disable(AudioMixer::MIXING);
1093 }
1094 }
1095
1096 // remove all the tracks that need to be...
1097 count = tracksToRemove.size();
1098 if (UNLIKELY(count)) {
1099 for (size_t i=0 ; i<count ; i++) {
1100 const sp<Track>& track = tracksToRemove[i];
1101 removeActiveTrack(track);
1102 if (track->isTerminated()) {
1103 mTracks.remove(track);
1104 deleteTrackName(track->mName);
1105 }
1106 }
1107 }
1108 }
1109
1110 if (LIKELY(enabledTracks)) {
1111 // mix buffers...
1112 mAudioMixer->process(curBuf);
1113
1114#ifdef WITH_A2DP
1115 if (mOutputTrack != NULL && mAudioFlinger->isA2dpEnabled()) {
1116 if (!outputTrackActive) {
1117 LOGV("starting output track in mixer for output %d", mOutputType);
1118 mOutputTrack->start();
1119 outputTrackActive = true;
1120 }
1121 mOutputTrack->write(curBuf, mFrameCount);
1122 }
1123#endif
1124
1125 // output audio to hardware
1126 mLastWriteTime = systemTime();
1127 mInWrite = true;
1128 mOutput->write(curBuf, mixBufferSize);
1129 mNumWrites++;
1130 mInWrite = false;
1131 mStandby = false;
1132 nsecs_t temp = systemTime();
1133 standbyTime = temp + kStandbyTimeInNsecs;
1134 nsecs_t delta = temp - mLastWriteTime;
1135 if (delta > maxPeriod) {
1136 LOGW("write blocked for %llu msecs", ns2ms(delta));
1137 mNumDelayedWrites++;
1138 }
1139 sleepTime = kBufferRecoveryInUsecs;
1140 } else {
1141#ifdef WITH_A2DP
1142 if (mOutputTrack != NULL && mAudioFlinger->isA2dpEnabled()) {
1143 if (outputTrackActive) {
1144 mOutputTrack->write(curBuf, 0);
1145 if (mOutputTrack->bufferQueueEmpty()) {
1146 mOutputTrack->stop();
1147 outputTrackActive = false;
1148 } else {
1149 standbyTime = systemTime() + kStandbyTimeInNsecs;
1150 }
1151 }
1152 }
1153#endif
1154 // There was nothing to mix this round, which means all
1155 // active tracks were late. Sleep a little bit to give
1156 // them another chance. If we're too late, the audio
1157 // hardware will zero-fill for us.
1158// LOGV("no buffers - usleep(%lu)", sleepTime);
1159 usleep(sleepTime);
1160 if (sleepTime < kMaxBufferRecoveryInUsecs) {
1161 sleepTime += kBufferRecoveryInUsecs;
1162 }
1163 }
1164
1165 // finally let go of all our tracks, without the lock held
1166 // since we can't guarantee the destructors won't acquire that
1167 // same lock.
1168 tracksToRemove.clear();
1169 } while (true);
1170
1171 return false;
1172}
1173
1174status_t AudioFlinger::MixerThread::readyToRun()
1175{
1176 if (mSampleRate == 0) {
1177 LOGE("No working audio driver found.");
1178 return NO_INIT;
1179 }
1180 LOGI("AudioFlinger's thread ready to run for output %d", mOutputType);
1181 return NO_ERROR;
1182}
1183
1184void AudioFlinger::MixerThread::onFirstRef()
1185{
1186 const size_t SIZE = 256;
1187 char buffer[SIZE];
1188
1189 snprintf(buffer, SIZE, "Mixer Thread for output %d", mOutputType);
1190
1191 run(buffer, ANDROID_PRIORITY_URGENT_AUDIO);
1192}
1193
1194
1195sp<AudioFlinger::MixerThread::Track> AudioFlinger::MixerThread::createTrack(
1196 const sp<AudioFlinger::Client>& client,
1197 int streamType,
1198 uint32_t sampleRate,
1199 int format,
1200 int channelCount,
1201 int frameCount,
1202 const sp<IMemory>& sharedBuffer,
1203 status_t *status)
1204{
1205 sp<Track> track;
1206 status_t lStatus;
1207
1208 // Resampler implementation limits input sampling rate to 2 x output sampling rate.
1209 if (sampleRate > MAX_SAMPLE_RATE || sampleRate > mSampleRate*2) {
1210 LOGE("Sample rate out of range: %d mSampleRate %d", sampleRate, mSampleRate);
1211 lStatus = BAD_VALUE;
1212 goto Exit;
1213 }
1214
1215 {
1216 Mutex::Autolock _l(mLock);
1217
1218 if (mSampleRate == 0) {
1219 LOGE("Audio driver not initialized.");
1220 lStatus = NO_INIT;
1221 goto Exit;
1222 }
1223
1224 track = new Track(this, client, streamType, sampleRate, format,
1225 channelCount, frameCount, sharedBuffer);
1226 mTracks.add(track);
1227 lStatus = NO_ERROR;
1228 }
1229
1230Exit:
1231 if(status) {
1232 *status = lStatus;
1233 }
1234 return track;
1235}
1236
1237void AudioFlinger::MixerThread::getTracks(
1238 SortedVector < sp<Track> >& tracks,
1239 SortedVector < wp<Track> >& activeTracks)
1240{
1241 size_t size = mTracks.size();
1242 LOGV ("MixerThread::getTracks() for output %d, mTracks.size %d, mActiveTracks.size %d", mOutputType, mTracks.size(), mActiveTracks.size());
1243 for (size_t i = 0; i < size; i++) {
1244 sp<Track> t = mTracks[i];
1245 if (AudioSystem::routedToA2dpOutput(t->mStreamType)) {
1246 tracks.add(t);
1247 int j = mActiveTracks.indexOf(t);
1248 if (j >= 0) {
1249 t = mActiveTracks[j].promote();
1250 if (t != NULL) {
1251 activeTracks.add(t);
1252 }
1253 }
1254 }
1255 }
1256
1257 size = activeTracks.size();
1258 for (size_t i = 0; i < size; i++) {
1259 removeActiveTrack(activeTracks[i]);
1260 }
1261
1262 size = tracks.size();
1263 for (size_t i = 0; i < size; i++) {
1264 sp<Track> t = tracks[i];
1265 mTracks.remove(t);
1266 deleteTrackName(t->name());
1267 }
1268}
1269
1270void AudioFlinger::MixerThread::putTracks(
1271 SortedVector < sp<Track> >& tracks,
1272 SortedVector < wp<Track> >& activeTracks)
1273{
1274
1275 LOGV ("MixerThread::putTracks() for output %d, tracks.size %d, activeTracks.size %d", mOutputType, tracks.size(), activeTracks.size());
1276
1277 size_t size = tracks.size();
1278 for (size_t i = 0; i < size ; i++) {
1279 sp<Track> t = tracks[i];
1280 int name = getTrackName();
1281
1282 if (name < 0) return;
1283
1284 t->mName = name;
1285 t->mMixerThread = this;
1286 mTracks.add(t);
1287
1288 int j = activeTracks.indexOf(t);
1289 if (j >= 0) {
1290 addActiveTrack(t);
1291 }
1292 }
1293}
1294
1295uint32_t AudioFlinger::MixerThread::sampleRate() const
1296{
1297 return mSampleRate;
1298}
1299
1300int AudioFlinger::MixerThread::channelCount() const
1301{
1302 return mChannelCount;
1303}
1304
1305int AudioFlinger::MixerThread::format() const
1306{
1307 return mFormat;
1308}
1309
1310size_t AudioFlinger::MixerThread::frameCount() const
1311{
1312 return mFrameCount;
1313}
1314
1315uint32_t AudioFlinger::MixerThread::latency() const
1316{
1317 if (mOutput) {
1318 return mOutput->latency();
1319 }
1320 else {
1321 return 0;
1322 }
1323}
1324
1325status_t AudioFlinger::MixerThread::setMasterVolume(float value)
1326{
1327 mMasterVolume = value;
1328 return NO_ERROR;
1329}
1330
1331status_t AudioFlinger::MixerThread::setMasterMute(bool muted)
1332{
1333 mMasterMute = muted;
1334 return NO_ERROR;
1335}
1336
1337float AudioFlinger::MixerThread::masterVolume() const
1338{
1339 return mMasterVolume;
1340}
1341
1342bool AudioFlinger::MixerThread::masterMute() const
1343{
1344 return mMasterMute;
1345}
1346
1347status_t AudioFlinger::MixerThread::setStreamVolume(int stream, float value)
1348{
1349 mStreamTypes[stream].volume = value;
1350 return NO_ERROR;
1351}
1352
1353status_t AudioFlinger::MixerThread::setStreamMute(int stream, bool muted)
1354{
1355 mStreamTypes[stream].mute = muted;
1356 return NO_ERROR;
1357}
1358
1359float AudioFlinger::MixerThread::streamVolume(int stream) const
1360{
1361 return mStreamTypes[stream].volume;
1362}
1363
1364bool AudioFlinger::MixerThread::streamMute(int stream) const
1365{
1366 return mStreamTypes[stream].mute;
1367}
1368
1369bool AudioFlinger::MixerThread::isMusicActive() const
1370{
1371 size_t count = mActiveTracks.size();
1372 for (size_t i = 0 ; i < count ; ++i) {
1373 sp<Track> t = mActiveTracks[i].promote();
1374 if (t == 0) continue;
1375 Track* const track = t.get();
1376 if (t->mStreamType == AudioSystem::MUSIC)
1377 return true;
1378 }
1379 return false;
1380}
1381
1382status_t AudioFlinger::MixerThread::addTrack(const sp<Track>& track)
1383{
1384 status_t status = ALREADY_EXISTS;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001385 Mutex::Autolock _l(mLock);
1386
1387 // here the track could be either new, or restarted
1388 // in both cases "unstop" the track
1389 if (track->isPaused()) {
1390 track->mState = TrackBase::RESUMING;
1391 LOGV("PAUSED => RESUMING (%d)", track->name());
1392 } else {
1393 track->mState = TrackBase::ACTIVE;
1394 LOGV("? => ACTIVE (%d)", track->name());
1395 }
1396 // set retry count for buffer fill
1397 track->mRetryCount = kMaxTrackStartupRetries;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001398 if (mActiveTracks.indexOf(track) < 0) {
1399 // the track is newly added, make sure it fills up all its
1400 // buffers before playing. This is to ensure the client will
1401 // effectively get the latency it requested.
1402 track->mFillingUpStatus = Track::FS_FILLING;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001403 track->mResetDone = false;
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001404 addActiveTrack(track);
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001405 status = NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001406 }
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001407
1408 LOGV("mWaitWorkCV.broadcast");
1409 mWaitWorkCV.broadcast();
1410
1411 return status;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001412}
1413
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001414void AudioFlinger::MixerThread::removeTrack(wp<Track> track, int name)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001415{
1416 Mutex::Autolock _l(mLock);
1417 sp<Track> t = track.promote();
1418 if (t!=NULL && (t->mState <= TrackBase::STOPPED)) {
1419 remove_track_l(track, name);
1420 }
1421}
1422
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001423void AudioFlinger::MixerThread::remove_track_l(wp<Track> track, int name)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001424{
1425 sp<Track> t = track.promote();
1426 if (t!=NULL) {
1427 t->reset();
1428 }
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -08001429 deleteTrackName(name);
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001430 removeActiveTrack(track);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001431 mWaitWorkCV.broadcast();
1432}
1433
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001434void AudioFlinger::MixerThread::destroyTrack(const sp<Track>& track)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001435{
1436 // NOTE: We're acquiring a strong reference on the track before
1437 // acquiring the lock, this is to make sure removing it from
1438 // mTracks won't cause the destructor to be called while the lock is
1439 // held (note that technically, 'track' could be a reference to an item
1440 // in mTracks, which is why we need to do this).
1441 sp<Track> keep(track);
1442 Mutex::Autolock _l(mLock);
1443 track->mState = TrackBase::TERMINATED;
1444 if (mActiveTracks.indexOf(track) < 0) {
1445 LOGV("remove track (%d) and delete from mixer", track->name());
1446 mTracks.remove(track);
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -08001447 deleteTrackName(keep->name());
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001448 }
1449}
1450
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001451
1452void AudioFlinger::MixerThread::addActiveTrack(const wp<Track>& t)
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001453{
1454 mActiveTracks.add(t);
1455
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001456 // Force routing to speaker for certain stream types
1457 // The forced routing to speaker is managed by hardware mixer
1458 if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) {
1459 sp<Track> track = t.promote();
1460 if (track == NULL) return;
1461
1462 if (streamForcedToSpeaker(track->type())) {
1463 mAudioFlinger->handleForcedSpeakerRoute(ACTIVE_TRACK_ADDED);
1464 }
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001465 }
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001466}
1467
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001468void AudioFlinger::MixerThread::removeActiveTrack(const wp<Track>& t)
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001469{
1470 mActiveTracks.remove(t);
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001471
1472 // Force routing to speaker for certain stream types
1473 // The forced routing to speaker is managed by hardware mixer
1474 if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) {
1475 sp<Track> track = t.promote();
1476 if (track == NULL) return;
1477
1478 if (streamForcedToSpeaker(track->type())) {
1479 mAudioFlinger->handleForcedSpeakerRoute(ACTIVE_TRACK_REMOVED);
1480 }
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001481 }
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001482}
1483
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001484int AudioFlinger::MixerThread::getTrackName()
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -08001485{
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001486 return mAudioMixer->getTrackName();
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -08001487}
1488
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001489void AudioFlinger::MixerThread::deleteTrackName(int name)
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -08001490{
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001491 mAudioMixer->deleteTrackName(name);
1492}
1493
1494size_t AudioFlinger::MixerThread::getOutputFrameCount()
1495{
1496 return mOutput->bufferSize() / mOutput->channelCount() / sizeof(int16_t);
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -08001497}
1498
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001499// ----------------------------------------------------------------------------
1500
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001501AudioFlinger::MixerThread::TrackBase::TrackBase(
1502 const sp<MixerThread>& mixerThread,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001503 const sp<Client>& client,
1504 int streamType,
1505 uint32_t sampleRate,
1506 int format,
1507 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001508 int frameCount,
1509 const sp<IMemory>& sharedBuffer)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001510 : RefBase(),
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001511 mMixerThread(mixerThread),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001512 mClient(client),
1513 mStreamType(streamType),
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001514 mFrameCount(0),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001515 mState(IDLE),
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001516 mClientTid(-1),
1517 mFormat(format),
1518 mFlags(0)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001519{
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001520 mName = mixerThread->getTrackName();
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -08001521 LOGV("TrackBase contructor name %d, calling thread %d", mName, IPCThreadState::self()->getCallingPid());
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001522 if (mName < 0) {
1523 LOGE("no more track names availlable");
1524 return;
1525 }
1526
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001527 LOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size());
1528
1529
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001530 // LOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001531 size_t size = sizeof(audio_track_cblk_t);
1532 size_t bufferSize = frameCount*channelCount*sizeof(int16_t);
1533 if (sharedBuffer == 0) {
1534 size += bufferSize;
1535 }
1536
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001537 if (client != NULL) {
1538 mCblkMemory = client->heap()->allocate(size);
1539 if (mCblkMemory != 0) {
1540 mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer());
1541 if (mCblk) { // construct the shared structure in-place.
1542 new(mCblk) audio_track_cblk_t();
1543 // clear all buffers
1544 mCblk->frameCount = frameCount;
1545 mCblk->sampleRate = sampleRate;
1546 mCblk->channels = channelCount;
1547 if (sharedBuffer == 0) {
1548 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
1549 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
1550 // Force underrun condition to avoid false underrun callback until first data is
1551 // written to buffer
1552 mCblk->flowControlFlag = 1;
1553 } else {
1554 mBuffer = sharedBuffer->pointer();
1555 }
1556 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001557 }
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001558 } else {
1559 LOGE("not enough memory for AudioTrack size=%u", size);
1560 client->heap()->dump("AudioTrack");
1561 return;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001562 }
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001563 } else {
1564 mCblk = (audio_track_cblk_t *)(new uint8_t[size]);
1565 if (mCblk) { // construct the shared structure in-place.
1566 new(mCblk) audio_track_cblk_t();
1567 // clear all buffers
1568 mCblk->frameCount = frameCount;
1569 mCblk->sampleRate = sampleRate;
1570 mCblk->channels = channelCount;
1571 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
1572 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
1573 // Force underrun condition to avoid false underrun callback until first data is
1574 // written to buffer
1575 mCblk->flowControlFlag = 1;
1576 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
1577 }
1578 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001579}
1580
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001581AudioFlinger::MixerThread::TrackBase::~TrackBase()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001582{
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001583 if (mCblk) {
1584 mCblk->~audio_track_cblk_t(); // destroy our shared-structure.
1585 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001586 mCblkMemory.clear(); // and free the shared memory
1587 mClient.clear();
1588}
1589
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001590void AudioFlinger::MixerThread::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001591{
1592 buffer->raw = 0;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001593 mFrameCount = buffer->frameCount;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001594 step();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001595 buffer->frameCount = 0;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001596}
1597
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001598bool AudioFlinger::MixerThread::TrackBase::step() {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001599 bool result;
1600 audio_track_cblk_t* cblk = this->cblk();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001601
1602 result = cblk->stepServer(mFrameCount);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001603 if (!result) {
1604 LOGV("stepServer failed acquiring cblk mutex");
1605 mFlags |= STEPSERVER_FAILED;
1606 }
1607 return result;
1608}
1609
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001610void AudioFlinger::MixerThread::TrackBase::reset() {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001611 audio_track_cblk_t* cblk = this->cblk();
1612
1613 cblk->user = 0;
1614 cblk->server = 0;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001615 cblk->userBase = 0;
1616 cblk->serverBase = 0;
1617 mFlags = 0;
1618 LOGV("TrackBase::reset");
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001619}
1620
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001621sp<IMemory> AudioFlinger::MixerThread::TrackBase::getCblk() const
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001622{
1623 return mCblkMemory;
1624}
1625
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001626int AudioFlinger::MixerThread::TrackBase::sampleRate() const {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001627 return mCblk->sampleRate;
1628}
1629
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001630int AudioFlinger::MixerThread::TrackBase::channelCount() const {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001631 return mCblk->channels;
1632}
1633
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001634void* AudioFlinger::MixerThread::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001635 audio_track_cblk_t* cblk = this->cblk();
1636 int16_t *bufferStart = (int16_t *)mBuffer + (offset-cblk->serverBase)*cblk->channels;
1637 int16_t *bufferEnd = bufferStart + frames * cblk->channels;
1638
1639 // Check validity of returned pointer in case the track control block would have been corrupted.
1640 if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd) {
1641 LOGW("TrackBase::getBuffer buffer out of range:\n start: %p, end %p , mBuffer %p mBufferEnd %p\n \
1642 server %d, serverBase %d, user %d, userBase %d",
1643 bufferStart, bufferEnd, mBuffer, mBufferEnd,
1644 cblk->server, cblk->serverBase, cblk->user, cblk->userBase);
1645 return 0;
1646 }
1647
1648 return bufferStart;
1649}
1650
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001651// ----------------------------------------------------------------------------
1652
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001653AudioFlinger::MixerThread::Track::Track(
1654 const sp<MixerThread>& mixerThread,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001655 const sp<Client>& client,
1656 int streamType,
1657 uint32_t sampleRate,
1658 int format,
1659 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001660 int frameCount,
1661 const sp<IMemory>& sharedBuffer)
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001662 : TrackBase(mixerThread, client, streamType, sampleRate, format, channelCount, frameCount, sharedBuffer)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001663{
1664 mVolume[0] = 1.0f;
1665 mVolume[1] = 1.0f;
1666 mMute = false;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001667 mSharedBuffer = sharedBuffer;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001668}
1669
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001670AudioFlinger::MixerThread::Track::~Track()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001671{
1672 wp<Track> weak(this); // never create a strong ref from the dtor
1673 mState = TERMINATED;
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001674 mMixerThread->removeTrack(weak, mName);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001675}
1676
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001677void AudioFlinger::MixerThread::Track::destroy()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001678{
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001679 mMixerThread->destroyTrack(this);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001680}
1681
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001682void AudioFlinger::MixerThread::Track::dump(char* buffer, size_t size)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001683{
1684 snprintf(buffer, size, " %5d %5d %3u %3u %3u %3u %1d %1d %1d %5u %5u %5u %04x %04x\n",
1685 mName - AudioMixer::TRACK0,
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001686 (mClient == NULL) ? getpid() : mClient->pid(),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001687 mStreamType,
1688 mFormat,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001689 mCblk->channels,
1690 mFrameCount,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001691 mState,
1692 mMute,
1693 mFillingUpStatus,
1694 mCblk->sampleRate,
1695 mCblk->volume[0],
1696 mCblk->volume[1],
1697 mCblk->server,
1698 mCblk->user);
1699}
1700
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001701status_t AudioFlinger::MixerThread::Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001702{
1703 audio_track_cblk_t* cblk = this->cblk();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001704 uint32_t framesReady;
1705 uint32_t framesReq = buffer->frameCount;
1706
1707 // Check if last stepServer failed, try to step now
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001708 if (mFlags & TrackBase::STEPSERVER_FAILED) {
1709 if (!step()) goto getNextBuffer_exit;
1710 LOGV("stepServer recovered");
1711 mFlags &= ~TrackBase::STEPSERVER_FAILED;
1712 }
1713
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001714 framesReady = cblk->framesReady();
1715
1716 if (LIKELY(framesReady)) {
1717 uint32_t s = cblk->server;
1718 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
1719
1720 bufferEnd = (cblk->loopEnd < bufferEnd) ? cblk->loopEnd : bufferEnd;
1721 if (framesReq > framesReady) {
1722 framesReq = framesReady;
1723 }
1724 if (s + framesReq > bufferEnd) {
1725 framesReq = bufferEnd - s;
1726 }
1727
1728 buffer->raw = getBuffer(s, framesReq);
1729 if (buffer->raw == 0) goto getNextBuffer_exit;
1730
1731 buffer->frameCount = framesReq;
1732 return NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001733 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001734
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001735getNextBuffer_exit:
1736 buffer->raw = 0;
1737 buffer->frameCount = 0;
1738 return NOT_ENOUGH_DATA;
1739}
1740
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001741bool AudioFlinger::MixerThread::Track::isReady() const {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001742 if (mFillingUpStatus != FS_FILLING) return true;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001743
1744 if (mCblk->framesReady() >= mCblk->frameCount ||
1745 mCblk->forceReady) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001746 mFillingUpStatus = FS_FILLED;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001747 mCblk->forceReady = 0;
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001748 LOGV("Track::isReady() track %d for output %d", mName, mMixerThread->mOutputType);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001749 return true;
1750 }
1751 return false;
1752}
1753
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001754status_t AudioFlinger::MixerThread::Track::start()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001755{
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001756 LOGV("start(%d), calling thread %d for output %d", mName, IPCThreadState::self()->getCallingPid(), mMixerThread->mOutputType);
1757 mMixerThread->addTrack(this);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001758 return NO_ERROR;
1759}
1760
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001761void AudioFlinger::MixerThread::Track::stop()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001762{
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001763 LOGV("stop(%d), calling thread %d for output %d", mName, IPCThreadState::self()->getCallingPid(), mMixerThread->mOutputType);
1764 Mutex::Autolock _l(mMixerThread->mLock);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001765 if (mState > STOPPED) {
1766 mState = STOPPED;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001767 // If the track is not active (PAUSED and buffers full), flush buffers
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001768 if (mMixerThread->mActiveTracks.indexOf(this) < 0) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001769 reset();
1770 }
1771 LOGV("(> STOPPED) => STOPPED (%d)", mName);
1772 }
1773}
1774
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001775void AudioFlinger::MixerThread::Track::pause()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001776{
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -08001777 LOGV("pause(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001778 Mutex::Autolock _l(mMixerThread->mLock);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001779 if (mState == ACTIVE || mState == RESUMING) {
1780 mState = PAUSING;
1781 LOGV("ACTIVE/RESUMING => PAUSING (%d)", mName);
1782 }
1783}
1784
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001785void AudioFlinger::MixerThread::Track::flush()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001786{
1787 LOGV("flush(%d)", mName);
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001788 Mutex::Autolock _l(mMixerThread->mLock);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001789 if (mState != STOPPED && mState != PAUSED && mState != PAUSING) {
1790 return;
1791 }
1792 // No point remaining in PAUSED state after a flush => go to
1793 // STOPPED state
1794 mState = STOPPED;
1795
1796 // NOTE: reset() will reset cblk->user and cblk->server with
1797 // the risk that at the same time, the AudioMixer is trying to read
1798 // data. In this case, getNextBuffer() would return a NULL pointer
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001799 // as audio buffer => the AudioMixer code MUST always test that pointer
1800 // returned by getNextBuffer() is not NULL!
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001801 reset();
1802}
1803
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001804void AudioFlinger::MixerThread::Track::reset()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001805{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001806 // Do not reset twice to avoid discarding data written just after a flush and before
1807 // the audioflinger thread detects the track is stopped.
1808 if (!mResetDone) {
1809 TrackBase::reset();
1810 // Force underrun condition to avoid false underrun callback until first data is
1811 // written to buffer
1812 mCblk->flowControlFlag = 1;
1813 mCblk->forceReady = 0;
1814 mFillingUpStatus = FS_FILLING;
1815 mResetDone = true;
1816 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001817}
1818
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001819void AudioFlinger::MixerThread::Track::mute(bool muted)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001820{
1821 mMute = muted;
1822}
1823
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001824void AudioFlinger::MixerThread::Track::setVolume(float left, float right)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001825{
1826 mVolume[0] = left;
1827 mVolume[1] = right;
1828}
1829
1830// ----------------------------------------------------------------------------
1831
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08001832AudioFlinger::MixerThread::RecordTrack::RecordTrack(
1833 const sp<MixerThread>& mixerThread,
1834 const sp<Client>& client,
1835 int streamType,
1836 uint32_t sampleRate,
1837 int format,
1838 int channelCount,
1839 int frameCount)
1840 : TrackBase(mixerThread, client, streamType, sampleRate, format,
1841 channelCount, frameCount, 0),
1842 mOverflow(false)
1843{
1844}
1845
1846AudioFlinger::MixerThread::RecordTrack::~RecordTrack()
1847{
1848 mMixerThread->deleteTrackName(mName);
1849}
1850
1851status_t AudioFlinger::MixerThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
1852{
1853 audio_track_cblk_t* cblk = this->cblk();
1854 uint32_t framesAvail;
1855 uint32_t framesReq = buffer->frameCount;
1856
1857 // Check if last stepServer failed, try to step now
1858 if (mFlags & TrackBase::STEPSERVER_FAILED) {
1859 if (!step()) goto getNextBuffer_exit;
1860 LOGV("stepServer recovered");
1861 mFlags &= ~TrackBase::STEPSERVER_FAILED;
1862 }
1863
1864 framesAvail = cblk->framesAvailable_l();
1865
1866 if (LIKELY(framesAvail)) {
1867 uint32_t s = cblk->server;
1868 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
1869
1870 if (framesReq > framesAvail) {
1871 framesReq = framesAvail;
1872 }
1873 if (s + framesReq > bufferEnd) {
1874 framesReq = bufferEnd - s;
1875 }
1876
1877 buffer->raw = getBuffer(s, framesReq);
1878 if (buffer->raw == 0) goto getNextBuffer_exit;
1879
1880 buffer->frameCount = framesReq;
1881 return NO_ERROR;
1882 }
1883
1884getNextBuffer_exit:
1885 buffer->raw = 0;
1886 buffer->frameCount = 0;
1887 return NOT_ENOUGH_DATA;
1888}
1889
1890status_t AudioFlinger::MixerThread::RecordTrack::start()
1891{
1892 return mMixerThread->mAudioFlinger->startRecord(this);
1893}
1894
1895void AudioFlinger::MixerThread::RecordTrack::stop()
1896{
1897 mMixerThread->mAudioFlinger->stopRecord(this);
1898 TrackBase::reset();
1899 // Force overerrun condition to avoid false overrun callback until first data is
1900 // read from buffer
1901 mCblk->flowControlFlag = 1;
1902}
1903
1904
1905// ----------------------------------------------------------------------------
1906
1907AudioFlinger::MixerThread::OutputTrack::OutputTrack(
1908 const sp<MixerThread>& mixerThread,
1909 uint32_t sampleRate,
1910 int format,
1911 int channelCount,
1912 int frameCount)
1913 : Track(mixerThread, NULL, AudioSystem::SYSTEM, sampleRate, format, channelCount, frameCount, NULL),
1914 mOutputMixerThread(mixerThread)
1915{
1916
1917 mCblk->out = 1;
1918 mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
1919 mCblk->volume[0] = mCblk->volume[1] = 0x1000;
1920 mOutBuffer.frameCount = 0;
1921 mCblk->bufferTimeoutMs = 10;
1922
1923 LOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, mCblk->frameCount %d, mCblk->sampleRate %d, mCblk->channels %d mBufferEnd %p",
1924 mCblk, mBuffer, mCblk->buffers, mCblk->frameCount, mCblk->sampleRate, mCblk->channels, mBufferEnd);
1925
1926}
1927
1928AudioFlinger::MixerThread::OutputTrack::~OutputTrack()
1929{
1930 stop();
1931}
1932
1933status_t AudioFlinger::MixerThread::OutputTrack::start()
1934{
1935 status_t status = Track::start();
1936
1937 mRetryCount = 127;
1938 return status;
1939}
1940
1941void AudioFlinger::MixerThread::OutputTrack::stop()
1942{
1943 Track::stop();
1944 clearBufferQueue();
1945 mOutBuffer.frameCount = 0;
1946}
1947
1948void AudioFlinger::MixerThread::OutputTrack::write(int16_t* data, uint32_t frames)
1949{
1950 Buffer *pInBuffer;
1951 Buffer inBuffer;
1952 uint32_t channels = mCblk->channels;
1953
1954 inBuffer.frameCount = frames;
1955 inBuffer.i16 = data;
1956
1957 if (mCblk->user == 0) {
1958 if (mOutputMixerThread->isMusicActive()) {
1959 mCblk->forceReady = 1;
1960 LOGV("OutputTrack::start() force ready");
1961 } else if (mCblk->frameCount > frames){
1962 if (mBufferQueue.size() < kMaxOutputTrackBuffers) {
1963 uint32_t startFrames = (mCblk->frameCount - frames);
1964 LOGV("OutputTrack::start() write %d frames", startFrames);
1965 pInBuffer = new Buffer;
1966 pInBuffer->mBuffer = new int16_t[startFrames * channels];
1967 pInBuffer->frameCount = startFrames;
1968 pInBuffer->i16 = pInBuffer->mBuffer;
1969 memset(pInBuffer->raw, 0, startFrames * channels * sizeof(int16_t));
1970 mBufferQueue.add(pInBuffer);
1971 } else {
1972 LOGW ("OutputTrack::write() no more buffers");
1973 }
1974 }
1975 }
1976
1977 while (1) {
1978 // First write pending buffers, then new data
1979 if (mBufferQueue.size()) {
1980 pInBuffer = mBufferQueue.itemAt(0);
1981 } else {
1982 pInBuffer = &inBuffer;
1983 }
1984
1985 if (pInBuffer->frameCount == 0) {
1986 break;
1987 }
1988
1989 if (mOutBuffer.frameCount == 0) {
1990 mOutBuffer.frameCount = pInBuffer->frameCount;
1991 if (obtainBuffer(&mOutBuffer) == (status_t)AudioTrack::NO_MORE_BUFFERS) {
1992 break;
1993 }
1994 }
1995
1996 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount : pInBuffer->frameCount;
1997 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * channels * sizeof(int16_t));
1998 mCblk->stepUser(outFrames);
1999 pInBuffer->frameCount -= outFrames;
2000 pInBuffer->i16 += outFrames * channels;
2001 mOutBuffer.frameCount -= outFrames;
2002 mOutBuffer.i16 += outFrames * channels;
2003
2004 if (pInBuffer->frameCount == 0) {
2005 if (mBufferQueue.size()) {
2006 mBufferQueue.removeAt(0);
2007 delete [] pInBuffer->mBuffer;
2008 delete pInBuffer;
2009 } else {
2010 break;
2011 }
2012 }
2013 }
2014
2015 // If we could not write all frames, allocate a buffer and queue it for next time.
2016 if (inBuffer.frameCount) {
2017 if (mBufferQueue.size() < kMaxOutputTrackBuffers) {
2018 pInBuffer = new Buffer;
2019 pInBuffer->mBuffer = new int16_t[inBuffer.frameCount * channels];
2020 pInBuffer->frameCount = inBuffer.frameCount;
2021 pInBuffer->i16 = pInBuffer->mBuffer;
2022 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * channels * sizeof(int16_t));
2023 mBufferQueue.add(pInBuffer);
2024 } else {
2025 LOGW("OutputTrack::write() no more buffers");
2026 }
2027 }
2028
2029 // Calling write() with a 0 length buffer, means that no more data will be written:
2030 // If no more buffers are pending, fill output track buffer to make sure it is started
2031 // by output mixer.
2032 if (frames == 0 && mBufferQueue.size() == 0 && mCblk->user < mCblk->frameCount) {
2033 frames = mCblk->frameCount - mCblk->user;
2034 pInBuffer = new Buffer;
2035 pInBuffer->mBuffer = new int16_t[frames * channels];
2036 pInBuffer->frameCount = frames;
2037 pInBuffer->i16 = pInBuffer->mBuffer;
2038 memset(pInBuffer->raw, 0, frames * channels * sizeof(int16_t));
2039 mBufferQueue.add(pInBuffer);
2040 }
2041
2042}
2043
2044status_t AudioFlinger::MixerThread::OutputTrack::obtainBuffer(AudioBufferProvider::Buffer* buffer)
2045{
2046 int active;
2047 int timeout = 0;
2048 status_t result;
2049 audio_track_cblk_t* cblk = mCblk;
2050 uint32_t framesReq = buffer->frameCount;
2051
2052 LOGV("OutputTrack::obtainBuffer user %d, server %d", cblk->user, cblk->server);
2053 buffer->frameCount = 0;
2054
2055 uint32_t framesAvail = cblk->framesAvailable();
2056
2057 if (framesAvail == 0) {
2058 return AudioTrack::NO_MORE_BUFFERS;
2059 }
2060
2061 if (framesReq > framesAvail) {
2062 framesReq = framesAvail;
2063 }
2064
2065 uint32_t u = cblk->user;
2066 uint32_t bufferEnd = cblk->userBase + cblk->frameCount;
2067
2068 if (u + framesReq > bufferEnd) {
2069 framesReq = bufferEnd - u;
2070 }
2071
2072 buffer->frameCount = framesReq;
2073 buffer->raw = (void *)cblk->buffer(u);
2074 return NO_ERROR;
2075}
2076
2077
2078void AudioFlinger::MixerThread::OutputTrack::clearBufferQueue()
2079{
2080 size_t size = mBufferQueue.size();
2081 Buffer *pBuffer;
2082
2083 for (size_t i = 0; i < size; i++) {
2084 pBuffer = mBufferQueue.itemAt(i);
2085 delete [] pBuffer->mBuffer;
2086 delete pBuffer;
2087 }
2088 mBufferQueue.clear();
2089}
2090
2091// ----------------------------------------------------------------------------
2092
2093AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
2094 : RefBase(),
2095 mAudioFlinger(audioFlinger),
2096 mMemoryDealer(new MemoryDealer(1024*1024)),
2097 mPid(pid)
2098{
2099 // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
2100}
2101
2102AudioFlinger::Client::~Client()
2103{
2104 mAudioFlinger->removeClient(mPid);
2105}
2106
2107const sp<MemoryDealer>& AudioFlinger::Client::heap() const
2108{
2109 return mMemoryDealer;
2110}
2111
2112// ----------------------------------------------------------------------------
2113
2114AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::MixerThread::Track>& track)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002115 : BnAudioTrack(),
2116 mTrack(track)
2117{
2118}
2119
2120AudioFlinger::TrackHandle::~TrackHandle() {
2121 // just stop the track on deletion, associated resources
2122 // will be freed from the main thread once all pending buffers have
2123 // been played. Unless it's not in the active track list, in which
2124 // case we free everything now...
2125 mTrack->destroy();
2126}
2127
2128status_t AudioFlinger::TrackHandle::start() {
2129 return mTrack->start();
2130}
2131
2132void AudioFlinger::TrackHandle::stop() {
2133 mTrack->stop();
2134}
2135
2136void AudioFlinger::TrackHandle::flush() {
2137 mTrack->flush();
2138}
2139
2140void AudioFlinger::TrackHandle::mute(bool e) {
2141 mTrack->mute(e);
2142}
2143
2144void AudioFlinger::TrackHandle::pause() {
2145 mTrack->pause();
2146}
2147
2148void AudioFlinger::TrackHandle::setVolume(float left, float right) {
2149 mTrack->setVolume(left, right);
2150}
2151
2152sp<IMemory> AudioFlinger::TrackHandle::getCblk() const {
2153 return mTrack->getCblk();
2154}
2155
2156status_t AudioFlinger::TrackHandle::onTransact(
2157 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
2158{
2159 return BnAudioTrack::onTransact(code, data, reply, flags);
2160}
2161
2162// ----------------------------------------------------------------------------
2163
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002164sp<IAudioRecord> AudioFlinger::openRecord(
2165 pid_t pid,
2166 int streamType,
2167 uint32_t sampleRate,
2168 int format,
2169 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002170 int frameCount,
2171 uint32_t flags,
2172 status_t *status)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002173{
2174 sp<AudioRecordThread> thread;
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08002175 sp<MixerThread::RecordTrack> recordTrack;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002176 sp<RecordHandle> recordHandle;
2177 sp<Client> client;
2178 wp<Client> wclient;
2179 AudioStreamIn* input = 0;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002180 int inFrameCount;
2181 size_t inputBufferSize;
2182 status_t lStatus;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002183
2184 // check calling permissions
2185 if (!recordingAllowed()) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002186 lStatus = PERMISSION_DENIED;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002187 goto Exit;
2188 }
2189
2190 if (uint32_t(streamType) >= AudioRecord::NUM_STREAM_TYPES) {
2191 LOGE("invalid stream type");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002192 lStatus = BAD_VALUE;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002193 goto Exit;
2194 }
2195
2196 if (sampleRate > MAX_SAMPLE_RATE) {
2197 LOGE("Sample rate out of range");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002198 lStatus = BAD_VALUE;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002199 goto Exit;
2200 }
2201
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002202 if (mAudioRecordThread == 0) {
2203 LOGE("Audio record thread not started");
2204 lStatus = NO_INIT;
2205 goto Exit;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002206 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002207
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002208
2209 // Check that audio input stream accepts requested audio parameters
2210 inputBufferSize = mAudioHardware->getInputBufferSize(sampleRate, format, channelCount);
2211 if (inputBufferSize == 0) {
2212 lStatus = BAD_VALUE;
2213 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 -07002214 goto Exit;
2215 }
2216
2217 // add client to list
2218 {
2219 Mutex::Autolock _l(mLock);
2220 wclient = mClients.valueFor(pid);
2221 if (wclient != NULL) {
2222 client = wclient.promote();
2223 } else {
2224 client = new Client(this, pid);
2225 mClients.add(pid, client);
2226 }
2227 }
2228
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002229 // frameCount must be a multiple of input buffer size
2230 inFrameCount = inputBufferSize/channelCount/sizeof(short);
2231 frameCount = ((frameCount - 1)/inFrameCount + 1) * inFrameCount;
2232
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002233 // create new record track and pass to record thread
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08002234 recordTrack = new MixerThread::RecordTrack(mHardwareMixerThread, client, streamType, sampleRate,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002235 format, channelCount, frameCount);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002236
2237 // return to handle to client
2238 recordHandle = new RecordHandle(recordTrack);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002239 lStatus = NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002240
2241Exit:
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002242 if (status) {
2243 *status = lStatus;
2244 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002245 return recordHandle;
2246}
2247
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08002248status_t AudioFlinger::startRecord(MixerThread::RecordTrack* recordTrack) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002249 if (mAudioRecordThread != 0) {
2250 return mAudioRecordThread->start(recordTrack);
2251 }
2252 return NO_INIT;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002253}
2254
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08002255void AudioFlinger::stopRecord(MixerThread::RecordTrack* recordTrack) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002256 if (mAudioRecordThread != 0) {
2257 mAudioRecordThread->stop(recordTrack);
2258 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002259}
2260
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002261// ----------------------------------------------------------------------------
2262
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08002263AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::MixerThread::RecordTrack>& recordTrack)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002264 : BnAudioRecord(),
2265 mRecordTrack(recordTrack)
2266{
2267}
2268
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002269AudioFlinger::RecordHandle::~RecordHandle() {
2270 stop();
2271}
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002272
2273status_t AudioFlinger::RecordHandle::start() {
2274 LOGV("RecordHandle::start()");
2275 return mRecordTrack->start();
2276}
2277
2278void AudioFlinger::RecordHandle::stop() {
2279 LOGV("RecordHandle::stop()");
2280 mRecordTrack->stop();
2281}
2282
2283sp<IMemory> AudioFlinger::RecordHandle::getCblk() const {
2284 return mRecordTrack->getCblk();
2285}
2286
2287status_t AudioFlinger::RecordHandle::onTransact(
2288 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
2289{
2290 return BnAudioRecord::onTransact(code, data, reply, flags);
2291}
2292
2293// ----------------------------------------------------------------------------
2294
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002295AudioFlinger::AudioRecordThread::AudioRecordThread(AudioHardwareInterface* audioHardware) :
2296 mAudioHardware(audioHardware),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002297 mActive(false)
2298{
2299}
2300
2301AudioFlinger::AudioRecordThread::~AudioRecordThread()
2302{
2303}
2304
2305bool AudioFlinger::AudioRecordThread::threadLoop()
2306{
2307 LOGV("AudioRecordThread: start record loop");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002308 AudioBufferProvider::Buffer buffer;
2309 int inBufferSize = 0;
2310 int inFrameCount = 0;
2311 AudioStreamIn* input = 0;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002312
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002313 mActive = 0;
2314
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002315 // start recording
2316 while (!exitPending()) {
2317 if (!mActive) {
2318 mLock.lock();
2319 if (!mActive && !exitPending()) {
2320 LOGV("AudioRecordThread: loop stopping");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002321 if (input) {
2322 delete input;
2323 input = 0;
2324 }
2325 mRecordTrack.clear();
2326
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002327 mWaitWorkCV.wait(mLock);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002328
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002329 LOGV("AudioRecordThread: loop starting");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002330 if (mRecordTrack != 0) {
2331 input = mAudioHardware->openInputStream(mRecordTrack->format(),
2332 mRecordTrack->channelCount(),
2333 mRecordTrack->sampleRate(),
2334 &mStartStatus);
2335 if (input != 0) {
2336 inBufferSize = input->bufferSize();
2337 inFrameCount = inBufferSize/input->frameSize();
2338 }
2339 } else {
2340 mStartStatus = NO_INIT;
2341 }
2342 if (mStartStatus !=NO_ERROR) {
2343 LOGW("record start failed, status %d", mStartStatus);
2344 mActive = false;
2345 mRecordTrack.clear();
2346 }
2347 mWaitWorkCV.signal();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002348 }
2349 mLock.unlock();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002350 } else if (mRecordTrack != 0){
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002351
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002352 buffer.frameCount = inFrameCount;
2353 if (LIKELY(mRecordTrack->getNextBuffer(&buffer) == NO_ERROR)) {
2354 LOGV("AudioRecordThread read: %d frames", buffer.frameCount);
2355 if (input->read(buffer.raw, inBufferSize) < 0) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002356 LOGE("Error reading audio input");
2357 sleep(1);
2358 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002359 mRecordTrack->releaseBuffer(&buffer);
2360 mRecordTrack->overflow();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002361 }
2362
2363 // client isn't retrieving buffers fast enough
2364 else {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002365 if (!mRecordTrack->setOverflow())
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002366 LOGW("AudioRecordThread: buffer overflow");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002367 // Release the processor for a while before asking for a new buffer.
2368 // This will give the application more chance to read from the buffer and
2369 // clear the overflow.
2370 usleep(5000);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002371 }
2372 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002373 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002374
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002375
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002376 if (input) {
2377 delete input;
2378 }
2379 mRecordTrack.clear();
2380
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002381 return false;
2382}
2383
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08002384status_t AudioFlinger::AudioRecordThread::start(MixerThread::RecordTrack* recordTrack)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002385{
2386 LOGV("AudioRecordThread::start");
2387 AutoMutex lock(&mLock);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002388 mActive = true;
2389 // If starting the active track, just reset mActive in case a stop
2390 // was pending and exit
2391 if (recordTrack == mRecordTrack.get()) return NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002392
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002393 if (mRecordTrack != 0) return -EBUSY;
2394
2395 mRecordTrack = recordTrack;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002396
2397 // signal thread to start
2398 LOGV("Signal record thread");
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002399 mWaitWorkCV.signal();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002400 mWaitWorkCV.wait(mLock);
2401 LOGV("Record started, status %d", mStartStatus);
2402 return mStartStatus;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002403}
2404
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -08002405void AudioFlinger::AudioRecordThread::stop(MixerThread::RecordTrack* recordTrack) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002406 LOGV("AudioRecordThread::stop");
2407 AutoMutex lock(&mLock);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002408 if (mActive && (recordTrack == mRecordTrack.get())) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002409 mActive = false;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002410 }
2411}
2412
2413void AudioFlinger::AudioRecordThread::exit()
2414{
2415 LOGV("AudioRecordThread::exit");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002416 {
2417 AutoMutex lock(&mLock);
2418 requestExit();
2419 mWaitWorkCV.signal();
2420 }
2421 requestExitAndWait();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002422}
2423
2424
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002425status_t AudioFlinger::onTransact(
2426 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
2427{
2428 return BnAudioFlinger::onTransact(code, data, reply, flags);
2429}
2430
2431// ----------------------------------------------------------------------------
2432void AudioFlinger::instantiate() {
2433 defaultServiceManager()->addService(
2434 String16("media.audio_flinger"), new AudioFlinger());
2435}
2436
2437}; // namespace android