blob: 43df7ddfdb2b6ac6176c617c9880aa269eaaa91c [file] [log] [blame]
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001/* //device/include/server/AudioFlinger/AudioFlinger.cpp
2**
3** Copyright 2007, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18
19#define LOG_TAG "AudioFlinger"
20//#define LOG_NDEBUG 0
21
22#include <math.h>
23#include <signal.h>
24#include <sys/time.h>
25#include <sys/resource.h>
26
27#include <utils/IServiceManager.h>
28#include <utils/Log.h>
29#include <utils/Parcel.h>
30#include <utils/IPCThreadState.h>
31#include <utils/String16.h>
32#include <utils/threads.h>
33
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -080034#include <cutils/properties.h>
35
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070036#include <media/AudioTrack.h>
37#include <media/AudioRecord.h>
38
39#include <private/media/AudioTrackShared.h>
40
The Android Open Source Project9266c552009-01-15 16:12:10 -080041#include <hardware_legacy/AudioHardwareInterface.h>
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070042
43#include "AudioMixer.h"
44#include "AudioFlinger.h"
45
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -080046#ifdef WITH_A2DP
47#include "A2dpAudioInterface.h"
48#endif
49
The Android Open Source Project9066cfe2009-03-03 19:31:44 -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 Project54b6cfa2008-10-21 07:00:00 -070059namespace android {
60
The Android Open Source Project10592532009-03-18 17:39:46 -070061static const char* kDeadlockedString = "AudioFlinger may be deadlocked\n";
62static const char* kHardwareLockedString = "Hardware lock is taken\n";
63
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -080064//static const nsecs_t kStandbyTimeInNsecs = seconds(3);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070065static const unsigned long kBufferRecoveryInUsecs = 2000;
66static const unsigned long kMaxBufferRecoveryInUsecs = 20000;
67static const float MAX_GAIN = 4096.0f;
68
69// retry counts for buffer fill timeout
70// 50 * ~20msecs = 1 second
71static const int8_t kMaxTrackRetries = 50;
72static const int8_t kMaxTrackStartupRetries = 50;
73
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080074static const int kStartSleepTime = 30000;
75static const int kStopSleepTime = 30000;
76
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070077static const int kDumpLockRetries = 50;
78static const int kDumpLockSleep = 20000;
79
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080// Maximum number of pending buffers allocated by OutputTrack::write()
81static const uint8_t kMaxOutputTrackBuffers = 5;
82
83
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070084#define AUDIOFLINGER_SECURITY_ENABLED 1
85
86// ----------------------------------------------------------------------------
87
88static bool recordingAllowed() {
89#ifndef HAVE_ANDROID_OS
90 return true;
91#endif
92#if AUDIOFLINGER_SECURITY_ENABLED
93 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
94 bool ok = checkCallingPermission(String16("android.permission.RECORD_AUDIO"));
95 if (!ok) LOGE("Request requires android.permission.RECORD_AUDIO");
96 return ok;
97#else
98 if (!checkCallingPermission(String16("android.permission.RECORD_AUDIO")))
99 LOGW("WARNING: Need to add android.permission.RECORD_AUDIO to manifest");
100 return true;
101#endif
102}
103
104static bool settingsAllowed() {
105#ifndef HAVE_ANDROID_OS
106 return true;
107#endif
108#if AUDIOFLINGER_SECURITY_ENABLED
109 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
110 bool ok = checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS"));
111 if (!ok) LOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS");
112 return ok;
113#else
114 if (!checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS")))
115 LOGW("WARNING: Need to add android.permission.MODIFY_AUDIO_SETTINGS to manifest");
116 return true;
117#endif
118}
119
120// ----------------------------------------------------------------------------
121
122AudioFlinger::AudioFlinger()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800123 : BnAudioFlinger(),
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700124 mAudioHardware(0), mA2dpAudioInterface(0), mA2dpEnabled(false), mNotifyA2dpChange(false),
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -0700125 mForcedSpeakerCount(0), mA2dpDisableCount(0), mA2dpSuppressed(false), mForcedRoute(0),
126 mRouteRestoreTime(0), mMusicMuteSaved(false)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700127{
128 mHardwareStatus = AUDIO_HW_IDLE;
129 mAudioHardware = AudioHardwareInterface::create();
130 mHardwareStatus = AUDIO_HW_INIT;
131 if (mAudioHardware->initCheck() == NO_ERROR) {
132 // open 16-bit output stream for s/w mixer
133 mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800134 status_t status;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800135 AudioStreamOut *hwOutput = mAudioHardware->openOutputStream(AudioSystem::PCM_16_BIT, 0, 0, &status);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700136 mHardwareStatus = AUDIO_HW_IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800137 if (hwOutput) {
138 mHardwareMixerThread = new MixerThread(this, hwOutput, AudioSystem::AUDIO_OUTPUT_HARDWARE);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700139 } else {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140 LOGE("Failed to initialize hardware output stream, status: %d", status);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700141 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800142
143#ifdef WITH_A2DP
144 // Create A2DP interface
145 mA2dpAudioInterface = new A2dpAudioInterface();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146 AudioStreamOut *a2dpOutput = mA2dpAudioInterface->openOutputStream(AudioSystem::PCM_16_BIT, 0, 0, &status);
147 if (a2dpOutput) {
148 mA2dpMixerThread = new MixerThread(this, a2dpOutput, AudioSystem::AUDIO_OUTPUT_A2DP);
149 if (hwOutput) {
150 uint32_t frameCount = ((a2dpOutput->bufferSize()/a2dpOutput->frameSize()) * hwOutput->sampleRate()) / a2dpOutput->sampleRate();
151 MixerThread::OutputTrack *a2dpOutTrack = new MixerThread::OutputTrack(mA2dpMixerThread,
152 hwOutput->sampleRate(),
153 AudioSystem::PCM_16_BIT,
154 hwOutput->channelCount(),
155 frameCount);
156 mHardwareMixerThread->setOuputTrack(a2dpOutTrack);
157 }
158 } else {
159 LOGE("Failed to initialize A2DP output stream, status: %d", status);
160 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800161#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800162
163 // FIXME - this should come from settings
164 setRouting(AudioSystem::MODE_NORMAL, AudioSystem::ROUTE_SPEAKER, AudioSystem::ROUTE_ALL);
165 setRouting(AudioSystem::MODE_RINGTONE, AudioSystem::ROUTE_SPEAKER, AudioSystem::ROUTE_ALL);
166 setRouting(AudioSystem::MODE_IN_CALL, AudioSystem::ROUTE_EARPIECE, AudioSystem::ROUTE_ALL);
167 setMode(AudioSystem::MODE_NORMAL);
168
169 setMasterVolume(1.0f);
170 setMasterMute(false);
171
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800172 // Start record thread
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -0700173 mAudioRecordThread = new AudioRecordThread(mAudioHardware, this);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800174 if (mAudioRecordThread != 0) {
175 mAudioRecordThread->run("AudioRecordThread", PRIORITY_URGENT_AUDIO);
176 }
177 } else {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700178 LOGE("Couldn't even initialize the stubbed audio hardware!");
179 }
180}
181
182AudioFlinger::~AudioFlinger()
183{
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800184 if (mAudioRecordThread != 0) {
185 mAudioRecordThread->exit();
186 mAudioRecordThread.clear();
187 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800188 mHardwareMixerThread.clear();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700189 delete mAudioHardware;
The Android Open Source Projectb7986892009-01-09 17:51:23 -0800190 // deleting mA2dpAudioInterface also deletes mA2dpOutput;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800191#ifdef WITH_A2DP
192 mA2dpMixerThread.clear();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800193 delete mA2dpAudioInterface;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194#endif
The Android Open Source Projectb7986892009-01-09 17:51:23 -0800195}
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800196
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700197
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -0800198#ifdef WITH_A2DP
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700199// setA2dpEnabled_l() must be called with AudioFlinger::mLock held
200void AudioFlinger::setA2dpEnabled_l(bool enable)
The Android Open Source Project10592532009-03-18 17:39:46 -0700201{
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700202 SortedVector < sp<MixerThread::Track> > tracks;
203 SortedVector < wp<MixerThread::Track> > activeTracks;
204
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800205 LOGV_IF(enable, "set output to A2DP\n");
206 LOGV_IF(!enable, "set output to hardware audio\n");
207
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700208 // Transfer tracks playing on MUSIC stream from one mixer to the other
209 if (enable) {
210 mHardwareMixerThread->getTracks_l(tracks, activeTracks);
211 mA2dpMixerThread->putTracks_l(tracks, activeTracks);
212 } else {
213 mA2dpMixerThread->getTracks_l(tracks, activeTracks);
214 mHardwareMixerThread->putTracks_l(tracks, activeTracks);
215 }
216 mA2dpEnabled = enable;
217 mNotifyA2dpChange = true;
218 mWaitWorkCV.broadcast();
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -0800219}
220
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700221// checkA2dpEnabledChange_l() must be called with AudioFlinger::mLock held
222void AudioFlinger::checkA2dpEnabledChange_l()
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -0800223{
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700224 if (mNotifyA2dpChange) {
225 // Notify AudioSystem of the A2DP activation/deactivation
226 size_t size = mNotificationClients.size();
227 for (size_t i = 0; i < size; i++) {
228 sp<IBinder> binder = mNotificationClients.itemAt(i).promote();
229 if (binder != NULL) {
230 LOGV("Notifying output change to client %p", binder.get());
231 sp<IAudioFlingerClient> client = interface_cast<IAudioFlingerClient> (binder);
232 client->a2dpEnabledChanged(mA2dpEnabled);
233 }
234 }
235 mNotifyA2dpChange = false;
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -0800236 }
237}
238#endif // WITH_A2DP
239
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800240bool AudioFlinger::streamForcedToSpeaker(int streamType)
241{
242 // NOTE that streams listed here must not be routed to A2DP by default:
243 // AudioSystem::routedToA2dpOutput(streamType) == false
244 return (streamType == AudioSystem::RING ||
245 streamType == AudioSystem::ALARM ||
Eric Laurenteeea9222009-03-26 01:57:59 -0700246 streamType == AudioSystem::NOTIFICATION ||
247 streamType == AudioSystem::ENFORCED_AUDIBLE);
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -0700248}
249
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700250status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args)
251{
252 const size_t SIZE = 256;
253 char buffer[SIZE];
254 String8 result;
255
256 result.append("Clients:\n");
257 for (size_t i = 0; i < mClients.size(); ++i) {
258 wp<Client> wClient = mClients.valueAt(i);
259 if (wClient != 0) {
260 sp<Client> client = wClient.promote();
261 if (client != 0) {
262 snprintf(buffer, SIZE, " pid: %d\n", client->pid());
263 result.append(buffer);
264 }
265 }
266 }
267 write(fd, result.string(), result.size());
268 return NO_ERROR;
269}
270
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700271
272status_t AudioFlinger::dumpInternals(int fd, const Vector<String16>& args)
273{
274 const size_t SIZE = 256;
275 char buffer[SIZE];
276 String8 result;
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700277 int hardwareStatus = mHardwareStatus;
278
279 if (hardwareStatus == AUDIO_HW_IDLE && mHardwareMixerThread->mStandby) {
280 hardwareStatus = AUDIO_HW_STANDBY;
281 }
282 snprintf(buffer, SIZE, "Hardware status: %d\n", hardwareStatus);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700283 result.append(buffer);
284 write(fd, result.string(), result.size());
285 return NO_ERROR;
286}
287
288status_t AudioFlinger::dumpPermissionDenial(int fd, const Vector<String16>& args)
289{
290 const size_t SIZE = 256;
291 char buffer[SIZE];
292 String8 result;
293 snprintf(buffer, SIZE, "Permission Denial: "
294 "can't dump AudioFlinger from pid=%d, uid=%d\n",
295 IPCThreadState::self()->getCallingPid(),
296 IPCThreadState::self()->getCallingUid());
297 result.append(buffer);
298 write(fd, result.string(), result.size());
299 return NO_ERROR;
300}
301
The Android Open Source Project10592532009-03-18 17:39:46 -0700302static bool tryLock(Mutex& mutex)
303{
304 bool locked = false;
305 for (int i = 0; i < kDumpLockRetries; ++i) {
306 if (mutex.tryLock() == NO_ERROR) {
307 locked = true;
308 break;
309 }
310 usleep(kDumpLockSleep);
311 }
312 return locked;
313}
314
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700315status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
316{
317 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
318 dumpPermissionDenial(fd, args);
319 } else {
The Android Open Source Project10592532009-03-18 17:39:46 -0700320 // get state of hardware lock
321 bool hardwareLocked = tryLock(mHardwareLock);
322 if (!hardwareLocked) {
323 String8 result(kHardwareLockedString);
324 write(fd, result.string(), result.size());
325 } else {
326 mHardwareLock.unlock();
327 }
328
329 bool locked = tryLock(mLock);
330
331 // failed to lock - AudioFlinger is probably deadlocked
332 if (!locked) {
333 String8 result(kDeadlockedString);
334 write(fd, result.string(), result.size());
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700335 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700336
337 dumpClients(fd, args);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700338 dumpInternals(fd, args);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800339 mHardwareMixerThread->dump(fd, args);
340#ifdef WITH_A2DP
341 mA2dpMixerThread->dump(fd, args);
342#endif
343
344 // dump record client
345 if (mAudioRecordThread != 0) mAudioRecordThread->dump(fd, args);
346
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700347 if (mAudioHardware) {
348 mAudioHardware->dumpState(fd, args);
349 }
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700350 if (locked) mLock.unlock();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700351 }
352 return NO_ERROR;
353}
354
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700355// IAudioFlinger interface
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800356
357
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700358sp<IAudioTrack> AudioFlinger::createTrack(
359 pid_t pid,
360 int streamType,
361 uint32_t sampleRate,
362 int format,
363 int channelCount,
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800364 int frameCount,
365 uint32_t flags,
366 const sp<IMemory>& sharedBuffer,
367 status_t *status)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700368{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800369 sp<MixerThread::Track> track;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700370 sp<TrackHandle> trackHandle;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700371 sp<Client> client;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800372 wp<Client> wclient;
373 status_t lStatus;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700374
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800375 if (streamType >= AudioSystem::NUM_STREAM_TYPES) {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800376 LOGE("invalid stream type");
377 lStatus = BAD_VALUE;
378 goto Exit;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700379 }
380
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800381 {
382 Mutex::Autolock _l(mLock);
383
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800384 wclient = mClients.valueFor(pid);
385
386 if (wclient != NULL) {
387 client = wclient.promote();
388 } else {
389 client = new Client(this, pid);
390 mClients.add(pid, client);
391 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800392#ifdef WITH_A2DP
393 if (isA2dpEnabled() && AudioSystem::routedToA2dpOutput(streamType)) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700394 track = mA2dpMixerThread->createTrack_l(client, streamType, sampleRate, format,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800395 channelCount, frameCount, sharedBuffer, &lStatus);
396 } else
397#endif
398 {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700399 track = mHardwareMixerThread->createTrack_l(client, streamType, sampleRate, format,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800400 channelCount, frameCount, sharedBuffer, &lStatus);
401 }
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700402 }
403 if (lStatus == NO_ERROR) {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800404 trackHandle = new TrackHandle(track);
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700405 } else {
406 track.clear();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800407 }
408
409Exit:
410 if(status) {
411 *status = lStatus;
412 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700413 return trackHandle;
414}
415
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800416uint32_t AudioFlinger::sampleRate(int output) const
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700417{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800418#ifdef WITH_A2DP
419 if (output == AudioSystem::AUDIO_OUTPUT_A2DP) {
420 return mA2dpMixerThread->sampleRate();
421 }
422#endif
423 return mHardwareMixerThread->sampleRate();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700424}
425
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800426int AudioFlinger::channelCount(int output) const
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700427{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800428#ifdef WITH_A2DP
429 if (output == AudioSystem::AUDIO_OUTPUT_A2DP) {
430 return mA2dpMixerThread->channelCount();
431 }
432#endif
433 return mHardwareMixerThread->channelCount();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700434}
435
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800436int AudioFlinger::format(int output) const
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700437{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800438#ifdef WITH_A2DP
439 if (output == AudioSystem::AUDIO_OUTPUT_A2DP) {
440 return mA2dpMixerThread->format();
441 }
442#endif
443 return mHardwareMixerThread->format();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700444}
445
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800446size_t AudioFlinger::frameCount(int output) const
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700447{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800448#ifdef WITH_A2DP
449 if (output == AudioSystem::AUDIO_OUTPUT_A2DP) {
450 return mA2dpMixerThread->frameCount();
451 }
452#endif
453 return mHardwareMixerThread->frameCount();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700454}
455
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800456uint32_t AudioFlinger::latency(int output) const
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800457{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800458#ifdef WITH_A2DP
459 if (output == AudioSystem::AUDIO_OUTPUT_A2DP) {
460 return mA2dpMixerThread->latency();
461 }
462#endif
463 return mHardwareMixerThread->latency();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800464}
465
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700466status_t AudioFlinger::setMasterVolume(float value)
467{
468 // check calling permissions
469 if (!settingsAllowed()) {
470 return PERMISSION_DENIED;
471 }
472
473 // when hw supports master volume, don't scale in sw mixer
474 AutoMutex lock(mHardwareLock);
475 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
476 if (mAudioHardware->setMasterVolume(value) == NO_ERROR) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800477 value = 1.0f;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700478 }
479 mHardwareStatus = AUDIO_HW_IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800480 mHardwareMixerThread->setMasterVolume(value);
481#ifdef WITH_A2DP
482 mA2dpMixerThread->setMasterVolume(value);
483#endif
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700484
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700485 return NO_ERROR;
486}
487
488status_t AudioFlinger::setRouting(int mode, uint32_t routes, uint32_t mask)
489{
The Android Open Source Projectb7986892009-01-09 17:51:23 -0800490 status_t err = NO_ERROR;
491
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700492 // check calling permissions
493 if (!settingsAllowed()) {
494 return PERMISSION_DENIED;
495 }
496 if ((mode < AudioSystem::MODE_CURRENT) || (mode >= AudioSystem::NUM_MODES)) {
497 LOGW("Illegal value: setRouting(%d, %u, %u)", mode, routes, mask);
498 return BAD_VALUE;
499 }
500
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800501#ifdef WITH_A2DP
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800502 LOGD("setRouting %d %d %d, tid %d, calling tid %d\n", mode, routes, mask, gettid(), IPCThreadState::self()->getCallingPid());
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800503 if (mode == AudioSystem::MODE_NORMAL &&
504 (mask & AudioSystem::ROUTE_BLUETOOTH_A2DP)) {
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -0800505 AutoMutex lock(&mLock);
506
507 bool enableA2dp = false;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800508 if (routes & AudioSystem::ROUTE_BLUETOOTH_A2DP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800509 enableA2dp = true;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800510 }
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -0700511 if (mA2dpDisableCount > 0) {
512 mA2dpSuppressed = enableA2dp;
513 } else {
514 setA2dpEnabled_l(enableA2dp);
515 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800516 LOGV("setOutput done\n");
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800517 }
The Android Open Source Project10592532009-03-18 17:39:46 -0700518 // setRouting() is always called at least for mode == AudioSystem::MODE_IN_CALL when
519 // SCO is enabled, whatever current mode is so we can safely handle A2DP disabling only
520 // in this case to avoid doing it several times.
521 if (mode == AudioSystem::MODE_IN_CALL &&
522 (mask & AudioSystem::ROUTE_BLUETOOTH_SCO)) {
523 AutoMutex lock(&mLock);
524 handleRouteDisablesA2dp_l(routes);
525 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800526#endif
527
The Android Open Source Projectb7986892009-01-09 17:51:23 -0800528 // do nothing if only A2DP routing is affected
529 mask &= ~AudioSystem::ROUTE_BLUETOOTH_A2DP;
530 if (mask) {
531 AutoMutex lock(mHardwareLock);
532 mHardwareStatus = AUDIO_HW_GET_ROUTING;
533 uint32_t r;
534 err = mAudioHardware->getRouting(mode, &r);
535 if (err == NO_ERROR) {
536 r = (r & ~mask) | (routes & mask);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800537 if (mode == AudioSystem::MODE_NORMAL ||
538 (mode == AudioSystem::MODE_CURRENT && getMode() == AudioSystem::MODE_NORMAL)) {
539 mSavedRoute = r;
540 r |= mForcedRoute;
541 LOGV("setRouting mSavedRoute %08x mForcedRoute %08x\n", mSavedRoute, mForcedRoute);
542 }
The Android Open Source Projectb7986892009-01-09 17:51:23 -0800543 mHardwareStatus = AUDIO_HW_SET_ROUTING;
544 err = mAudioHardware->setRouting(mode, r);
545 }
546 mHardwareStatus = AUDIO_HW_IDLE;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700547 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700548 return err;
549}
550
551uint32_t AudioFlinger::getRouting(int mode) const
552{
553 uint32_t routes = 0;
554 if ((mode >= AudioSystem::MODE_CURRENT) && (mode < AudioSystem::NUM_MODES)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800555 if (mode == AudioSystem::MODE_NORMAL ||
556 (mode == AudioSystem::MODE_CURRENT && getMode() == AudioSystem::MODE_NORMAL)) {
557 routes = mSavedRoute;
558 } else {
559 mHardwareStatus = AUDIO_HW_GET_ROUTING;
560 mAudioHardware->getRouting(mode, &routes);
561 mHardwareStatus = AUDIO_HW_IDLE;
562 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700563 } else {
564 LOGW("Illegal value: getRouting(%d)", mode);
565 }
566 return routes;
567}
568
569status_t AudioFlinger::setMode(int mode)
570{
571 // check calling permissions
572 if (!settingsAllowed()) {
573 return PERMISSION_DENIED;
574 }
575 if ((mode < 0) || (mode >= AudioSystem::NUM_MODES)) {
576 LOGW("Illegal value: setMode(%d)", mode);
577 return BAD_VALUE;
578 }
579
580 AutoMutex lock(mHardwareLock);
581 mHardwareStatus = AUDIO_HW_SET_MODE;
582 status_t ret = mAudioHardware->setMode(mode);
583 mHardwareStatus = AUDIO_HW_IDLE;
584 return ret;
585}
586
587int AudioFlinger::getMode() const
588{
589 int mode = AudioSystem::MODE_INVALID;
590 mHardwareStatus = AUDIO_HW_SET_MODE;
591 mAudioHardware->getMode(&mode);
592 mHardwareStatus = AUDIO_HW_IDLE;
593 return mode;
594}
595
596status_t AudioFlinger::setMicMute(bool state)
597{
598 // check calling permissions
599 if (!settingsAllowed()) {
600 return PERMISSION_DENIED;
601 }
602
603 AutoMutex lock(mHardwareLock);
604 mHardwareStatus = AUDIO_HW_SET_MIC_MUTE;
605 status_t ret = mAudioHardware->setMicMute(state);
606 mHardwareStatus = AUDIO_HW_IDLE;
607 return ret;
608}
609
610bool AudioFlinger::getMicMute() const
611{
612 bool state = AudioSystem::MODE_INVALID;
613 mHardwareStatus = AUDIO_HW_GET_MIC_MUTE;
614 mAudioHardware->getMicMute(&state);
615 mHardwareStatus = AUDIO_HW_IDLE;
616 return state;
617}
618
619status_t AudioFlinger::setMasterMute(bool muted)
620{
621 // check calling permissions
622 if (!settingsAllowed()) {
623 return PERMISSION_DENIED;
624 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800625 mHardwareMixerThread->setMasterMute(muted);
626#ifdef WITH_A2DP
627 mA2dpMixerThread->setMasterMute(muted);
628#endif
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700629 return NO_ERROR;
630}
631
632float AudioFlinger::masterVolume() const
633{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800634 return mHardwareMixerThread->masterVolume();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700635}
636
637bool AudioFlinger::masterMute() const
638{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800639 return mHardwareMixerThread->masterMute();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700640}
641
642status_t AudioFlinger::setStreamVolume(int stream, float value)
643{
644 // check calling permissions
645 if (!settingsAllowed()) {
646 return PERMISSION_DENIED;
647 }
648
Eric Laurenteeea9222009-03-26 01:57:59 -0700649 if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES ||
650 uint32_t(stream) == AudioSystem::ENFORCED_AUDIBLE) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700651 return BAD_VALUE;
652 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800653
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700654 status_t ret = NO_ERROR;
Jean-Baptiste Queru2a73de72009-03-18 11:33:14 -0700655
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800656 if (stream == AudioSystem::VOICE_CALL ||
657 stream == AudioSystem::BLUETOOTH_SCO) {
Jean-Baptiste Queru2a73de72009-03-18 11:33:14 -0700658 float hwValue = value;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800659 if (stream == AudioSystem::VOICE_CALL) {
Jean-Baptiste Queru2a73de72009-03-18 11:33:14 -0700660 hwValue = (float)AudioSystem::logToLinear(value)/100.0f;
661 // FIXME: This is a temporary fix to re-base the internally
662 // generated in-call audio so that it is never muted, which is
663 // already the case for the hardware routed in-call audio.
664 // When audio stream handling is reworked, this should be
665 // addressed more cleanly. Fixes #1324; see discussion at
666 // http://review.source.android.com/8224
667 value = value * 0.99 + 0.01;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800668 } else { // (type == AudioSystem::BLUETOOTH_SCO)
Jean-Baptiste Queru2a73de72009-03-18 11:33:14 -0700669 hwValue = 1.0f;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800670 }
671
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700672 AutoMutex lock(mHardwareLock);
673 mHardwareStatus = AUDIO_SET_VOICE_VOLUME;
Jean-Baptiste Queru2a73de72009-03-18 11:33:14 -0700674 ret = mAudioHardware->setVoiceVolume(hwValue);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700675 mHardwareStatus = AUDIO_HW_IDLE;
Jean-Baptiste Queru2a73de72009-03-18 11:33:14 -0700676
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700677 }
Jean-Baptiste Queru2a73de72009-03-18 11:33:14 -0700678
679 mHardwareMixerThread->setStreamVolume(stream, value);
680#ifdef WITH_A2DP
681 mA2dpMixerThread->setStreamVolume(stream, value);
682#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800683
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700684 return ret;
685}
686
687status_t AudioFlinger::setStreamMute(int stream, bool muted)
688{
689 // check calling permissions
690 if (!settingsAllowed()) {
691 return PERMISSION_DENIED;
692 }
693
Eric Laurenteeea9222009-03-26 01:57:59 -0700694 if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES ||
695 uint32_t(stream) == AudioSystem::ENFORCED_AUDIBLE) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700696 return BAD_VALUE;
697 }
The Android Open Source Project10592532009-03-18 17:39:46 -0700698
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800699#ifdef WITH_A2DP
700 mA2dpMixerThread->setStreamMute(stream, muted);
701#endif
702 if (stream == AudioSystem::MUSIC)
703 {
704 AutoMutex lock(&mHardwareLock);
705 if (mForcedRoute != 0)
706 mMusicMuteSaved = muted;
707 else
708 mHardwareMixerThread->setStreamMute(stream, muted);
709 } else {
710 mHardwareMixerThread->setStreamMute(stream, muted);
711 }
712
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700713 return NO_ERROR;
714}
715
716float AudioFlinger::streamVolume(int stream) const
717{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800718 if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700719 return 0.0f;
720 }
Jean-Baptiste Queru2a73de72009-03-18 11:33:14 -0700721 float value = mHardwareMixerThread->streamVolume(stream);
722
723 if (stream == AudioSystem::VOICE_CALL) {
James E. Blair90329a62009-01-17 13:30:20 -0800724 // FIXME: Re-base internally generated in-call audio,
725 // reverse of above in setStreamVolume.
Jean-Baptiste Queru2a73de72009-03-18 11:33:14 -0700726 value = (value - 0.01) / 0.99;
James E. Blair90329a62009-01-17 13:30:20 -0800727 }
Jean-Baptiste Queru2a73de72009-03-18 11:33:14 -0700728
729 return value;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700730}
731
732bool AudioFlinger::streamMute(int stream) const
733{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800734 if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700735 return true;
736 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800737
738 if (stream == AudioSystem::MUSIC && mForcedRoute != 0)
739 {
740 return mMusicMuteSaved;
741 }
742 return mHardwareMixerThread->streamMute(stream);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700743}
744
745bool AudioFlinger::isMusicActive() const
746{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800747 #ifdef WITH_A2DP
748 if (isA2dpEnabled()) {
749 return mA2dpMixerThread->isMusicActive();
750 }
751 #endif
752 return mHardwareMixerThread->isMusicActive();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700753}
754
755status_t AudioFlinger::setParameter(const char* key, const char* value)
756{
The Android Open Source Project9266c552009-01-15 16:12:10 -0800757 status_t result, result2;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700758 AutoMutex lock(mHardwareLock);
759 mHardwareStatus = AUDIO_SET_PARAMETER;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800760
761 LOGV("setParameter() key %s, value %s, tid %d, calling tid %d", key, value, gettid(), IPCThreadState::self()->getCallingPid());
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700762 result = mAudioHardware->setParameter(key, value);
The Android Open Source Project9266c552009-01-15 16:12:10 -0800763 if (mA2dpAudioInterface) {
764 result2 = mA2dpAudioInterface->setParameter(key, value);
765 if (result2)
766 result = result2;
767 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700768 mHardwareStatus = AUDIO_HW_IDLE;
769 return result;
770}
771
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800772size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
773{
774 return mAudioHardware->getInputBufferSize(sampleRate, format, channelCount);
775}
776
777void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
778{
779
780 LOGV("registerClient() %p, tid %d, calling tid %d", client.get(), gettid(), IPCThreadState::self()->getCallingPid());
781 Mutex::Autolock _l(mLock);
782
783 sp<IBinder> binder = client->asBinder();
784 if (mNotificationClients.indexOf(binder) < 0) {
785 LOGV("Adding notification client %p", binder.get());
786 binder->linkToDeath(this);
787 mNotificationClients.add(binder);
788 client->a2dpEnabledChanged(isA2dpEnabled());
789 }
790}
791
792void AudioFlinger::binderDied(const wp<IBinder>& who) {
793
794 LOGV("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(), IPCThreadState::self()->getCallingPid());
795 Mutex::Autolock _l(mLock);
796
797 IBinder *binder = who.unsafe_get();
798
799 if (binder != NULL) {
800 int index = mNotificationClients.indexOf(binder);
801 if (index >= 0) {
802 LOGV("Removing notification client %p", binder);
803 mNotificationClients.removeAt(index);
804 }
805 }
806}
807
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700808void AudioFlinger::removeClient(pid_t pid)
809{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800810 LOGV("removeClient() pid %d, tid %d, calling tid %d", pid, gettid(), IPCThreadState::self()->getCallingPid());
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700811 Mutex::Autolock _l(mLock);
812 mClients.removeItem(pid);
813}
814
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800815bool AudioFlinger::isA2dpEnabled() const
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700816{
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700817 return mA2dpEnabled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800818}
819
820void AudioFlinger::handleForcedSpeakerRoute(int command)
821{
822 switch(command) {
823 case ACTIVE_TRACK_ADDED:
824 {
825 AutoMutex lock(mHardwareLock);
826 if (mForcedSpeakerCount++ == 0) {
827 mRouteRestoreTime = 0;
828 mMusicMuteSaved = mHardwareMixerThread->streamMute(AudioSystem::MUSIC);
829 if (mForcedRoute == 0 && !(mSavedRoute & AudioSystem::ROUTE_SPEAKER)) {
830 LOGV("Route forced to Speaker ON %08x", mSavedRoute | AudioSystem::ROUTE_SPEAKER);
831 mHardwareMixerThread->setStreamMute(AudioSystem::MUSIC, true);
832 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
833 mAudioHardware->setMasterVolume(0);
834 usleep(mHardwareMixerThread->latency()*1000);
835 mHardwareStatus = AUDIO_HW_SET_ROUTING;
836 mAudioHardware->setRouting(AudioSystem::MODE_NORMAL, mSavedRoute | AudioSystem::ROUTE_SPEAKER);
837 mHardwareStatus = AUDIO_HW_IDLE;
838 // delay track start so that audio hardware has time to siwtch routes
839 usleep(kStartSleepTime);
840 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
841 mAudioHardware->setMasterVolume(mHardwareMixerThread->masterVolume());
842 mHardwareStatus = AUDIO_HW_IDLE;
843 }
844 mForcedRoute = AudioSystem::ROUTE_SPEAKER;
845 }
846 LOGV("mForcedSpeakerCount incremented to %d", mForcedSpeakerCount);
847 }
848 break;
849 case ACTIVE_TRACK_REMOVED:
850 {
851 AutoMutex lock(mHardwareLock);
852 if (mForcedSpeakerCount > 0){
853 if (--mForcedSpeakerCount == 0) {
854 mRouteRestoreTime = systemTime() + milliseconds(kStopSleepTime/1000);
855 }
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -0700856 LOGV("mForcedSpeakerCount decremented to %d", mForcedSpeakerCount);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800857 } else {
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -0700858 LOGE("mForcedSpeakerCount is already zero");
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700859 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800860 }
861 break;
862 case CHECK_ROUTE_RESTORE_TIME:
863 case FORCE_ROUTE_RESTORE:
864 if (mRouteRestoreTime) {
865 AutoMutex lock(mHardwareLock);
866 if (mRouteRestoreTime &&
867 (systemTime() > mRouteRestoreTime || command == FORCE_ROUTE_RESTORE)) {
868 mHardwareMixerThread->setStreamMute(AudioSystem::MUSIC, mMusicMuteSaved);
869 mForcedRoute = 0;
870 if (!(mSavedRoute & AudioSystem::ROUTE_SPEAKER)) {
871 mHardwareStatus = AUDIO_HW_SET_ROUTING;
872 mAudioHardware->setRouting(AudioSystem::MODE_NORMAL, mSavedRoute);
873 mHardwareStatus = AUDIO_HW_IDLE;
874 LOGV("Route forced to Speaker OFF %08x", mSavedRoute);
875 }
876 mRouteRestoreTime = 0;
877 }
878 }
879 break;
880 }
881}
882
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -0700883#ifdef WITH_A2DP
The Android Open Source Project10592532009-03-18 17:39:46 -0700884// handleRouteDisablesA2dp_l() must be called with AudioFlinger::mLock held
885void AudioFlinger::handleRouteDisablesA2dp_l(int routes)
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -0700886{
The Android Open Source Project10592532009-03-18 17:39:46 -0700887 if (routes & AudioSystem::ROUTE_BLUETOOTH_SCO) {
888 if (mA2dpDisableCount++ == 0) {
889 if (mA2dpEnabled) {
890 setA2dpEnabled_l(false);
891 mA2dpSuppressed = true;
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -0700892 }
893 }
The Android Open Source Project10592532009-03-18 17:39:46 -0700894 LOGV("mA2dpDisableCount incremented to %d", mA2dpDisableCount);
895 } else {
896 if (mA2dpDisableCount > 0) {
897 if (--mA2dpDisableCount == 0) {
898 if (mA2dpSuppressed) {
899 setA2dpEnabled_l(true);
900 mA2dpSuppressed = false;
901 }
902 }
903 LOGV("mA2dpDisableCount decremented to %d", mA2dpDisableCount);
904 } else {
905 LOGE("mA2dpDisableCount is already zero");
906 }
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -0700907 }
908}
909#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800910
911// ----------------------------------------------------------------------------
912
913AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int outputType)
914 : Thread(false),
915 mAudioFlinger(audioFlinger), mAudioMixer(0), mOutput(output), mOutputType(outputType),
916 mSampleRate(0), mFrameCount(0), mChannelCount(0), mFormat(0), mMixBuffer(0),
917 mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mStandby(false),
918 mInWrite(false)
919{
920 mSampleRate = output->sampleRate();
921 mChannelCount = output->channelCount();
922
923 // FIXME - Current mixer implementation only supports stereo output
924 if (mChannelCount == 1) {
925 LOGE("Invalid audio hardware channel count");
926 }
927
928 mFormat = output->format();
929 mFrameCount = output->bufferSize() / output->channelCount() / sizeof(int16_t);
930 mAudioMixer = new AudioMixer(mFrameCount, output->sampleRate());
931
932 // FIXME - Current mixer implementation only supports stereo output: Always
933 // Allocate a stereo buffer even if HW output is mono.
934 mMixBuffer = new int16_t[mFrameCount * 2];
935 memset(mMixBuffer, 0, mFrameCount * 2 * sizeof(int16_t));
936}
937
938AudioFlinger::MixerThread::~MixerThread()
939{
940 delete [] mMixBuffer;
941 delete mAudioMixer;
942}
943
944status_t AudioFlinger::MixerThread::dump(int fd, const Vector<String16>& args)
945{
946 dumpInternals(fd, args);
947 dumpTracks(fd, args);
948 return NO_ERROR;
949}
950
951status_t AudioFlinger::MixerThread::dumpTracks(int fd, const Vector<String16>& args)
952{
953 const size_t SIZE = 256;
954 char buffer[SIZE];
955 String8 result;
956
957 snprintf(buffer, SIZE, "Output %d mixer thread tracks\n", mOutputType);
958 result.append(buffer);
959 result.append(" Name Clien Typ Fmt Chn Buf S M F SRate LeftV RighV Serv User\n");
960 for (size_t i = 0; i < mTracks.size(); ++i) {
Eric Laurent08defa02009-03-31 09:38:57 -0700961 sp<Track> track = mTracks[i];
962 if (track != 0) {
963 track->dump(buffer, SIZE);
964 result.append(buffer);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800965 }
966 }
967
968 snprintf(buffer, SIZE, "Output %d mixer thread active tracks\n", mOutputType);
969 result.append(buffer);
970 result.append(" Name Clien Typ Fmt Chn Buf S M F SRate LeftV RighV Serv User\n");
971 for (size_t i = 0; i < mActiveTracks.size(); ++i) {
Eric Laurent08defa02009-03-31 09:38:57 -0700972 wp<Track> wTrack = mActiveTracks[i];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800973 if (wTrack != 0) {
974 sp<Track> track = wTrack.promote();
975 if (track != 0) {
976 track->dump(buffer, SIZE);
977 result.append(buffer);
978 }
979 }
980 }
981 write(fd, result.string(), result.size());
982 return NO_ERROR;
983}
984
985status_t AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>& args)
986{
987 const size_t SIZE = 256;
988 char buffer[SIZE];
989 String8 result;
990
991 snprintf(buffer, SIZE, "Output %d mixer thread internals\n", mOutputType);
992 result.append(buffer);
993 snprintf(buffer, SIZE, "AudioMixer tracks: %08x\n", mAudioMixer->trackNames());
994 result.append(buffer);
995 snprintf(buffer, SIZE, "last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime));
996 result.append(buffer);
997 snprintf(buffer, SIZE, "total writes: %d\n", mNumWrites);
998 result.append(buffer);
999 snprintf(buffer, SIZE, "delayed writes: %d\n", mNumDelayedWrites);
1000 result.append(buffer);
1001 snprintf(buffer, SIZE, "blocked in write: %d\n", mInWrite);
1002 result.append(buffer);
1003 snprintf(buffer, SIZE, "standby: %d\n", mStandby);
1004 result.append(buffer);
1005 write(fd, result.string(), result.size());
1006 return NO_ERROR;
1007}
1008
1009// Thread virtuals
1010bool AudioFlinger::MixerThread::threadLoop()
1011{
1012 unsigned long sleepTime = kBufferRecoveryInUsecs;
1013 int16_t* curBuf = mMixBuffer;
1014 Vector< sp<Track> > tracksToRemove;
1015 size_t enabledTracks = 0;
1016 nsecs_t standbyTime = systemTime();
1017 size_t mixBufferSize = mFrameCount*mChannelCount*sizeof(int16_t);
1018 nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 2;
1019
1020#ifdef WITH_A2DP
1021 bool outputTrackActive = false;
1022#endif
1023
1024 do {
1025 enabledTracks = 0;
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001026 { // scope for the AudioFlinger::mLock
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001027
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001028 Mutex::Autolock _l(mAudioFlinger->mLock);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001029
1030#ifdef WITH_A2DP
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001031 if (mOutputTrack != NULL && !mAudioFlinger->isA2dpEnabled()) {
1032 if (outputTrackActive) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001033 mAudioFlinger->mLock.unlock();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001034 mOutputTrack->stop();
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001035 mAudioFlinger->mLock.lock();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001036 outputTrackActive = false;
1037 }
1038 }
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001039 mAudioFlinger->checkA2dpEnabledChange_l();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001040#endif
1041
1042 const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
1043
1044 // put audio hardware into standby after short delay
1045 if UNLIKELY(!activeTracks.size() && systemTime() > standbyTime) {
1046 // wait until we have something to do...
1047 LOGV("Audio hardware entering standby, output %d\n", mOutputType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001048 if (!mStandby) {
1049 mOutput->standby();
1050 mStandby = true;
1051 }
1052
1053#ifdef WITH_A2DP
1054 if (outputTrackActive) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001055 mAudioFlinger->mLock.unlock();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001056 mOutputTrack->stop();
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001057 mAudioFlinger->mLock.lock();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001058 outputTrackActive = false;
1059 }
1060#endif
1061 if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) {
1062 mAudioFlinger->handleForcedSpeakerRoute(FORCE_ROUTE_RESTORE);
1063 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001064 // we're about to wait, flush the binder command buffer
1065 IPCThreadState::self()->flushCommands();
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001066 mAudioFlinger->mWaitWorkCV.wait(mAudioFlinger->mLock);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001067 LOGV("Audio hardware exiting standby, output %d\n", mOutputType);
1068
1069 if (mMasterMute == false) {
1070 char value[PROPERTY_VALUE_MAX];
1071 property_get("ro.audio.silent", value, "0");
1072 if (atoi(value)) {
1073 LOGD("Silence is golden");
1074 setMasterMute(true);
1075 }
1076 }
1077
1078 standbyTime = systemTime() + kStandbyTimeInNsecs;
1079 continue;
1080 }
1081
1082 // Forced route to speaker is handled by hardware mixer thread
1083 if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) {
1084 mAudioFlinger->handleForcedSpeakerRoute(CHECK_ROUTE_RESTORE_TIME);
1085 }
1086
1087 // find out which tracks need to be processed
1088 size_t count = activeTracks.size();
1089 for (size_t i=0 ; i<count ; i++) {
1090 sp<Track> t = activeTracks[i].promote();
1091 if (t == 0) continue;
1092
1093 Track* const track = t.get();
1094 audio_track_cblk_t* cblk = track->cblk();
1095
1096 // The first time a track is added we wait
1097 // for all its buffers to be filled before processing it
1098 mAudioMixer->setActiveTrack(track->name());
1099 if (cblk->framesReady() && (track->isReady() || track->isStopped()) &&
1100 !track->isPaused())
1101 {
1102 //LOGV("track %d u=%08x, s=%08x [OK]", track->name(), cblk->user, cblk->server);
1103
1104 // compute volume for this track
1105 int16_t left, right;
1106 if (track->isMuted() || mMasterMute || track->isPausing()) {
1107 left = right = 0;
1108 if (track->isPausing()) {
1109 LOGV("paused(%d)", track->name());
1110 track->setPaused();
1111 }
1112 } else {
1113 float typeVolume = mStreamTypes[track->type()].volume;
1114 float v = mMasterVolume * typeVolume;
1115 float v_clamped = v * cblk->volume[0];
1116 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
1117 left = int16_t(v_clamped);
1118 v_clamped = v * cblk->volume[1];
1119 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
1120 right = int16_t(v_clamped);
1121 }
1122
1123 // XXX: these things DON'T need to be done each time
1124 mAudioMixer->setBufferProvider(track);
1125 mAudioMixer->enable(AudioMixer::MIXING);
1126
1127 int param;
1128 if ( track->mFillingUpStatus == Track::FS_FILLED) {
1129 // no ramp for the first volume setting
1130 track->mFillingUpStatus = Track::FS_ACTIVE;
1131 if (track->mState == TrackBase::RESUMING) {
1132 track->mState = TrackBase::ACTIVE;
1133 param = AudioMixer::RAMP_VOLUME;
1134 } else {
1135 param = AudioMixer::VOLUME;
1136 }
1137 } else {
1138 param = AudioMixer::RAMP_VOLUME;
1139 }
1140 mAudioMixer->setParameter(param, AudioMixer::VOLUME0, left);
1141 mAudioMixer->setParameter(param, AudioMixer::VOLUME1, right);
1142 mAudioMixer->setParameter(
1143 AudioMixer::TRACK,
1144 AudioMixer::FORMAT, track->format());
1145 mAudioMixer->setParameter(
1146 AudioMixer::TRACK,
1147 AudioMixer::CHANNEL_COUNT, track->channelCount());
1148 mAudioMixer->setParameter(
1149 AudioMixer::RESAMPLE,
1150 AudioMixer::SAMPLE_RATE,
1151 int(cblk->sampleRate));
1152
1153 // reset retry count
1154 track->mRetryCount = kMaxTrackRetries;
1155 enabledTracks++;
1156 } else {
1157 //LOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
1158 if (track->isStopped()) {
1159 track->reset();
1160 }
1161 if (track->isTerminated() || track->isStopped() || track->isPaused()) {
1162 // We have consumed all the buffers of this track.
1163 // Remove it from the list of active tracks.
1164 LOGV("remove(%d) from active list", track->name());
1165 tracksToRemove.add(track);
1166 } else {
1167 // No buffers for this track. Give it a few chances to
1168 // fill a buffer, then remove it from active list.
1169 if (--(track->mRetryCount) <= 0) {
1170 LOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
1171 tracksToRemove.add(track);
1172 }
1173 }
1174 // LOGV("disable(%d)", track->name());
1175 mAudioMixer->disable(AudioMixer::MIXING);
1176 }
1177 }
1178
1179 // remove all the tracks that need to be...
1180 count = tracksToRemove.size();
1181 if (UNLIKELY(count)) {
1182 for (size_t i=0 ; i<count ; i++) {
1183 const sp<Track>& track = tracksToRemove[i];
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001184 removeActiveTrack_l(track);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001185 if (track->isTerminated()) {
1186 mTracks.remove(track);
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001187 deleteTrackName_l(track->mName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001188 }
1189 }
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001190 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001191 }
1192
1193 if (LIKELY(enabledTracks)) {
1194 // mix buffers...
1195 mAudioMixer->process(curBuf);
1196
1197#ifdef WITH_A2DP
1198 if (mOutputTrack != NULL && mAudioFlinger->isA2dpEnabled()) {
1199 if (!outputTrackActive) {
1200 LOGV("starting output track in mixer for output %d", mOutputType);
1201 mOutputTrack->start();
1202 outputTrackActive = true;
1203 }
1204 mOutputTrack->write(curBuf, mFrameCount);
1205 }
1206#endif
1207
1208 // output audio to hardware
1209 mLastWriteTime = systemTime();
1210 mInWrite = true;
1211 mOutput->write(curBuf, mixBufferSize);
1212 mNumWrites++;
1213 mInWrite = false;
1214 mStandby = false;
1215 nsecs_t temp = systemTime();
1216 standbyTime = temp + kStandbyTimeInNsecs;
1217 nsecs_t delta = temp - mLastWriteTime;
1218 if (delta > maxPeriod) {
1219 LOGW("write blocked for %llu msecs", ns2ms(delta));
1220 mNumDelayedWrites++;
1221 }
1222 sleepTime = kBufferRecoveryInUsecs;
1223 } else {
1224#ifdef WITH_A2DP
1225 if (mOutputTrack != NULL && mAudioFlinger->isA2dpEnabled()) {
1226 if (outputTrackActive) {
1227 mOutputTrack->write(curBuf, 0);
1228 if (mOutputTrack->bufferQueueEmpty()) {
1229 mOutputTrack->stop();
1230 outputTrackActive = false;
1231 } else {
1232 standbyTime = systemTime() + kStandbyTimeInNsecs;
1233 }
1234 }
1235 }
1236#endif
1237 // There was nothing to mix this round, which means all
1238 // active tracks were late. Sleep a little bit to give
1239 // them another chance. If we're too late, the audio
1240 // hardware will zero-fill for us.
1241 //LOGV("no buffers - usleep(%lu)", sleepTime);
1242 usleep(sleepTime);
1243 if (sleepTime < kMaxBufferRecoveryInUsecs) {
1244 sleepTime += kBufferRecoveryInUsecs;
1245 }
1246 }
1247
1248 // finally let go of all our tracks, without the lock held
1249 // since we can't guarantee the destructors won't acquire that
1250 // same lock.
1251 tracksToRemove.clear();
1252 } while (true);
1253
1254 return false;
1255}
1256
1257status_t AudioFlinger::MixerThread::readyToRun()
1258{
1259 if (mSampleRate == 0) {
1260 LOGE("No working audio driver found.");
1261 return NO_INIT;
1262 }
1263 LOGI("AudioFlinger's thread ready to run for output %d", mOutputType);
1264 return NO_ERROR;
1265}
1266
1267void AudioFlinger::MixerThread::onFirstRef()
1268{
1269 const size_t SIZE = 256;
1270 char buffer[SIZE];
1271
1272 snprintf(buffer, SIZE, "Mixer Thread for output %d", mOutputType);
1273
1274 run(buffer, ANDROID_PRIORITY_URGENT_AUDIO);
1275}
1276
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001277// MixerThread::createTrack_l() must be called with AudioFlinger::mLock held
1278sp<AudioFlinger::MixerThread::Track> AudioFlinger::MixerThread::createTrack_l(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001279 const sp<AudioFlinger::Client>& client,
1280 int streamType,
1281 uint32_t sampleRate,
1282 int format,
1283 int channelCount,
1284 int frameCount,
1285 const sp<IMemory>& sharedBuffer,
1286 status_t *status)
1287{
1288 sp<Track> track;
1289 status_t lStatus;
1290
1291 // Resampler implementation limits input sampling rate to 2 x output sampling rate.
1292 if (sampleRate > MAX_SAMPLE_RATE || sampleRate > mSampleRate*2) {
1293 LOGE("Sample rate out of range: %d mSampleRate %d", sampleRate, mSampleRate);
1294 lStatus = BAD_VALUE;
1295 goto Exit;
1296 }
1297
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001298
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001299 if (mSampleRate == 0) {
1300 LOGE("Audio driver not initialized.");
1301 lStatus = NO_INIT;
1302 goto Exit;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001303 }
1304
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001305 track = new Track(this, client, streamType, sampleRate, format,
1306 channelCount, frameCount, sharedBuffer);
1307 if (track->getCblk() == NULL) {
1308 lStatus = NO_MEMORY;
1309 goto Exit;
1310 }
1311 mTracks.add(track);
1312 lStatus = NO_ERROR;
1313
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001314Exit:
1315 if(status) {
1316 *status = lStatus;
1317 }
1318 return track;
1319}
1320
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001321// getTracks_l() must be called with AudioFlinger::mLock held
1322void AudioFlinger::MixerThread::getTracks_l(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001323 SortedVector < sp<Track> >& tracks,
1324 SortedVector < wp<Track> >& activeTracks)
1325{
1326 size_t size = mTracks.size();
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001327 LOGV ("MixerThread::getTracks_l() for output %d, mTracks.size %d, mActiveTracks.size %d", mOutputType, mTracks.size(), mActiveTracks.size());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001328 for (size_t i = 0; i < size; i++) {
1329 sp<Track> t = mTracks[i];
1330 if (AudioSystem::routedToA2dpOutput(t->mStreamType)) {
1331 tracks.add(t);
1332 int j = mActiveTracks.indexOf(t);
1333 if (j >= 0) {
1334 t = mActiveTracks[j].promote();
1335 if (t != NULL) {
1336 activeTracks.add(t);
1337 }
1338 }
1339 }
1340 }
1341
1342 size = activeTracks.size();
1343 for (size_t i = 0; i < size; i++) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001344 removeActiveTrack_l(activeTracks[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001345 }
1346
1347 size = tracks.size();
1348 for (size_t i = 0; i < size; i++) {
1349 sp<Track> t = tracks[i];
1350 mTracks.remove(t);
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001351 deleteTrackName_l(t->name());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001352 }
1353}
1354
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001355// putTracks_l() must be called with AudioFlinger::mLock held
1356void AudioFlinger::MixerThread::putTracks_l(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001357 SortedVector < sp<Track> >& tracks,
1358 SortedVector < wp<Track> >& activeTracks)
1359{
1360
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001361 LOGV ("MixerThread::putTracks_l() for output %d, tracks.size %d, activeTracks.size %d", mOutputType, tracks.size(), activeTracks.size());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001362
1363 size_t size = tracks.size();
1364 for (size_t i = 0; i < size ; i++) {
1365 sp<Track> t = tracks[i];
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001366 int name = getTrackName_l();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001367
1368 if (name < 0) return;
1369
1370 t->mName = name;
1371 t->mMixerThread = this;
1372 mTracks.add(t);
1373
1374 int j = activeTracks.indexOf(t);
1375 if (j >= 0) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001376 addActiveTrack_l(t);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001377 }
1378 }
1379}
1380
1381uint32_t AudioFlinger::MixerThread::sampleRate() const
1382{
1383 return mSampleRate;
1384}
1385
1386int AudioFlinger::MixerThread::channelCount() const
1387{
1388 return mChannelCount;
1389}
1390
1391int AudioFlinger::MixerThread::format() const
1392{
1393 return mFormat;
1394}
1395
1396size_t AudioFlinger::MixerThread::frameCount() const
1397{
1398 return mFrameCount;
1399}
1400
1401uint32_t AudioFlinger::MixerThread::latency() const
1402{
1403 if (mOutput) {
1404 return mOutput->latency();
1405 }
1406 else {
1407 return 0;
1408 }
1409}
1410
1411status_t AudioFlinger::MixerThread::setMasterVolume(float value)
1412{
1413 mMasterVolume = value;
1414 return NO_ERROR;
1415}
1416
1417status_t AudioFlinger::MixerThread::setMasterMute(bool muted)
1418{
1419 mMasterMute = muted;
1420 return NO_ERROR;
1421}
1422
1423float AudioFlinger::MixerThread::masterVolume() const
1424{
1425 return mMasterVolume;
1426}
1427
1428bool AudioFlinger::MixerThread::masterMute() const
1429{
1430 return mMasterMute;
1431}
1432
1433status_t AudioFlinger::MixerThread::setStreamVolume(int stream, float value)
1434{
1435 mStreamTypes[stream].volume = value;
1436 return NO_ERROR;
1437}
1438
1439status_t AudioFlinger::MixerThread::setStreamMute(int stream, bool muted)
1440{
1441 mStreamTypes[stream].mute = muted;
1442 return NO_ERROR;
1443}
1444
1445float AudioFlinger::MixerThread::streamVolume(int stream) const
1446{
1447 return mStreamTypes[stream].volume;
1448}
1449
1450bool AudioFlinger::MixerThread::streamMute(int stream) const
1451{
1452 return mStreamTypes[stream].mute;
1453}
1454
1455bool AudioFlinger::MixerThread::isMusicActive() const
1456{
1457 size_t count = mActiveTracks.size();
1458 for (size_t i = 0 ; i < count ; ++i) {
1459 sp<Track> t = mActiveTracks[i].promote();
1460 if (t == 0) continue;
1461 Track* const track = t.get();
1462 if (t->mStreamType == AudioSystem::MUSIC)
1463 return true;
1464 }
1465 return false;
1466}
1467
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001468// addTrack_l() must be called with AudioFlinger::mLock held
1469status_t AudioFlinger::MixerThread::addTrack_l(const sp<Track>& track)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001470{
1471 status_t status = ALREADY_EXISTS;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001472
1473 // here the track could be either new, or restarted
1474 // in both cases "unstop" the track
1475 if (track->isPaused()) {
1476 track->mState = TrackBase::RESUMING;
1477 LOGV("PAUSED => RESUMING (%d)", track->name());
1478 } else {
1479 track->mState = TrackBase::ACTIVE;
1480 LOGV("? => ACTIVE (%d)", track->name());
1481 }
1482 // set retry count for buffer fill
1483 track->mRetryCount = kMaxTrackStartupRetries;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001484 if (mActiveTracks.indexOf(track) < 0) {
1485 // the track is newly added, make sure it fills up all its
1486 // buffers before playing. This is to ensure the client will
1487 // effectively get the latency it requested.
1488 track->mFillingUpStatus = Track::FS_FILLING;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001489 track->mResetDone = false;
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001490 addActiveTrack_l(track);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001491 status = NO_ERROR;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001492 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001493
1494 LOGV("mWaitWorkCV.broadcast");
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001495 mAudioFlinger->mWaitWorkCV.broadcast();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001496
1497 return status;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001498}
1499
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001500// removeTrack_l() must be called with AudioFlinger::mLock held
1501void AudioFlinger::MixerThread::removeTrack_l(wp<Track> track, int name)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001502{
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001503 sp<Track> t = track.promote();
1504 if (t!=NULL && (t->mState <= TrackBase::STOPPED)) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001505 t->reset();
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001506 deleteTrackName_l(name);
1507 removeActiveTrack_l(track);
1508 mAudioFlinger->mWaitWorkCV.broadcast();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001509 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001510}
1511
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001512// destroyTrack_l() must be called with AudioFlinger::mLock held
1513void AudioFlinger::MixerThread::destroyTrack_l(const sp<Track>& track)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001514{
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001515 track->mState = TrackBase::TERMINATED;
1516 if (mActiveTracks.indexOf(track) < 0) {
1517 LOGV("remove track (%d) and delete from mixer", track->name());
1518 mTracks.remove(track);
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001519 deleteTrackName_l(track->name());
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001520 }
1521}
1522
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001523// addActiveTrack_l() must be called with AudioFlinger::mLock held
1524void AudioFlinger::MixerThread::addActiveTrack_l(const wp<Track>& t)
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -08001525{
1526 mActiveTracks.add(t);
1527
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001528 // Force routing to speaker for certain stream types
1529 // The forced routing to speaker is managed by hardware mixer
1530 if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) {
1531 sp<Track> track = t.promote();
1532 if (track == NULL) return;
1533
1534 if (streamForcedToSpeaker(track->type())) {
1535 mAudioFlinger->handleForcedSpeakerRoute(ACTIVE_TRACK_ADDED);
1536 }
1537 }
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -08001538}
1539
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001540// removeActiveTrack_l() must be called with AudioFlinger::mLock held
1541void AudioFlinger::MixerThread::removeActiveTrack_l(const wp<Track>& t)
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -08001542{
1543 mActiveTracks.remove(t);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001544
1545 // Force routing to speaker for certain stream types
1546 // The forced routing to speaker is managed by hardware mixer
1547 if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) {
1548 sp<Track> track = t.promote();
1549 if (track == NULL) return;
1550
1551 if (streamForcedToSpeaker(track->type())) {
1552 mAudioFlinger->handleForcedSpeakerRoute(ACTIVE_TRACK_REMOVED);
1553 }
1554 }
1555}
1556
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001557// getTrackName_l() must be called with AudioFlinger::mLock held
1558int AudioFlinger::MixerThread::getTrackName_l()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001559{
1560 return mAudioMixer->getTrackName();
1561}
1562
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001563// deleteTrackName_l() must be called with AudioFlinger::mLock held
1564void AudioFlinger::MixerThread::deleteTrackName_l(int name)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001565{
1566 mAudioMixer->deleteTrackName(name);
1567}
1568
1569size_t AudioFlinger::MixerThread::getOutputFrameCount()
1570{
1571 return mOutput->bufferSize() / mOutput->channelCount() / sizeof(int16_t);
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -08001572}
1573
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001574// ----------------------------------------------------------------------------
1575
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001576// TrackBase constructor must be called with AudioFlinger::mLock held
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001577AudioFlinger::MixerThread::TrackBase::TrackBase(
1578 const sp<MixerThread>& mixerThread,
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001579 const sp<Client>& client,
1580 int streamType,
1581 uint32_t sampleRate,
1582 int format,
1583 int channelCount,
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001584 int frameCount,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001585 uint32_t flags,
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001586 const sp<IMemory>& sharedBuffer)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001587 : RefBase(),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001588 mMixerThread(mixerThread),
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001589 mClient(client),
1590 mStreamType(streamType),
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001591 mFrameCount(0),
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001592 mState(IDLE),
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001593 mClientTid(-1),
1594 mFormat(format),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001595 mFlags(flags & ~SYSTEM_FLAGS_MASK)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001596{
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001597 mName = mixerThread->getTrackName_l();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001598 LOGV("TrackBase contructor name %d, calling thread %d", mName, IPCThreadState::self()->getCallingPid());
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001599 if (mName < 0) {
1600 LOGE("no more track names availlable");
1601 return;
1602 }
1603
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001604 LOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size());
1605
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001606 // LOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001607 size_t size = sizeof(audio_track_cblk_t);
1608 size_t bufferSize = frameCount*channelCount*sizeof(int16_t);
1609 if (sharedBuffer == 0) {
1610 size += bufferSize;
1611 }
1612
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001613 if (client != NULL) {
1614 mCblkMemory = client->heap()->allocate(size);
1615 if (mCblkMemory != 0) {
1616 mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer());
1617 if (mCblk) { // construct the shared structure in-place.
1618 new(mCblk) audio_track_cblk_t();
1619 // clear all buffers
1620 mCblk->frameCount = frameCount;
The Android Open Source Project10592532009-03-18 17:39:46 -07001621 mCblk->sampleRate = (uint16_t)sampleRate;
1622 mCblk->channels = (uint16_t)channelCount;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001623 if (sharedBuffer == 0) {
1624 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
1625 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
1626 // Force underrun condition to avoid false underrun callback until first data is
1627 // written to buffer
1628 mCblk->flowControlFlag = 1;
1629 } else {
1630 mBuffer = sharedBuffer->pointer();
1631 }
1632 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001633 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001634 } else {
1635 LOGE("not enough memory for AudioTrack size=%u", size);
1636 client->heap()->dump("AudioTrack");
1637 return;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001638 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001639 } else {
1640 mCblk = (audio_track_cblk_t *)(new uint8_t[size]);
1641 if (mCblk) { // construct the shared structure in-place.
1642 new(mCblk) audio_track_cblk_t();
1643 // clear all buffers
1644 mCblk->frameCount = frameCount;
The Android Open Source Project10592532009-03-18 17:39:46 -07001645 mCblk->sampleRate = (uint16_t)sampleRate;
1646 mCblk->channels = (uint16_t)channelCount;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001647 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
1648 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
1649 // Force underrun condition to avoid false underrun callback until first data is
1650 // written to buffer
1651 mCblk->flowControlFlag = 1;
1652 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
1653 }
1654 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001655}
1656
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001657AudioFlinger::MixerThread::TrackBase::~TrackBase()
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001658{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001659 if (mCblk) {
1660 mCblk->~audio_track_cblk_t(); // destroy our shared-structure.
1661 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001662 mCblkMemory.clear(); // and free the shared memory
1663 mClient.clear();
1664}
1665
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001666void AudioFlinger::MixerThread::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001667{
1668 buffer->raw = 0;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001669 mFrameCount = buffer->frameCount;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001670 step();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001671 buffer->frameCount = 0;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001672}
1673
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001674bool AudioFlinger::MixerThread::TrackBase::step() {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001675 bool result;
1676 audio_track_cblk_t* cblk = this->cblk();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001677
1678 result = cblk->stepServer(mFrameCount);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001679 if (!result) {
1680 LOGV("stepServer failed acquiring cblk mutex");
1681 mFlags |= STEPSERVER_FAILED;
1682 }
1683 return result;
1684}
1685
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001686void AudioFlinger::MixerThread::TrackBase::reset() {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001687 audio_track_cblk_t* cblk = this->cblk();
1688
1689 cblk->user = 0;
1690 cblk->server = 0;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001691 cblk->userBase = 0;
1692 cblk->serverBase = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001693 mFlags &= (uint32_t)(~SYSTEM_FLAGS_MASK);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001694 LOGV("TrackBase::reset");
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001695}
1696
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001697sp<IMemory> AudioFlinger::MixerThread::TrackBase::getCblk() const
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001698{
1699 return mCblkMemory;
1700}
1701
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001702int AudioFlinger::MixerThread::TrackBase::sampleRate() const {
The Android Open Source Project10592532009-03-18 17:39:46 -07001703 return (int)mCblk->sampleRate;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001704}
1705
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001706int AudioFlinger::MixerThread::TrackBase::channelCount() const {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001707 return mCblk->channels;
1708}
1709
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001710void* AudioFlinger::MixerThread::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001711 audio_track_cblk_t* cblk = this->cblk();
1712 int16_t *bufferStart = (int16_t *)mBuffer + (offset-cblk->serverBase)*cblk->channels;
1713 int16_t *bufferEnd = bufferStart + frames * cblk->channels;
1714
1715 // Check validity of returned pointer in case the track control block would have been corrupted.
The Android Open Source Project10592532009-03-18 17:39:46 -07001716 if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd ||
1717 cblk->channels == 2 && ((unsigned long)bufferStart & 3) ) {
1718 LOGE("TrackBase::getBuffer buffer out of range:\n start: %p, end %p , mBuffer %p mBufferEnd %p\n \
1719 server %d, serverBase %d, user %d, userBase %d, channels %d",
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001720 bufferStart, bufferEnd, mBuffer, mBufferEnd,
The Android Open Source Project10592532009-03-18 17:39:46 -07001721 cblk->server, cblk->serverBase, cblk->user, cblk->userBase, cblk->channels);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001722 return 0;
1723 }
1724
1725 return bufferStart;
1726}
1727
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001728// ----------------------------------------------------------------------------
1729
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001730// Track constructor must be called with AudioFlinger::mLock held
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001731AudioFlinger::MixerThread::Track::Track(
1732 const sp<MixerThread>& mixerThread,
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001733 const sp<Client>& client,
1734 int streamType,
1735 uint32_t sampleRate,
1736 int format,
1737 int channelCount,
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001738 int frameCount,
1739 const sp<IMemory>& sharedBuffer)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001740 : TrackBase(mixerThread, client, streamType, sampleRate, format, channelCount, frameCount, 0, sharedBuffer)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001741{
1742 mVolume[0] = 1.0f;
1743 mVolume[1] = 1.0f;
1744 mMute = false;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001745 mSharedBuffer = sharedBuffer;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001746}
1747
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001748AudioFlinger::MixerThread::Track::~Track()
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001749{
1750 wp<Track> weak(this); // never create a strong ref from the dtor
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001751 Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001752 mState = TERMINATED;
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001753 mMixerThread->removeTrack_l(weak, mName);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001754}
1755
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001756void AudioFlinger::MixerThread::Track::destroy()
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001757{
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001758 // NOTE: destroyTrack_l() can remove a strong reference to this Track
1759 // by removing it from mTracks vector, so there is a risk that this Tracks's
1760 // desctructor is called. As the destructor needs to lock AudioFlinger::mLock,
1761 // we must acquire a strong reference on this Track before locking AudioFlinger::mLock
1762 // here so that the destructor is called only when exiting this function.
1763 // On the other hand, as long as Track::destroy() is only called by
1764 // TrackHandle destructor, the TrackHandle still holds a strong ref on
1765 // this Track with its member mTrack.
1766 sp<Track> keep(this);
1767 { // scope for AudioFlinger::mLock
1768 Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
1769 mMixerThread->destroyTrack_l(this);
1770 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001771}
1772
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001773void AudioFlinger::MixerThread::Track::dump(char* buffer, size_t size)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001774{
1775 snprintf(buffer, size, " %5d %5d %3u %3u %3u %3u %1d %1d %1d %5u %5u %5u %04x %04x\n",
1776 mName - AudioMixer::TRACK0,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001777 (mClient == NULL) ? getpid() : mClient->pid(),
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001778 mStreamType,
1779 mFormat,
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001780 mCblk->channels,
1781 mFrameCount,
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001782 mState,
1783 mMute,
1784 mFillingUpStatus,
1785 mCblk->sampleRate,
1786 mCblk->volume[0],
1787 mCblk->volume[1],
1788 mCblk->server,
1789 mCblk->user);
1790}
1791
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001792status_t AudioFlinger::MixerThread::Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001793{
1794 audio_track_cblk_t* cblk = this->cblk();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001795 uint32_t framesReady;
1796 uint32_t framesReq = buffer->frameCount;
1797
1798 // Check if last stepServer failed, try to step now
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001799 if (mFlags & TrackBase::STEPSERVER_FAILED) {
1800 if (!step()) goto getNextBuffer_exit;
1801 LOGV("stepServer recovered");
1802 mFlags &= ~TrackBase::STEPSERVER_FAILED;
1803 }
1804
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001805 framesReady = cblk->framesReady();
1806
1807 if (LIKELY(framesReady)) {
1808 uint32_t s = cblk->server;
1809 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
1810
1811 bufferEnd = (cblk->loopEnd < bufferEnd) ? cblk->loopEnd : bufferEnd;
1812 if (framesReq > framesReady) {
1813 framesReq = framesReady;
1814 }
1815 if (s + framesReq > bufferEnd) {
1816 framesReq = bufferEnd - s;
1817 }
1818
1819 buffer->raw = getBuffer(s, framesReq);
1820 if (buffer->raw == 0) goto getNextBuffer_exit;
1821
1822 buffer->frameCount = framesReq;
1823 return NO_ERROR;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001824 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001825
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001826getNextBuffer_exit:
1827 buffer->raw = 0;
1828 buffer->frameCount = 0;
1829 return NOT_ENOUGH_DATA;
1830}
1831
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001832bool AudioFlinger::MixerThread::Track::isReady() const {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001833 if (mFillingUpStatus != FS_FILLING) return true;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001834
1835 if (mCblk->framesReady() >= mCblk->frameCount ||
1836 mCblk->forceReady) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001837 mFillingUpStatus = FS_FILLED;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001838 mCblk->forceReady = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001839 LOGV("Track::isReady() track %d for output %d", mName, mMixerThread->mOutputType);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001840 return true;
1841 }
1842 return false;
1843}
1844
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001845status_t AudioFlinger::MixerThread::Track::start()
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001846{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001847 LOGV("start(%d), calling thread %d for output %d", mName, IPCThreadState::self()->getCallingPid(), mMixerThread->mOutputType);
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001848 Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
1849 mMixerThread->addTrack_l(this);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001850 return NO_ERROR;
1851}
1852
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001853void AudioFlinger::MixerThread::Track::stop()
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001854{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001855 LOGV("stop(%d), calling thread %d for output %d", mName, IPCThreadState::self()->getCallingPid(), mMixerThread->mOutputType);
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001856 Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001857 if (mState > STOPPED) {
1858 mState = STOPPED;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001859 // If the track is not active (PAUSED and buffers full), flush buffers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001860 if (mMixerThread->mActiveTracks.indexOf(this) < 0) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001861 reset();
1862 }
1863 LOGV("(> STOPPED) => STOPPED (%d)", mName);
1864 }
1865}
1866
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001867void AudioFlinger::MixerThread::Track::pause()
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001868{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001869 LOGV("pause(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001870 Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001871 if (mState == ACTIVE || mState == RESUMING) {
1872 mState = PAUSING;
1873 LOGV("ACTIVE/RESUMING => PAUSING (%d)", mName);
1874 }
1875}
1876
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001877void AudioFlinger::MixerThread::Track::flush()
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001878{
1879 LOGV("flush(%d)", mName);
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001880 Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001881 if (mState != STOPPED && mState != PAUSED && mState != PAUSING) {
1882 return;
1883 }
1884 // No point remaining in PAUSED state after a flush => go to
1885 // STOPPED state
1886 mState = STOPPED;
1887
The Android Open Source Project10592532009-03-18 17:39:46 -07001888 mCblk->lock.lock();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001889 // NOTE: reset() will reset cblk->user and cblk->server with
1890 // the risk that at the same time, the AudioMixer is trying to read
1891 // data. In this case, getNextBuffer() would return a NULL pointer
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001892 // as audio buffer => the AudioMixer code MUST always test that pointer
1893 // returned by getNextBuffer() is not NULL!
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001894 reset();
The Android Open Source Project10592532009-03-18 17:39:46 -07001895 mCblk->lock.unlock();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001896}
1897
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001898void AudioFlinger::MixerThread::Track::reset()
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001899{
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001900 // Do not reset twice to avoid discarding data written just after a flush and before
1901 // the audioflinger thread detects the track is stopped.
1902 if (!mResetDone) {
1903 TrackBase::reset();
1904 // Force underrun condition to avoid false underrun callback until first data is
1905 // written to buffer
1906 mCblk->flowControlFlag = 1;
1907 mCblk->forceReady = 0;
1908 mFillingUpStatus = FS_FILLING;
1909 mResetDone = true;
1910 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001911}
1912
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001913void AudioFlinger::MixerThread::Track::mute(bool muted)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001914{
1915 mMute = muted;
1916}
1917
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001918void AudioFlinger::MixerThread::Track::setVolume(float left, float right)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001919{
1920 mVolume[0] = left;
1921 mVolume[1] = right;
1922}
1923
1924// ----------------------------------------------------------------------------
1925
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001926// RecordTrack constructor must be called with AudioFlinger::mLock held
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001927AudioFlinger::MixerThread::RecordTrack::RecordTrack(
1928 const sp<MixerThread>& mixerThread,
1929 const sp<Client>& client,
1930 int streamType,
1931 uint32_t sampleRate,
1932 int format,
1933 int channelCount,
1934 int frameCount,
1935 uint32_t flags)
1936 : TrackBase(mixerThread, client, streamType, sampleRate, format,
1937 channelCount, frameCount, flags, 0),
1938 mOverflow(false)
1939{
1940}
1941
1942AudioFlinger::MixerThread::RecordTrack::~RecordTrack()
1943{
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001944 Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
1945 mMixerThread->deleteTrackName_l(mName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001946}
1947
1948status_t AudioFlinger::MixerThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
1949{
1950 audio_track_cblk_t* cblk = this->cblk();
1951 uint32_t framesAvail;
1952 uint32_t framesReq = buffer->frameCount;
1953
1954 // Check if last stepServer failed, try to step now
1955 if (mFlags & TrackBase::STEPSERVER_FAILED) {
1956 if (!step()) goto getNextBuffer_exit;
1957 LOGV("stepServer recovered");
1958 mFlags &= ~TrackBase::STEPSERVER_FAILED;
1959 }
1960
1961 framesAvail = cblk->framesAvailable_l();
1962
1963 if (LIKELY(framesAvail)) {
1964 uint32_t s = cblk->server;
1965 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
1966
1967 if (framesReq > framesAvail) {
1968 framesReq = framesAvail;
1969 }
1970 if (s + framesReq > bufferEnd) {
1971 framesReq = bufferEnd - s;
1972 }
1973
1974 buffer->raw = getBuffer(s, framesReq);
1975 if (buffer->raw == 0) goto getNextBuffer_exit;
1976
1977 buffer->frameCount = framesReq;
1978 return NO_ERROR;
1979 }
1980
1981getNextBuffer_exit:
1982 buffer->raw = 0;
1983 buffer->frameCount = 0;
1984 return NOT_ENOUGH_DATA;
1985}
1986
1987status_t AudioFlinger::MixerThread::RecordTrack::start()
1988{
1989 return mMixerThread->mAudioFlinger->startRecord(this);
1990}
1991
1992void AudioFlinger::MixerThread::RecordTrack::stop()
1993{
1994 mMixerThread->mAudioFlinger->stopRecord(this);
1995 TrackBase::reset();
1996 // Force overerrun condition to avoid false overrun callback until first data is
1997 // read from buffer
1998 mCblk->flowControlFlag = 1;
1999}
2000
2001
2002// ----------------------------------------------------------------------------
2003
2004AudioFlinger::MixerThread::OutputTrack::OutputTrack(
2005 const sp<MixerThread>& mixerThread,
2006 uint32_t sampleRate,
2007 int format,
2008 int channelCount,
2009 int frameCount)
2010 : Track(mixerThread, NULL, AudioSystem::SYSTEM, sampleRate, format, channelCount, frameCount, NULL),
2011 mOutputMixerThread(mixerThread)
2012{
2013
2014 mCblk->out = 1;
2015 mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
2016 mCblk->volume[0] = mCblk->volume[1] = 0x1000;
2017 mOutBuffer.frameCount = 0;
2018 mCblk->bufferTimeoutMs = 10;
2019
2020 LOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, mCblk->frameCount %d, mCblk->sampleRate %d, mCblk->channels %d mBufferEnd %p",
2021 mCblk, mBuffer, mCblk->buffers, mCblk->frameCount, mCblk->sampleRate, mCblk->channels, mBufferEnd);
2022
2023}
2024
2025AudioFlinger::MixerThread::OutputTrack::~OutputTrack()
2026{
2027 stop();
2028}
2029
2030status_t AudioFlinger::MixerThread::OutputTrack::start()
2031{
2032 status_t status = Track::start();
2033
2034 mRetryCount = 127;
2035 return status;
2036}
2037
2038void AudioFlinger::MixerThread::OutputTrack::stop()
2039{
2040 Track::stop();
2041 clearBufferQueue();
2042 mOutBuffer.frameCount = 0;
2043}
2044
2045void AudioFlinger::MixerThread::OutputTrack::write(int16_t* data, uint32_t frames)
2046{
2047 Buffer *pInBuffer;
2048 Buffer inBuffer;
2049 uint32_t channels = mCblk->channels;
2050
2051 inBuffer.frameCount = frames;
2052 inBuffer.i16 = data;
2053
2054 if (mCblk->user == 0) {
2055 if (mOutputMixerThread->isMusicActive()) {
2056 mCblk->forceReady = 1;
2057 LOGV("OutputTrack::start() force ready");
2058 } else if (mCblk->frameCount > frames){
2059 if (mBufferQueue.size() < kMaxOutputTrackBuffers) {
2060 uint32_t startFrames = (mCblk->frameCount - frames);
2061 LOGV("OutputTrack::start() write %d frames", startFrames);
2062 pInBuffer = new Buffer;
2063 pInBuffer->mBuffer = new int16_t[startFrames * channels];
2064 pInBuffer->frameCount = startFrames;
2065 pInBuffer->i16 = pInBuffer->mBuffer;
2066 memset(pInBuffer->raw, 0, startFrames * channels * sizeof(int16_t));
2067 mBufferQueue.add(pInBuffer);
2068 } else {
2069 LOGW ("OutputTrack::write() no more buffers");
2070 }
2071 }
2072 }
2073
2074 while (1) {
2075 // First write pending buffers, then new data
2076 if (mBufferQueue.size()) {
2077 pInBuffer = mBufferQueue.itemAt(0);
2078 } else {
2079 pInBuffer = &inBuffer;
2080 }
2081
2082 if (pInBuffer->frameCount == 0) {
2083 break;
2084 }
2085
2086 if (mOutBuffer.frameCount == 0) {
2087 mOutBuffer.frameCount = pInBuffer->frameCount;
2088 if (obtainBuffer(&mOutBuffer) == (status_t)AudioTrack::NO_MORE_BUFFERS) {
2089 break;
2090 }
2091 }
2092
2093 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount : pInBuffer->frameCount;
2094 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * channels * sizeof(int16_t));
2095 mCblk->stepUser(outFrames);
2096 pInBuffer->frameCount -= outFrames;
2097 pInBuffer->i16 += outFrames * channels;
2098 mOutBuffer.frameCount -= outFrames;
2099 mOutBuffer.i16 += outFrames * channels;
2100
2101 if (pInBuffer->frameCount == 0) {
2102 if (mBufferQueue.size()) {
2103 mBufferQueue.removeAt(0);
2104 delete [] pInBuffer->mBuffer;
2105 delete pInBuffer;
2106 } else {
2107 break;
2108 }
2109 }
2110 }
2111
2112 // If we could not write all frames, allocate a buffer and queue it for next time.
2113 if (inBuffer.frameCount) {
2114 if (mBufferQueue.size() < kMaxOutputTrackBuffers) {
2115 pInBuffer = new Buffer;
2116 pInBuffer->mBuffer = new int16_t[inBuffer.frameCount * channels];
2117 pInBuffer->frameCount = inBuffer.frameCount;
2118 pInBuffer->i16 = pInBuffer->mBuffer;
2119 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * channels * sizeof(int16_t));
2120 mBufferQueue.add(pInBuffer);
2121 } else {
2122 LOGW("OutputTrack::write() no more buffers");
2123 }
2124 }
2125
2126 // Calling write() with a 0 length buffer, means that no more data will be written:
2127 // If no more buffers are pending, fill output track buffer to make sure it is started
2128 // by output mixer.
2129 if (frames == 0 && mBufferQueue.size() == 0 && mCblk->user < mCblk->frameCount) {
2130 frames = mCblk->frameCount - mCblk->user;
2131 pInBuffer = new Buffer;
2132 pInBuffer->mBuffer = new int16_t[frames * channels];
2133 pInBuffer->frameCount = frames;
2134 pInBuffer->i16 = pInBuffer->mBuffer;
2135 memset(pInBuffer->raw, 0, frames * channels * sizeof(int16_t));
2136 mBufferQueue.add(pInBuffer);
2137 }
2138
2139}
2140
2141status_t AudioFlinger::MixerThread::OutputTrack::obtainBuffer(AudioBufferProvider::Buffer* buffer)
2142{
2143 int active;
2144 int timeout = 0;
2145 status_t result;
2146 audio_track_cblk_t* cblk = mCblk;
2147 uint32_t framesReq = buffer->frameCount;
2148
2149 LOGV("OutputTrack::obtainBuffer user %d, server %d", cblk->user, cblk->server);
2150 buffer->frameCount = 0;
2151
2152 uint32_t framesAvail = cblk->framesAvailable();
2153
2154 if (framesAvail == 0) {
2155 return AudioTrack::NO_MORE_BUFFERS;
2156 }
2157
2158 if (framesReq > framesAvail) {
2159 framesReq = framesAvail;
2160 }
2161
2162 uint32_t u = cblk->user;
2163 uint32_t bufferEnd = cblk->userBase + cblk->frameCount;
2164
2165 if (u + framesReq > bufferEnd) {
2166 framesReq = bufferEnd - u;
2167 }
2168
2169 buffer->frameCount = framesReq;
2170 buffer->raw = (void *)cblk->buffer(u);
2171 return NO_ERROR;
2172}
2173
2174
2175void AudioFlinger::MixerThread::OutputTrack::clearBufferQueue()
2176{
2177 size_t size = mBufferQueue.size();
2178 Buffer *pBuffer;
2179
2180 for (size_t i = 0; i < size; i++) {
2181 pBuffer = mBufferQueue.itemAt(i);
2182 delete [] pBuffer->mBuffer;
2183 delete pBuffer;
2184 }
2185 mBufferQueue.clear();
2186}
2187
2188// ----------------------------------------------------------------------------
2189
2190AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
2191 : RefBase(),
2192 mAudioFlinger(audioFlinger),
2193 mMemoryDealer(new MemoryDealer(1024*1024)),
2194 mPid(pid)
2195{
2196 // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
2197}
2198
2199AudioFlinger::Client::~Client()
2200{
2201 mAudioFlinger->removeClient(mPid);
2202}
2203
2204const sp<MemoryDealer>& AudioFlinger::Client::heap() const
2205{
2206 return mMemoryDealer;
2207}
2208
2209// ----------------------------------------------------------------------------
2210
2211AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::MixerThread::Track>& track)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002212 : BnAudioTrack(),
2213 mTrack(track)
2214{
2215}
2216
2217AudioFlinger::TrackHandle::~TrackHandle() {
2218 // just stop the track on deletion, associated resources
2219 // will be freed from the main thread once all pending buffers have
2220 // been played. Unless it's not in the active track list, in which
2221 // case we free everything now...
2222 mTrack->destroy();
2223}
2224
2225status_t AudioFlinger::TrackHandle::start() {
2226 return mTrack->start();
2227}
2228
2229void AudioFlinger::TrackHandle::stop() {
2230 mTrack->stop();
2231}
2232
2233void AudioFlinger::TrackHandle::flush() {
2234 mTrack->flush();
2235}
2236
2237void AudioFlinger::TrackHandle::mute(bool e) {
2238 mTrack->mute(e);
2239}
2240
2241void AudioFlinger::TrackHandle::pause() {
2242 mTrack->pause();
2243}
2244
2245void AudioFlinger::TrackHandle::setVolume(float left, float right) {
2246 mTrack->setVolume(left, right);
2247}
2248
2249sp<IMemory> AudioFlinger::TrackHandle::getCblk() const {
2250 return mTrack->getCblk();
2251}
2252
2253status_t AudioFlinger::TrackHandle::onTransact(
2254 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
2255{
2256 return BnAudioTrack::onTransact(code, data, reply, flags);
2257}
2258
2259// ----------------------------------------------------------------------------
2260
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002261sp<IAudioRecord> AudioFlinger::openRecord(
2262 pid_t pid,
2263 int streamType,
2264 uint32_t sampleRate,
2265 int format,
2266 int channelCount,
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002267 int frameCount,
2268 uint32_t flags,
2269 status_t *status)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002270{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002271 sp<MixerThread::RecordTrack> recordTrack;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002272 sp<RecordHandle> recordHandle;
2273 sp<Client> client;
2274 wp<Client> wclient;
2275 AudioStreamIn* input = 0;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002276 int inFrameCount;
2277 size_t inputBufferSize;
2278 status_t lStatus;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002279
2280 // check calling permissions
2281 if (!recordingAllowed()) {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002282 lStatus = PERMISSION_DENIED;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002283 goto Exit;
2284 }
2285
2286 if (uint32_t(streamType) >= AudioRecord::NUM_STREAM_TYPES) {
2287 LOGE("invalid stream type");
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002288 lStatus = BAD_VALUE;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002289 goto Exit;
2290 }
2291
2292 if (sampleRate > MAX_SAMPLE_RATE) {
2293 LOGE("Sample rate out of range");
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002294 lStatus = BAD_VALUE;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002295 goto Exit;
2296 }
2297
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002298 if (mAudioRecordThread == 0) {
2299 LOGE("Audio record thread not started");
2300 lStatus = NO_INIT;
2301 goto Exit;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002302 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002303
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002304
2305 // Check that audio input stream accepts requested audio parameters
2306 inputBufferSize = mAudioHardware->getInputBufferSize(sampleRate, format, channelCount);
2307 if (inputBufferSize == 0) {
2308 lStatus = BAD_VALUE;
2309 LOGE("Bad audio input parameters: sampling rate %u, format %d, channels %d", sampleRate, format, channelCount);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002310 goto Exit;
2311 }
2312
2313 // add client to list
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07002314 { // scope for mLock
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002315 Mutex::Autolock _l(mLock);
2316 wclient = mClients.valueFor(pid);
2317 if (wclient != NULL) {
2318 client = wclient.promote();
2319 } else {
2320 client = new Client(this, pid);
2321 mClients.add(pid, client);
2322 }
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07002323
2324 // frameCount must be a multiple of input buffer size
2325 inFrameCount = inputBufferSize/channelCount/sizeof(short);
2326 frameCount = ((frameCount - 1)/inFrameCount + 1) * inFrameCount;
2327
2328 // create new record track. The record track uses one track in mHardwareMixerThread by convention.
2329 recordTrack = new MixerThread::RecordTrack(mHardwareMixerThread, client, streamType, sampleRate,
2330 format, channelCount, frameCount, flags);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002331 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002332 if (recordTrack->getCblk() == NULL) {
2333 recordTrack.clear();
2334 lStatus = NO_MEMORY;
2335 goto Exit;
2336 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002337
2338 // return to handle to client
2339 recordHandle = new RecordHandle(recordTrack);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002340 lStatus = NO_ERROR;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002341
2342Exit:
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002343 if (status) {
2344 *status = lStatus;
2345 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002346 return recordHandle;
2347}
2348
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002349status_t AudioFlinger::startRecord(MixerThread::RecordTrack* recordTrack) {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002350 if (mAudioRecordThread != 0) {
2351 return mAudioRecordThread->start(recordTrack);
2352 }
2353 return NO_INIT;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002354}
2355
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002356void AudioFlinger::stopRecord(MixerThread::RecordTrack* recordTrack) {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002357 if (mAudioRecordThread != 0) {
2358 mAudioRecordThread->stop(recordTrack);
2359 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002360}
2361
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002362// ----------------------------------------------------------------------------
2363
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002364AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::MixerThread::RecordTrack>& recordTrack)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002365 : BnAudioRecord(),
2366 mRecordTrack(recordTrack)
2367{
2368}
2369
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002370AudioFlinger::RecordHandle::~RecordHandle() {
2371 stop();
2372}
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002373
2374status_t AudioFlinger::RecordHandle::start() {
2375 LOGV("RecordHandle::start()");
2376 return mRecordTrack->start();
2377}
2378
2379void AudioFlinger::RecordHandle::stop() {
2380 LOGV("RecordHandle::stop()");
2381 mRecordTrack->stop();
2382}
2383
2384sp<IMemory> AudioFlinger::RecordHandle::getCblk() const {
2385 return mRecordTrack->getCblk();
2386}
2387
2388status_t AudioFlinger::RecordHandle::onTransact(
2389 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
2390{
2391 return BnAudioRecord::onTransact(code, data, reply, flags);
2392}
2393
2394// ----------------------------------------------------------------------------
2395
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07002396AudioFlinger::AudioRecordThread::AudioRecordThread(AudioHardwareInterface* audioHardware,
2397 const sp<AudioFlinger>& audioFlinger) :
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002398 mAudioHardware(audioHardware),
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07002399 mAudioFlinger(audioFlinger),
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002400 mActive(false)
2401{
2402}
2403
2404AudioFlinger::AudioRecordThread::~AudioRecordThread()
2405{
2406}
2407
2408bool AudioFlinger::AudioRecordThread::threadLoop()
2409{
2410 LOGV("AudioRecordThread: start record loop");
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002411 AudioBufferProvider::Buffer buffer;
2412 int inBufferSize = 0;
2413 int inFrameCount = 0;
2414 AudioStreamIn* input = 0;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002415
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002416 mActive = 0;
2417
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002418 // start recording
2419 while (!exitPending()) {
2420 if (!mActive) {
2421 mLock.lock();
2422 if (!mActive && !exitPending()) {
2423 LOGV("AudioRecordThread: loop stopping");
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002424 if (input) {
2425 delete input;
2426 input = 0;
2427 }
2428 mRecordTrack.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002429 mStopped.signal();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002430
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002431 mWaitWorkCV.wait(mLock);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002432
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002433 LOGV("AudioRecordThread: loop starting");
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002434 if (mRecordTrack != 0) {
2435 input = mAudioHardware->openInputStream(mRecordTrack->format(),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002436 mRecordTrack->channelCount(),
2437 mRecordTrack->sampleRate(),
2438 &mStartStatus,
2439 (AudioSystem::audio_in_acoustics)(mRecordTrack->mFlags >> 16));
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002440 if (input != 0) {
2441 inBufferSize = input->bufferSize();
2442 inFrameCount = inBufferSize/input->frameSize();
2443 }
2444 } else {
2445 mStartStatus = NO_INIT;
2446 }
2447 if (mStartStatus !=NO_ERROR) {
2448 LOGW("record start failed, status %d", mStartStatus);
2449 mActive = false;
2450 mRecordTrack.clear();
2451 }
2452 mWaitWorkCV.signal();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002453 }
2454 mLock.unlock();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002455 } else if (mRecordTrack != 0) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002456
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002457 buffer.frameCount = inFrameCount;
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07002458 if (LIKELY(mRecordTrack->getNextBuffer(&buffer) == NO_ERROR &&
2459 (int)buffer.frameCount == inFrameCount)) {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002460 LOGV("AudioRecordThread read: %d frames", buffer.frameCount);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002461 ssize_t bytesRead = input->read(buffer.raw, inBufferSize);
2462 if (bytesRead < 0) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002463 LOGE("Error reading audio input");
2464 sleep(1);
2465 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002466 mRecordTrack->releaseBuffer(&buffer);
2467 mRecordTrack->overflow();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002468 }
2469
2470 // client isn't retrieving buffers fast enough
2471 else {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002472 if (!mRecordTrack->setOverflow())
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002473 LOGW("AudioRecordThread: buffer overflow");
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002474 // Release the processor for a while before asking for a new buffer.
2475 // This will give the application more chance to read from the buffer and
2476 // clear the overflow.
2477 usleep(5000);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002478 }
2479 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002480 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002481
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002482
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002483 if (input) {
2484 delete input;
2485 }
2486 mRecordTrack.clear();
2487
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002488 return false;
2489}
2490
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002491status_t AudioFlinger::AudioRecordThread::start(MixerThread::RecordTrack* recordTrack)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002492{
2493 LOGV("AudioRecordThread::start");
2494 AutoMutex lock(&mLock);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002495 mActive = true;
2496 // If starting the active track, just reset mActive in case a stop
2497 // was pending and exit
2498 if (recordTrack == mRecordTrack.get()) return NO_ERROR;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002499
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002500 if (mRecordTrack != 0) return -EBUSY;
2501
2502 mRecordTrack = recordTrack;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002503
2504 // signal thread to start
2505 LOGV("Signal record thread");
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002506 mWaitWorkCV.signal();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002507 mWaitWorkCV.wait(mLock);
2508 LOGV("Record started, status %d", mStartStatus);
2509 return mStartStatus;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002510}
2511
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002512void AudioFlinger::AudioRecordThread::stop(MixerThread::RecordTrack* recordTrack) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002513 LOGV("AudioRecordThread::stop");
2514 AutoMutex lock(&mLock);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002515 if (mActive && (recordTrack == mRecordTrack.get())) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002516 mActive = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002517 mStopped.wait(mLock);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002518 }
2519}
2520
2521void AudioFlinger::AudioRecordThread::exit()
2522{
2523 LOGV("AudioRecordThread::exit");
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002524 {
2525 AutoMutex lock(&mLock);
2526 requestExit();
2527 mWaitWorkCV.signal();
2528 }
2529 requestExitAndWait();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002530}
2531
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002532status_t AudioFlinger::AudioRecordThread::dump(int fd, const Vector<String16>& args)
2533{
2534 const size_t SIZE = 256;
2535 char buffer[SIZE];
2536 String8 result;
2537 pid_t pid = 0;
2538
2539 if (mRecordTrack != 0 && mRecordTrack->mClient != 0) {
2540 snprintf(buffer, SIZE, "Record client pid: %d\n", mRecordTrack->mClient->pid());
2541 result.append(buffer);
2542 } else {
2543 result.append("No record client\n");
2544 }
2545 write(fd, result.string(), result.size());
2546 return NO_ERROR;
2547}
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002548
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002549status_t AudioFlinger::onTransact(
2550 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
2551{
2552 return BnAudioFlinger::onTransact(code, data, reply, flags);
2553}
2554
2555// ----------------------------------------------------------------------------
2556void AudioFlinger::instantiate() {
2557 defaultServiceManager()->addService(
2558 String16("media.audio_flinger"), new AudioFlinger());
2559}
2560
2561}; // namespace android