blob: 4ac9fb23b833c481de0b6732fef03054a47af335 [file] [log] [blame]
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001/* //device/include/server/AudioFlinger/AudioFlinger.cpp
2**
3** Copyright 2007, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18
19#define LOG_TAG "AudioFlinger"
20//#define LOG_NDEBUG 0
21
22#include <math.h>
23#include <signal.h>
24#include <sys/time.h>
25#include <sys/resource.h>
26
27#include <utils/IServiceManager.h>
28#include <utils/Log.h>
29#include <utils/Parcel.h>
30#include <utils/IPCThreadState.h>
31#include <utils/String16.h>
32#include <utils/threads.h>
33
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -080034#include <cutils/properties.h>
35
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070036#include <media/AudioTrack.h>
37#include <media/AudioRecord.h>
38
39#include <private/media/AudioTrackShared.h>
40
The Android Open Source Project8a7a6752009-01-15 16:12:10 -080041#include <hardware_legacy/AudioHardwareInterface.h>
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070042
43#include "AudioMixer.h"
44#include "AudioFlinger.h"
45
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -080046#ifdef WITH_A2DP
47#include "A2dpAudioInterface.h"
48#endif
49
The Android Open Source Projectedbf3b62009-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 Project7c1b96a2008-10-21 07:00:00 -070059namespace android {
60
The Android Open Source Project4f68be12009-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 Projecte09fd9e2008-12-17 18:05:43 -080064//static const nsecs_t kStandbyTimeInNsecs = seconds(3);
The Android Open Source Project7c1b96a2008-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 Projectedbf3b62009-03-03 19:31:44 -080074static const int kStartSleepTime = 30000;
75static const int kStopSleepTime = 30000;
76
The Android Open Source Project22f8def2009-03-09 11:52:12 -070077static const int kDumpLockRetries = 50;
78static const int kDumpLockSleep = 20000;
79
The Android Open Source Projectedbf3b62009-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 Project7c1b96a2008-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 Projectedbf3b62009-03-03 19:31:44 -0800123 : BnAudioFlinger(),
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700124 mAudioHardware(0), mA2dpAudioInterface(0), mA2dpEnabled(false), mNotifyA2dpChange(false),
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700125 mForcedSpeakerCount(0), mA2dpDisableCount(0), mA2dpSuppressed(false), mForcedRoute(0),
126 mRouteRestoreTime(0), mMusicMuteSaved(false)
The Android Open Source Project7c1b96a2008-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 Projecte09fd9e2008-12-17 18:05:43 -0800134 status_t status;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800135 AudioStreamOut *hwOutput = mAudioHardware->openOutputStream(AudioSystem::PCM_16_BIT, 0, 0, &status);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700136 mHardwareStatus = AUDIO_HW_IDLE;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800137 if (hwOutput) {
138 mHardwareMixerThread = new MixerThread(this, hwOutput, AudioSystem::AUDIO_OUTPUT_HARDWARE);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700139 } else {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800140 LOGE("Failed to initialize hardware output stream, status: %d", status);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700141 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800142
143#ifdef WITH_A2DP
144 // Create A2DP interface
145 mA2dpAudioInterface = new A2dpAudioInterface();
The Android Open Source Projectedbf3b62009-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 Projecte09fd9e2008-12-17 18:05:43 -0800161#endif
The Android Open Source Projectedbf3b62009-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 Projecte09fd9e2008-12-17 18:05:43 -0800172 // Start record thread
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700173 mAudioRecordThread = new AudioRecordThread(mAudioHardware, this);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800174 if (mAudioRecordThread != 0) {
175 mAudioRecordThread->run("AudioRecordThread", PRIORITY_URGENT_AUDIO);
176 }
177 } else {
The Android Open Source Project7c1b96a2008-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 Projecte09fd9e2008-12-17 18:05:43 -0800184 if (mAudioRecordThread != 0) {
185 mAudioRecordThread->exit();
186 mAudioRecordThread.clear();
187 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800188 mHardwareMixerThread.clear();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700189 delete mAudioHardware;
The Android Open Source Project27629322009-01-09 17:51:23 -0800190 // deleting mA2dpAudioInterface also deletes mA2dpOutput;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800191#ifdef WITH_A2DP
192 mA2dpMixerThread.clear();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800193 delete mA2dpAudioInterface;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800194#endif
The Android Open Source Project27629322009-01-09 17:51:23 -0800195}
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800196
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700197
The Android Open Source Projecte41dd752009-01-22 00:13:42 -0800198#ifdef WITH_A2DP
The Android Open Source Project22f8def2009-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 Project4f68be12009-03-18 17:39:46 -0700201{
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700202 SortedVector < sp<MixerThread::Track> > tracks;
203 SortedVector < wp<MixerThread::Track> > activeTracks;
204
The Android Open Source Projectedbf3b62009-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 Project22f8def2009-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 Projecte41dd752009-01-22 00:13:42 -0800219}
220
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700221// checkA2dpEnabledChange_l() must be called with AudioFlinger::mLock held
222void AudioFlinger::checkA2dpEnabledChange_l()
The Android Open Source Projecte41dd752009-01-22 00:13:42 -0800223{
The Android Open Source Project22f8def2009-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 Projecte41dd752009-01-22 00:13:42 -0800236 }
237}
238#endif // WITH_A2DP
239
The Android Open Source Projectedbf3b62009-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 Laurentb1596ee2009-03-26 01:57:59 -0700246 streamType == AudioSystem::NOTIFICATION ||
247 streamType == AudioSystem::ENFORCED_AUDIBLE);
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700248}
249
The Android Open Source Project7c1b96a2008-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 Project7c1b96a2008-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 Project22f8def2009-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 Project7c1b96a2008-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 Project4f68be12009-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 Project7c1b96a2008-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 Project4f68be12009-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 Project22f8def2009-03-09 11:52:12 -0700335 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700336
337 dumpClients(fd, args);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700338 dumpInternals(fd, args);
The Android Open Source Projectedbf3b62009-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 Project7c1b96a2008-10-21 07:00:00 -0700347 if (mAudioHardware) {
348 mAudioHardware->dumpState(fd, args);
349 }
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700350 if (locked) mLock.unlock();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700351 }
352 return NO_ERROR;
353}
354
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700355// IAudioFlinger interface
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800356
357
The Android Open Source Project7c1b96a2008-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 Projecte09fd9e2008-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 Project7c1b96a2008-10-21 07:00:00 -0700368{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800369 sp<MixerThread::Track> track;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700370 sp<TrackHandle> trackHandle;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700371 sp<Client> client;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800372 wp<Client> wclient;
373 status_t lStatus;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700374
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800375 if (streamType >= AudioSystem::NUM_STREAM_TYPES) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800376 LOGE("invalid stream type");
377 lStatus = BAD_VALUE;
378 goto Exit;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700379 }
380
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800381 {
382 Mutex::Autolock _l(mLock);
383
The Android Open Source Projecte09fd9e2008-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 Projectedbf3b62009-03-03 19:31:44 -0800392#ifdef WITH_A2DP
393 if (isA2dpEnabled() && AudioSystem::routedToA2dpOutput(streamType)) {
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700394 track = mA2dpMixerThread->createTrack_l(client, streamType, sampleRate, format,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800395 channelCount, frameCount, sharedBuffer, &lStatus);
396 } else
397#endif
398 {
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700399 track = mHardwareMixerThread->createTrack_l(client, streamType, sampleRate, format,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800400 channelCount, frameCount, sharedBuffer, &lStatus);
401 }
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700402 }
403 if (lStatus == NO_ERROR) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800404 trackHandle = new TrackHandle(track);
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700405 } else {
406 track.clear();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800407 }
408
409Exit:
410 if(status) {
411 *status = lStatus;
412 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700413 return trackHandle;
414}
415
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800416uint32_t AudioFlinger::sampleRate(int output) const
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700417{
The Android Open Source Projectedbf3b62009-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 Project7c1b96a2008-10-21 07:00:00 -0700424}
425
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800426int AudioFlinger::channelCount(int output) const
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700427{
The Android Open Source Projectedbf3b62009-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 Project7c1b96a2008-10-21 07:00:00 -0700434}
435
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800436int AudioFlinger::format(int output) const
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700437{
The Android Open Source Projectedbf3b62009-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 Project7c1b96a2008-10-21 07:00:00 -0700444}
445
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800446size_t AudioFlinger::frameCount(int output) const
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700447{
The Android Open Source Projectedbf3b62009-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 Project7c1b96a2008-10-21 07:00:00 -0700454}
455
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800456uint32_t AudioFlinger::latency(int output) const
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800457{
The Android Open Source Projectedbf3b62009-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 Projecte09fd9e2008-12-17 18:05:43 -0800464}
465
The Android Open Source Project7c1b96a2008-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 Projectedbf3b62009-03-03 19:31:44 -0800477 value = 1.0f;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700478 }
479 mHardwareStatus = AUDIO_HW_IDLE;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800480 mHardwareMixerThread->setMasterVolume(value);
481#ifdef WITH_A2DP
482 mA2dpMixerThread->setMasterVolume(value);
483#endif
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700484
The Android Open Source Project7c1b96a2008-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 Project27629322009-01-09 17:51:23 -0800490 status_t err = NO_ERROR;
491
The Android Open Source Project7c1b96a2008-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 Projecte09fd9e2008-12-17 18:05:43 -0800501#ifdef WITH_A2DP
Jean-Baptiste Queru4d3b5c12009-07-21 11:16:54 -0700502 LOGV("setRouting %d %d %d, tid %d, calling tid %d\n", mode, routes, mask, gettid(),
503 IPCThreadState::self()->getCallingPid());
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800504 if (mode == AudioSystem::MODE_NORMAL &&
505 (mask & AudioSystem::ROUTE_BLUETOOTH_A2DP)) {
The Android Open Source Projecte41dd752009-01-22 00:13:42 -0800506 AutoMutex lock(&mLock);
507
508 bool enableA2dp = false;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800509 if (routes & AudioSystem::ROUTE_BLUETOOTH_A2DP) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800510 enableA2dp = true;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800511 }
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700512 if (mA2dpDisableCount > 0) {
513 mA2dpSuppressed = enableA2dp;
514 } else {
515 setA2dpEnabled_l(enableA2dp);
516 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800517 LOGV("setOutput done\n");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800518 }
The Android Open Source Project4f68be12009-03-18 17:39:46 -0700519 // setRouting() is always called at least for mode == AudioSystem::MODE_IN_CALL when
520 // SCO is enabled, whatever current mode is so we can safely handle A2DP disabling only
521 // in this case to avoid doing it several times.
522 if (mode == AudioSystem::MODE_IN_CALL &&
523 (mask & AudioSystem::ROUTE_BLUETOOTH_SCO)) {
524 AutoMutex lock(&mLock);
525 handleRouteDisablesA2dp_l(routes);
526 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800527#endif
528
The Android Open Source Project27629322009-01-09 17:51:23 -0800529 // do nothing if only A2DP routing is affected
530 mask &= ~AudioSystem::ROUTE_BLUETOOTH_A2DP;
531 if (mask) {
532 AutoMutex lock(mHardwareLock);
533 mHardwareStatus = AUDIO_HW_GET_ROUTING;
534 uint32_t r;
535 err = mAudioHardware->getRouting(mode, &r);
536 if (err == NO_ERROR) {
537 r = (r & ~mask) | (routes & mask);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800538 if (mode == AudioSystem::MODE_NORMAL ||
539 (mode == AudioSystem::MODE_CURRENT && getMode() == AudioSystem::MODE_NORMAL)) {
540 mSavedRoute = r;
541 r |= mForcedRoute;
542 LOGV("setRouting mSavedRoute %08x mForcedRoute %08x\n", mSavedRoute, mForcedRoute);
543 }
The Android Open Source Project27629322009-01-09 17:51:23 -0800544 mHardwareStatus = AUDIO_HW_SET_ROUTING;
545 err = mAudioHardware->setRouting(mode, r);
546 }
547 mHardwareStatus = AUDIO_HW_IDLE;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700548 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700549 return err;
550}
551
552uint32_t AudioFlinger::getRouting(int mode) const
553{
554 uint32_t routes = 0;
555 if ((mode >= AudioSystem::MODE_CURRENT) && (mode < AudioSystem::NUM_MODES)) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800556 if (mode == AudioSystem::MODE_NORMAL ||
557 (mode == AudioSystem::MODE_CURRENT && getMode() == AudioSystem::MODE_NORMAL)) {
558 routes = mSavedRoute;
559 } else {
560 mHardwareStatus = AUDIO_HW_GET_ROUTING;
561 mAudioHardware->getRouting(mode, &routes);
562 mHardwareStatus = AUDIO_HW_IDLE;
563 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700564 } else {
565 LOGW("Illegal value: getRouting(%d)", mode);
566 }
567 return routes;
568}
569
570status_t AudioFlinger::setMode(int mode)
571{
572 // check calling permissions
573 if (!settingsAllowed()) {
574 return PERMISSION_DENIED;
575 }
576 if ((mode < 0) || (mode >= AudioSystem::NUM_MODES)) {
577 LOGW("Illegal value: setMode(%d)", mode);
578 return BAD_VALUE;
579 }
580
581 AutoMutex lock(mHardwareLock);
582 mHardwareStatus = AUDIO_HW_SET_MODE;
583 status_t ret = mAudioHardware->setMode(mode);
584 mHardwareStatus = AUDIO_HW_IDLE;
585 return ret;
586}
587
588int AudioFlinger::getMode() const
589{
590 int mode = AudioSystem::MODE_INVALID;
591 mHardwareStatus = AUDIO_HW_SET_MODE;
592 mAudioHardware->getMode(&mode);
593 mHardwareStatus = AUDIO_HW_IDLE;
594 return mode;
595}
596
597status_t AudioFlinger::setMicMute(bool state)
598{
599 // check calling permissions
600 if (!settingsAllowed()) {
601 return PERMISSION_DENIED;
602 }
603
604 AutoMutex lock(mHardwareLock);
605 mHardwareStatus = AUDIO_HW_SET_MIC_MUTE;
606 status_t ret = mAudioHardware->setMicMute(state);
607 mHardwareStatus = AUDIO_HW_IDLE;
608 return ret;
609}
610
611bool AudioFlinger::getMicMute() const
612{
613 bool state = AudioSystem::MODE_INVALID;
614 mHardwareStatus = AUDIO_HW_GET_MIC_MUTE;
615 mAudioHardware->getMicMute(&state);
616 mHardwareStatus = AUDIO_HW_IDLE;
617 return state;
618}
619
620status_t AudioFlinger::setMasterMute(bool muted)
621{
622 // check calling permissions
623 if (!settingsAllowed()) {
624 return PERMISSION_DENIED;
625 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800626 mHardwareMixerThread->setMasterMute(muted);
627#ifdef WITH_A2DP
628 mA2dpMixerThread->setMasterMute(muted);
629#endif
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700630 return NO_ERROR;
631}
632
633float AudioFlinger::masterVolume() const
634{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800635 return mHardwareMixerThread->masterVolume();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700636}
637
638bool AudioFlinger::masterMute() const
639{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800640 return mHardwareMixerThread->masterMute();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700641}
642
643status_t AudioFlinger::setStreamVolume(int stream, float value)
644{
645 // check calling permissions
646 if (!settingsAllowed()) {
647 return PERMISSION_DENIED;
648 }
649
Eric Laurentb1596ee2009-03-26 01:57:59 -0700650 if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES ||
651 uint32_t(stream) == AudioSystem::ENFORCED_AUDIBLE) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700652 return BAD_VALUE;
653 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800654
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700655 status_t ret = NO_ERROR;
Jean-Baptiste Queru732ca392009-03-18 11:33:14 -0700656
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800657 if (stream == AudioSystem::VOICE_CALL ||
658 stream == AudioSystem::BLUETOOTH_SCO) {
Jean-Baptiste Queru9660d302009-05-20 11:28:04 -0700659 float hwValue;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800660 if (stream == AudioSystem::VOICE_CALL) {
Jean-Baptiste Queru732ca392009-03-18 11:33:14 -0700661 hwValue = (float)AudioSystem::logToLinear(value)/100.0f;
Jean-Baptiste Queru9660d302009-05-20 11:28:04 -0700662 // offset value to reflect actual hardware volume that never reaches 0
663 // 1% corresponds roughly to first step in VOICE_CALL stream volume setting (see AudioService.java)
664 value = 0.01 + 0.99 * value;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800665 } else { // (type == AudioSystem::BLUETOOTH_SCO)
Jean-Baptiste Queru732ca392009-03-18 11:33:14 -0700666 hwValue = 1.0f;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800667 }
668
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700669 AutoMutex lock(mHardwareLock);
670 mHardwareStatus = AUDIO_SET_VOICE_VOLUME;
Jean-Baptiste Queru732ca392009-03-18 11:33:14 -0700671 ret = mAudioHardware->setVoiceVolume(hwValue);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700672 mHardwareStatus = AUDIO_HW_IDLE;
Jean-Baptiste Queru732ca392009-03-18 11:33:14 -0700673
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700674 }
Jean-Baptiste Queru732ca392009-03-18 11:33:14 -0700675
676 mHardwareMixerThread->setStreamVolume(stream, value);
677#ifdef WITH_A2DP
678 mA2dpMixerThread->setStreamVolume(stream, value);
679#endif
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800680
Jean-Baptiste Queru9660d302009-05-20 11:28:04 -0700681 mHardwareMixerThread->setStreamVolume(stream, value);
682#ifdef WITH_A2DP
683 mA2dpMixerThread->setStreamVolume(stream, value);
684#endif
685
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700686 return ret;
687}
688
689status_t AudioFlinger::setStreamMute(int stream, bool muted)
690{
691 // check calling permissions
692 if (!settingsAllowed()) {
693 return PERMISSION_DENIED;
694 }
695
Eric Laurentb1596ee2009-03-26 01:57:59 -0700696 if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES ||
697 uint32_t(stream) == AudioSystem::ENFORCED_AUDIBLE) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700698 return BAD_VALUE;
699 }
The Android Open Source Project4f68be12009-03-18 17:39:46 -0700700
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800701#ifdef WITH_A2DP
702 mA2dpMixerThread->setStreamMute(stream, muted);
703#endif
704 if (stream == AudioSystem::MUSIC)
705 {
706 AutoMutex lock(&mHardwareLock);
707 if (mForcedRoute != 0)
708 mMusicMuteSaved = muted;
709 else
710 mHardwareMixerThread->setStreamMute(stream, muted);
711 } else {
712 mHardwareMixerThread->setStreamMute(stream, muted);
713 }
714
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700715 return NO_ERROR;
716}
717
718float AudioFlinger::streamVolume(int stream) const
719{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800720 if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700721 return 0.0f;
722 }
Jean-Baptiste Queru732ca392009-03-18 11:33:14 -0700723
Jean-Baptiste Queru9660d302009-05-20 11:28:04 -0700724 float volume = mHardwareMixerThread->streamVolume(stream);
725 // remove correction applied by setStreamVolume()
Jean-Baptiste Queru732ca392009-03-18 11:33:14 -0700726 if (stream == AudioSystem::VOICE_CALL) {
Jean-Baptiste Queru9660d302009-05-20 11:28:04 -0700727 volume = (volume - 0.01) / 0.99 ;
James E. Blair6015dfc2009-01-17 13:30:20 -0800728 }
Jean-Baptiste Queru732ca392009-03-18 11:33:14 -0700729
Jean-Baptiste Queru9660d302009-05-20 11:28:04 -0700730 return volume;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700731}
732
733bool AudioFlinger::streamMute(int stream) const
734{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800735 if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700736 return true;
737 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800738
739 if (stream == AudioSystem::MUSIC && mForcedRoute != 0)
740 {
741 return mMusicMuteSaved;
742 }
743 return mHardwareMixerThread->streamMute(stream);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700744}
745
746bool AudioFlinger::isMusicActive() const
747{
Jean-Baptiste Queru02f54242009-07-29 14:25:07 -0700748 Mutex::Autolock _l(mLock);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800749 #ifdef WITH_A2DP
750 if (isA2dpEnabled()) {
Jean-Baptiste Queru02f54242009-07-29 14:25:07 -0700751 return mA2dpMixerThread->isMusicActive_l();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800752 }
753 #endif
Jean-Baptiste Queru02f54242009-07-29 14:25:07 -0700754 return mHardwareMixerThread->isMusicActive_l();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700755}
756
757status_t AudioFlinger::setParameter(const char* key, const char* value)
758{
The Android Open Source Project8a7a6752009-01-15 16:12:10 -0800759 status_t result, result2;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700760 AutoMutex lock(mHardwareLock);
761 mHardwareStatus = AUDIO_SET_PARAMETER;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800762
763 LOGV("setParameter() key %s, value %s, tid %d, calling tid %d", key, value, gettid(), IPCThreadState::self()->getCallingPid());
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700764 result = mAudioHardware->setParameter(key, value);
The Android Open Source Project8a7a6752009-01-15 16:12:10 -0800765 if (mA2dpAudioInterface) {
766 result2 = mA2dpAudioInterface->setParameter(key, value);
767 if (result2)
768 result = result2;
769 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700770 mHardwareStatus = AUDIO_HW_IDLE;
771 return result;
772}
773
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800774size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
775{
776 return mAudioHardware->getInputBufferSize(sampleRate, format, channelCount);
777}
778
779void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
780{
781
782 LOGV("registerClient() %p, tid %d, calling tid %d", client.get(), gettid(), IPCThreadState::self()->getCallingPid());
783 Mutex::Autolock _l(mLock);
784
785 sp<IBinder> binder = client->asBinder();
786 if (mNotificationClients.indexOf(binder) < 0) {
787 LOGV("Adding notification client %p", binder.get());
788 binder->linkToDeath(this);
789 mNotificationClients.add(binder);
790 client->a2dpEnabledChanged(isA2dpEnabled());
791 }
792}
793
794void AudioFlinger::binderDied(const wp<IBinder>& who) {
795
796 LOGV("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(), IPCThreadState::self()->getCallingPid());
797 Mutex::Autolock _l(mLock);
798
799 IBinder *binder = who.unsafe_get();
800
801 if (binder != NULL) {
802 int index = mNotificationClients.indexOf(binder);
803 if (index >= 0) {
804 LOGV("Removing notification client %p", binder);
805 mNotificationClients.removeAt(index);
806 }
807 }
808}
809
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700810void AudioFlinger::removeClient(pid_t pid)
811{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800812 LOGV("removeClient() pid %d, tid %d, calling tid %d", pid, gettid(), IPCThreadState::self()->getCallingPid());
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700813 Mutex::Autolock _l(mLock);
814 mClients.removeItem(pid);
815}
816
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800817bool AudioFlinger::isA2dpEnabled() const
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700818{
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700819 return mA2dpEnabled;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800820}
821
822void AudioFlinger::handleForcedSpeakerRoute(int command)
823{
824 switch(command) {
825 case ACTIVE_TRACK_ADDED:
826 {
827 AutoMutex lock(mHardwareLock);
828 if (mForcedSpeakerCount++ == 0) {
Jean-Baptiste Queru4d3b5c12009-07-21 11:16:54 -0700829 if (mForcedRoute == 0) {
830 mMusicMuteSaved = mHardwareMixerThread->streamMute(AudioSystem::MUSIC);
831 LOGV("++mForcedSpeakerCount == 0, mMusicMuteSaved = %d, mRouteRestoreTime = %d", mMusicMuteSaved, mRouteRestoreTime);
832 if (!(mSavedRoute & AudioSystem::ROUTE_SPEAKER)) {
833 LOGV("Route forced to Speaker ON %08x", mSavedRoute | AudioSystem::ROUTE_SPEAKER);
834 mHardwareMixerThread->setStreamMute(AudioSystem::MUSIC, true);
835 usleep(mHardwareMixerThread->latency()*1000);
836 mHardwareStatus = AUDIO_HW_SET_ROUTING;
837 mAudioHardware->setRouting(AudioSystem::MODE_NORMAL, mSavedRoute | AudioSystem::ROUTE_SPEAKER);
838 mHardwareStatus = AUDIO_HW_IDLE;
839 // delay track start so that audio hardware has time to siwtch routes
840 usleep(kStartSleepTime);
841 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800842 }
843 mForcedRoute = AudioSystem::ROUTE_SPEAKER;
Jean-Baptiste Queru4d3b5c12009-07-21 11:16:54 -0700844 mRouteRestoreTime = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800845 }
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 Projectbcef13b2009-03-11 12:11:56 -0700856 LOGV("mForcedSpeakerCount decremented to %d", mForcedSpeakerCount);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800857 } else {
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700858 LOGE("mForcedSpeakerCount is already zero");
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700859 }
The Android Open Source Projectedbf3b62009-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 Projectbcef13b2009-03-11 12:11:56 -0700883#ifdef WITH_A2DP
The Android Open Source Project4f68be12009-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 Projectbcef13b2009-03-11 12:11:56 -0700886{
The Android Open Source Project4f68be12009-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 Projectbcef13b2009-03-11 12:11:56 -0700892 }
893 }
The Android Open Source Project4f68be12009-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 {
Jean-Baptiste Queru4d3b5c12009-07-21 11:16:54 -0700905 LOGV("mA2dpDisableCount is already zero");
The Android Open Source Project4f68be12009-03-18 17:39:46 -0700906 }
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700907 }
908}
909#endif
The Android Open Source Projectedbf3b62009-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 Laurent3c525882009-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 Projectedbf3b62009-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 Laurent3c525882009-03-31 09:38:57 -0700972 wp<Track> wTrack = mActiveTracks[i];
The Android Open Source Projectedbf3b62009-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 Project22f8def2009-03-09 11:52:12 -07001026 { // scope for the AudioFlinger::mLock
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001027
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001028 Mutex::Autolock _l(mAudioFlinger->mLock);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001029
1030#ifdef WITH_A2DP
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001031 if (mOutputTrack != NULL && !mAudioFlinger->isA2dpEnabled()) {
1032 if (outputTrackActive) {
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001033 mAudioFlinger->mLock.unlock();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001034 mOutputTrack->stop();
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001035 mAudioFlinger->mLock.lock();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001036 outputTrackActive = false;
1037 }
1038 }
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001039 mAudioFlinger->checkA2dpEnabledChange_l();
The Android Open Source Projectedbf3b62009-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 Projectedbf3b62009-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 Project22f8def2009-03-09 11:52:12 -07001055 mAudioFlinger->mLock.unlock();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001056 mOutputTrack->stop();
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001057 mAudioFlinger->mLock.lock();
The Android Open Source Projectedbf3b62009-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 Projectedbf3b62009-03-03 19:31:44 -08001064 // we're about to wait, flush the binder command buffer
1065 IPCThreadState::self()->flushCommands();
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001066 mAudioFlinger->mWaitWorkCV.wait(mAudioFlinger->mLock);
The Android Open Source Projectedbf3b62009-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 Project22f8def2009-03-09 11:52:12 -07001184 removeActiveTrack_l(track);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001185 if (track->isTerminated()) {
1186 mTracks.remove(track);
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001187 deleteTrackName_l(track->mName);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001188 }
1189 }
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001190 }
The Android Open Source Projectedbf3b62009-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 Project22f8def2009-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 Projectedbf3b62009-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.
Jean-Baptiste Queru4d3b5c12009-07-21 11:16:54 -07001292 if (sampleRate > mSampleRate*2) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001293 LOGE("Sample rate out of range: %d mSampleRate %d", sampleRate, mSampleRate);
1294 lStatus = BAD_VALUE;
1295 goto Exit;
1296 }
1297
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001298
The Android Open Source Project22f8def2009-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 Projectedbf3b62009-03-03 19:31:44 -08001303 }
1304
The Android Open Source Project22f8def2009-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 Projectedbf3b62009-03-03 19:31:44 -08001314Exit:
1315 if(status) {
1316 *status = lStatus;
1317 }
1318 return track;
1319}
1320
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001321// getTracks_l() must be called with AudioFlinger::mLock held
1322void AudioFlinger::MixerThread::getTracks_l(
The Android Open Source Projectedbf3b62009-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 Project22f8def2009-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 Projectedbf3b62009-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 Project22f8def2009-03-09 11:52:12 -07001344 removeActiveTrack_l(activeTracks[i]);
The Android Open Source Projectedbf3b62009-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 Project22f8def2009-03-09 11:52:12 -07001351 deleteTrackName_l(t->name());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001352 }
1353}
1354
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001355// putTracks_l() must be called with AudioFlinger::mLock held
1356void AudioFlinger::MixerThread::putTracks_l(
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001357 SortedVector < sp<Track> >& tracks,
1358 SortedVector < wp<Track> >& activeTracks)
1359{
1360
The Android Open Source Project22f8def2009-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 Projectedbf3b62009-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 Project22f8def2009-03-09 11:52:12 -07001366 int name = getTrackName_l();
The Android Open Source Projectedbf3b62009-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 Project22f8def2009-03-09 11:52:12 -07001376 addActiveTrack_l(t);
The Android Open Source Projectedbf3b62009-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
Jean-Baptiste Queru02f54242009-07-29 14:25:07 -07001455// isMusicActive_l() must be called with AudioFlinger::mLock held
1456bool AudioFlinger::MixerThread::isMusicActive_l() const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001457{
1458 size_t count = mActiveTracks.size();
1459 for (size_t i = 0 ; i < count ; ++i) {
1460 sp<Track> t = mActiveTracks[i].promote();
1461 if (t == 0) continue;
1462 Track* const track = t.get();
1463 if (t->mStreamType == AudioSystem::MUSIC)
1464 return true;
1465 }
1466 return false;
1467}
1468
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001469// addTrack_l() must be called with AudioFlinger::mLock held
1470status_t AudioFlinger::MixerThread::addTrack_l(const sp<Track>& track)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001471{
1472 status_t status = ALREADY_EXISTS;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001473
1474 // here the track could be either new, or restarted
1475 // in both cases "unstop" the track
1476 if (track->isPaused()) {
1477 track->mState = TrackBase::RESUMING;
1478 LOGV("PAUSED => RESUMING (%d)", track->name());
1479 } else {
1480 track->mState = TrackBase::ACTIVE;
1481 LOGV("? => ACTIVE (%d)", track->name());
1482 }
1483 // set retry count for buffer fill
1484 track->mRetryCount = kMaxTrackStartupRetries;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001485 if (mActiveTracks.indexOf(track) < 0) {
1486 // the track is newly added, make sure it fills up all its
1487 // buffers before playing. This is to ensure the client will
1488 // effectively get the latency it requested.
1489 track->mFillingUpStatus = Track::FS_FILLING;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001490 track->mResetDone = false;
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001491 addActiveTrack_l(track);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001492 status = NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001493 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001494
1495 LOGV("mWaitWorkCV.broadcast");
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001496 mAudioFlinger->mWaitWorkCV.broadcast();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001497
1498 return status;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001499}
1500
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001501// destroyTrack_l() must be called with AudioFlinger::mLock held
1502void AudioFlinger::MixerThread::destroyTrack_l(const sp<Track>& track)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001503{
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001504 track->mState = TrackBase::TERMINATED;
1505 if (mActiveTracks.indexOf(track) < 0) {
1506 LOGV("remove track (%d) and delete from mixer", track->name());
1507 mTracks.remove(track);
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001508 deleteTrackName_l(track->name());
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001509 }
1510}
1511
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001512// addActiveTrack_l() must be called with AudioFlinger::mLock held
1513void AudioFlinger::MixerThread::addActiveTrack_l(const wp<Track>& t)
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001514{
1515 mActiveTracks.add(t);
1516
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001517 // Force routing to speaker for certain stream types
1518 // The forced routing to speaker is managed by hardware mixer
1519 if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) {
1520 sp<Track> track = t.promote();
1521 if (track == NULL) return;
1522
1523 if (streamForcedToSpeaker(track->type())) {
1524 mAudioFlinger->handleForcedSpeakerRoute(ACTIVE_TRACK_ADDED);
1525 }
1526 }
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001527}
1528
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001529// removeActiveTrack_l() must be called with AudioFlinger::mLock held
1530void AudioFlinger::MixerThread::removeActiveTrack_l(const wp<Track>& t)
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001531{
1532 mActiveTracks.remove(t);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001533
1534 // Force routing to speaker for certain stream types
1535 // The forced routing to speaker is managed by hardware mixer
1536 if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) {
1537 sp<Track> track = t.promote();
1538 if (track == NULL) return;
1539
1540 if (streamForcedToSpeaker(track->type())) {
1541 mAudioFlinger->handleForcedSpeakerRoute(ACTIVE_TRACK_REMOVED);
1542 }
1543 }
1544}
1545
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001546// getTrackName_l() must be called with AudioFlinger::mLock held
1547int AudioFlinger::MixerThread::getTrackName_l()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001548{
1549 return mAudioMixer->getTrackName();
1550}
1551
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001552// deleteTrackName_l() must be called with AudioFlinger::mLock held
1553void AudioFlinger::MixerThread::deleteTrackName_l(int name)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001554{
1555 mAudioMixer->deleteTrackName(name);
1556}
1557
1558size_t AudioFlinger::MixerThread::getOutputFrameCount()
1559{
1560 return mOutput->bufferSize() / mOutput->channelCount() / sizeof(int16_t);
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001561}
1562
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001563// ----------------------------------------------------------------------------
1564
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001565// TrackBase constructor must be called with AudioFlinger::mLock held
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001566AudioFlinger::MixerThread::TrackBase::TrackBase(
1567 const sp<MixerThread>& mixerThread,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001568 const sp<Client>& client,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001569 uint32_t sampleRate,
1570 int format,
1571 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001572 int frameCount,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001573 uint32_t flags,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001574 const sp<IMemory>& sharedBuffer)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001575 : RefBase(),
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001576 mMixerThread(mixerThread),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001577 mClient(client),
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001578 mFrameCount(0),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001579 mState(IDLE),
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001580 mClientTid(-1),
1581 mFormat(format),
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001582 mFlags(flags & ~SYSTEM_FLAGS_MASK)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001583{
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001584 mName = mixerThread->getTrackName_l();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001585 LOGV("TrackBase contructor name %d, calling thread %d", mName, IPCThreadState::self()->getCallingPid());
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001586 if (mName < 0) {
1587 LOGE("no more track names availlable");
1588 return;
1589 }
1590
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001591 LOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size());
1592
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001593 // LOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001594 size_t size = sizeof(audio_track_cblk_t);
1595 size_t bufferSize = frameCount*channelCount*sizeof(int16_t);
1596 if (sharedBuffer == 0) {
1597 size += bufferSize;
1598 }
1599
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001600 if (client != NULL) {
1601 mCblkMemory = client->heap()->allocate(size);
1602 if (mCblkMemory != 0) {
1603 mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer());
1604 if (mCblk) { // construct the shared structure in-place.
1605 new(mCblk) audio_track_cblk_t();
1606 // clear all buffers
1607 mCblk->frameCount = frameCount;
Jean-Baptiste Queru4d3b5c12009-07-21 11:16:54 -07001608 mCblk->sampleRate = sampleRate;
1609 mCblk->channels = (uint8_t)channelCount;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001610 if (sharedBuffer == 0) {
1611 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
1612 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
1613 // Force underrun condition to avoid false underrun callback until first data is
1614 // written to buffer
1615 mCblk->flowControlFlag = 1;
1616 } else {
1617 mBuffer = sharedBuffer->pointer();
1618 }
1619 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001620 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001621 } else {
1622 LOGE("not enough memory for AudioTrack size=%u", size);
1623 client->heap()->dump("AudioTrack");
1624 return;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001625 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001626 } else {
1627 mCblk = (audio_track_cblk_t *)(new uint8_t[size]);
1628 if (mCblk) { // construct the shared structure in-place.
1629 new(mCblk) audio_track_cblk_t();
1630 // clear all buffers
1631 mCblk->frameCount = frameCount;
Jean-Baptiste Queru4d3b5c12009-07-21 11:16:54 -07001632 mCblk->sampleRate = sampleRate;
1633 mCblk->channels = (uint8_t)channelCount;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001634 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
1635 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
1636 // Force underrun condition to avoid false underrun callback until first data is
1637 // written to buffer
1638 mCblk->flowControlFlag = 1;
1639 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
1640 }
1641 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001642}
1643
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001644AudioFlinger::MixerThread::TrackBase::~TrackBase()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001645{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001646 if (mCblk) {
1647 mCblk->~audio_track_cblk_t(); // destroy our shared-structure.
1648 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001649 mCblkMemory.clear(); // and free the shared memory
1650 mClient.clear();
1651}
1652
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001653void AudioFlinger::MixerThread::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001654{
1655 buffer->raw = 0;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001656 mFrameCount = buffer->frameCount;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001657 step();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001658 buffer->frameCount = 0;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001659}
1660
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001661bool AudioFlinger::MixerThread::TrackBase::step() {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001662 bool result;
1663 audio_track_cblk_t* cblk = this->cblk();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001664
1665 result = cblk->stepServer(mFrameCount);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001666 if (!result) {
1667 LOGV("stepServer failed acquiring cblk mutex");
1668 mFlags |= STEPSERVER_FAILED;
1669 }
1670 return result;
1671}
1672
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001673void AudioFlinger::MixerThread::TrackBase::reset() {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001674 audio_track_cblk_t* cblk = this->cblk();
1675
1676 cblk->user = 0;
1677 cblk->server = 0;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001678 cblk->userBase = 0;
1679 cblk->serverBase = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001680 mFlags &= (uint32_t)(~SYSTEM_FLAGS_MASK);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001681 LOGV("TrackBase::reset");
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001682}
1683
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001684sp<IMemory> AudioFlinger::MixerThread::TrackBase::getCblk() const
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001685{
1686 return mCblkMemory;
1687}
1688
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001689int AudioFlinger::MixerThread::TrackBase::sampleRate() const {
The Android Open Source Project4f68be12009-03-18 17:39:46 -07001690 return (int)mCblk->sampleRate;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001691}
1692
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001693int AudioFlinger::MixerThread::TrackBase::channelCount() const {
Jean-Baptiste Queru4d3b5c12009-07-21 11:16:54 -07001694 return (int)mCblk->channels;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001695}
1696
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001697void* AudioFlinger::MixerThread::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001698 audio_track_cblk_t* cblk = this->cblk();
1699 int16_t *bufferStart = (int16_t *)mBuffer + (offset-cblk->serverBase)*cblk->channels;
1700 int16_t *bufferEnd = bufferStart + frames * cblk->channels;
1701
1702 // Check validity of returned pointer in case the track control block would have been corrupted.
The Android Open Source Project4f68be12009-03-18 17:39:46 -07001703 if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd ||
Jean-Baptiste Queru9660d302009-05-20 11:28:04 -07001704 (cblk->channels == 2 && ((unsigned long)bufferStart & 3))) {
The Android Open Source Project4f68be12009-03-18 17:39:46 -07001705 LOGE("TrackBase::getBuffer buffer out of range:\n start: %p, end %p , mBuffer %p mBufferEnd %p\n \
1706 server %d, serverBase %d, user %d, userBase %d, channels %d",
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001707 bufferStart, bufferEnd, mBuffer, mBufferEnd,
The Android Open Source Project4f68be12009-03-18 17:39:46 -07001708 cblk->server, cblk->serverBase, cblk->user, cblk->userBase, cblk->channels);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001709 return 0;
1710 }
1711
1712 return bufferStart;
1713}
1714
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001715// ----------------------------------------------------------------------------
1716
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001717// Track constructor must be called with AudioFlinger::mLock held
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001718AudioFlinger::MixerThread::Track::Track(
1719 const sp<MixerThread>& mixerThread,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001720 const sp<Client>& client,
1721 int streamType,
1722 uint32_t sampleRate,
1723 int format,
1724 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001725 int frameCount,
1726 const sp<IMemory>& sharedBuffer)
Jean-Baptiste Queru4d3b5c12009-07-21 11:16:54 -07001727 : TrackBase(mixerThread, client, sampleRate, format, channelCount, frameCount, 0, sharedBuffer)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001728{
1729 mVolume[0] = 1.0f;
1730 mVolume[1] = 1.0f;
1731 mMute = false;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001732 mSharedBuffer = sharedBuffer;
Jean-Baptiste Queru4d3b5c12009-07-21 11:16:54 -07001733 mStreamType = streamType;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001734}
1735
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001736AudioFlinger::MixerThread::Track::~Track()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001737{
1738 wp<Track> weak(this); // never create a strong ref from the dtor
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001739 Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001740 mState = TERMINATED;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001741}
1742
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001743void AudioFlinger::MixerThread::Track::destroy()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001744{
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001745 // NOTE: destroyTrack_l() can remove a strong reference to this Track
1746 // by removing it from mTracks vector, so there is a risk that this Tracks's
1747 // desctructor is called. As the destructor needs to lock AudioFlinger::mLock,
1748 // we must acquire a strong reference on this Track before locking AudioFlinger::mLock
1749 // here so that the destructor is called only when exiting this function.
1750 // On the other hand, as long as Track::destroy() is only called by
1751 // TrackHandle destructor, the TrackHandle still holds a strong ref on
1752 // this Track with its member mTrack.
1753 sp<Track> keep(this);
1754 { // scope for AudioFlinger::mLock
1755 Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
1756 mMixerThread->destroyTrack_l(this);
1757 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001758}
1759
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001760void AudioFlinger::MixerThread::Track::dump(char* buffer, size_t size)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001761{
1762 snprintf(buffer, size, " %5d %5d %3u %3u %3u %3u %1d %1d %1d %5u %5u %5u %04x %04x\n",
1763 mName - AudioMixer::TRACK0,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001764 (mClient == NULL) ? getpid() : mClient->pid(),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001765 mStreamType,
1766 mFormat,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001767 mCblk->channels,
1768 mFrameCount,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001769 mState,
1770 mMute,
1771 mFillingUpStatus,
1772 mCblk->sampleRate,
1773 mCblk->volume[0],
1774 mCblk->volume[1],
1775 mCblk->server,
1776 mCblk->user);
1777}
1778
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001779status_t AudioFlinger::MixerThread::Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001780{
1781 audio_track_cblk_t* cblk = this->cblk();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001782 uint32_t framesReady;
1783 uint32_t framesReq = buffer->frameCount;
1784
1785 // Check if last stepServer failed, try to step now
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001786 if (mFlags & TrackBase::STEPSERVER_FAILED) {
1787 if (!step()) goto getNextBuffer_exit;
1788 LOGV("stepServer recovered");
1789 mFlags &= ~TrackBase::STEPSERVER_FAILED;
1790 }
1791
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001792 framesReady = cblk->framesReady();
1793
1794 if (LIKELY(framesReady)) {
1795 uint32_t s = cblk->server;
1796 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
1797
1798 bufferEnd = (cblk->loopEnd < bufferEnd) ? cblk->loopEnd : bufferEnd;
1799 if (framesReq > framesReady) {
1800 framesReq = framesReady;
1801 }
1802 if (s + framesReq > bufferEnd) {
1803 framesReq = bufferEnd - s;
1804 }
1805
1806 buffer->raw = getBuffer(s, framesReq);
1807 if (buffer->raw == 0) goto getNextBuffer_exit;
1808
1809 buffer->frameCount = framesReq;
1810 return NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001811 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001812
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001813getNextBuffer_exit:
1814 buffer->raw = 0;
1815 buffer->frameCount = 0;
1816 return NOT_ENOUGH_DATA;
1817}
1818
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001819bool AudioFlinger::MixerThread::Track::isReady() const {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001820 if (mFillingUpStatus != FS_FILLING) return true;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001821
1822 if (mCblk->framesReady() >= mCblk->frameCount ||
1823 mCblk->forceReady) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001824 mFillingUpStatus = FS_FILLED;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001825 mCblk->forceReady = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001826 LOGV("Track::isReady() track %d for output %d", mName, mMixerThread->mOutputType);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001827 return true;
1828 }
1829 return false;
1830}
1831
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001832status_t AudioFlinger::MixerThread::Track::start()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001833{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001834 LOGV("start(%d), calling thread %d for output %d", mName, IPCThreadState::self()->getCallingPid(), mMixerThread->mOutputType);
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001835 Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
1836 mMixerThread->addTrack_l(this);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001837 return NO_ERROR;
1838}
1839
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001840void AudioFlinger::MixerThread::Track::stop()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001841{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001842 LOGV("stop(%d), calling thread %d for output %d", mName, IPCThreadState::self()->getCallingPid(), mMixerThread->mOutputType);
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001843 Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001844 if (mState > STOPPED) {
1845 mState = STOPPED;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001846 // If the track is not active (PAUSED and buffers full), flush buffers
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001847 if (mMixerThread->mActiveTracks.indexOf(this) < 0) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001848 reset();
1849 }
1850 LOGV("(> STOPPED) => STOPPED (%d)", mName);
1851 }
1852}
1853
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001854void AudioFlinger::MixerThread::Track::pause()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001855{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001856 LOGV("pause(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001857 Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001858 if (mState == ACTIVE || mState == RESUMING) {
1859 mState = PAUSING;
1860 LOGV("ACTIVE/RESUMING => PAUSING (%d)", mName);
1861 }
1862}
1863
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001864void AudioFlinger::MixerThread::Track::flush()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001865{
1866 LOGV("flush(%d)", mName);
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001867 Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001868 if (mState != STOPPED && mState != PAUSED && mState != PAUSING) {
1869 return;
1870 }
1871 // No point remaining in PAUSED state after a flush => go to
1872 // STOPPED state
1873 mState = STOPPED;
1874
The Android Open Source Project4f68be12009-03-18 17:39:46 -07001875 mCblk->lock.lock();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001876 // NOTE: reset() will reset cblk->user and cblk->server with
1877 // the risk that at the same time, the AudioMixer is trying to read
1878 // data. In this case, getNextBuffer() would return a NULL pointer
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001879 // as audio buffer => the AudioMixer code MUST always test that pointer
1880 // returned by getNextBuffer() is not NULL!
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001881 reset();
The Android Open Source Project4f68be12009-03-18 17:39:46 -07001882 mCblk->lock.unlock();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001883}
1884
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001885void AudioFlinger::MixerThread::Track::reset()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001886{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001887 // Do not reset twice to avoid discarding data written just after a flush and before
1888 // the audioflinger thread detects the track is stopped.
1889 if (!mResetDone) {
1890 TrackBase::reset();
1891 // Force underrun condition to avoid false underrun callback until first data is
1892 // written to buffer
1893 mCblk->flowControlFlag = 1;
1894 mCblk->forceReady = 0;
1895 mFillingUpStatus = FS_FILLING;
1896 mResetDone = true;
1897 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001898}
1899
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001900void AudioFlinger::MixerThread::Track::mute(bool muted)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001901{
1902 mMute = muted;
1903}
1904
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001905void AudioFlinger::MixerThread::Track::setVolume(float left, float right)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001906{
1907 mVolume[0] = left;
1908 mVolume[1] = right;
1909}
1910
1911// ----------------------------------------------------------------------------
1912
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001913// RecordTrack constructor must be called with AudioFlinger::mLock held
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001914AudioFlinger::MixerThread::RecordTrack::RecordTrack(
1915 const sp<MixerThread>& mixerThread,
1916 const sp<Client>& client,
Jean-Baptiste Queru4d3b5c12009-07-21 11:16:54 -07001917 int inputSource,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001918 uint32_t sampleRate,
1919 int format,
1920 int channelCount,
1921 int frameCount,
1922 uint32_t flags)
Jean-Baptiste Queru4d3b5c12009-07-21 11:16:54 -07001923 : TrackBase(mixerThread, client, sampleRate, format,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001924 channelCount, frameCount, flags, 0),
Jean-Baptiste Queru4d3b5c12009-07-21 11:16:54 -07001925 mOverflow(false), mInputSource(inputSource)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001926{
1927}
1928
1929AudioFlinger::MixerThread::RecordTrack::~RecordTrack()
1930{
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001931 Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
1932 mMixerThread->deleteTrackName_l(mName);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001933}
1934
1935status_t AudioFlinger::MixerThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
1936{
1937 audio_track_cblk_t* cblk = this->cblk();
1938 uint32_t framesAvail;
1939 uint32_t framesReq = buffer->frameCount;
1940
1941 // Check if last stepServer failed, try to step now
1942 if (mFlags & TrackBase::STEPSERVER_FAILED) {
1943 if (!step()) goto getNextBuffer_exit;
1944 LOGV("stepServer recovered");
1945 mFlags &= ~TrackBase::STEPSERVER_FAILED;
1946 }
1947
1948 framesAvail = cblk->framesAvailable_l();
1949
1950 if (LIKELY(framesAvail)) {
1951 uint32_t s = cblk->server;
1952 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
1953
1954 if (framesReq > framesAvail) {
1955 framesReq = framesAvail;
1956 }
1957 if (s + framesReq > bufferEnd) {
1958 framesReq = bufferEnd - s;
1959 }
1960
1961 buffer->raw = getBuffer(s, framesReq);
1962 if (buffer->raw == 0) goto getNextBuffer_exit;
1963
1964 buffer->frameCount = framesReq;
1965 return NO_ERROR;
1966 }
1967
1968getNextBuffer_exit:
1969 buffer->raw = 0;
1970 buffer->frameCount = 0;
1971 return NOT_ENOUGH_DATA;
1972}
1973
1974status_t AudioFlinger::MixerThread::RecordTrack::start()
1975{
1976 return mMixerThread->mAudioFlinger->startRecord(this);
1977}
1978
1979void AudioFlinger::MixerThread::RecordTrack::stop()
1980{
1981 mMixerThread->mAudioFlinger->stopRecord(this);
1982 TrackBase::reset();
1983 // Force overerrun condition to avoid false overrun callback until first data is
1984 // read from buffer
1985 mCblk->flowControlFlag = 1;
1986}
1987
1988
1989// ----------------------------------------------------------------------------
1990
1991AudioFlinger::MixerThread::OutputTrack::OutputTrack(
1992 const sp<MixerThread>& mixerThread,
1993 uint32_t sampleRate,
1994 int format,
1995 int channelCount,
1996 int frameCount)
1997 : Track(mixerThread, NULL, AudioSystem::SYSTEM, sampleRate, format, channelCount, frameCount, NULL),
1998 mOutputMixerThread(mixerThread)
1999{
2000
2001 mCblk->out = 1;
2002 mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
2003 mCblk->volume[0] = mCblk->volume[1] = 0x1000;
2004 mOutBuffer.frameCount = 0;
2005 mCblk->bufferTimeoutMs = 10;
2006
2007 LOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, mCblk->frameCount %d, mCblk->sampleRate %d, mCblk->channels %d mBufferEnd %p",
2008 mCblk, mBuffer, mCblk->buffers, mCblk->frameCount, mCblk->sampleRate, mCblk->channels, mBufferEnd);
2009
2010}
2011
2012AudioFlinger::MixerThread::OutputTrack::~OutputTrack()
2013{
2014 stop();
2015}
2016
2017status_t AudioFlinger::MixerThread::OutputTrack::start()
2018{
2019 status_t status = Track::start();
2020
2021 mRetryCount = 127;
2022 return status;
2023}
2024
2025void AudioFlinger::MixerThread::OutputTrack::stop()
2026{
2027 Track::stop();
2028 clearBufferQueue();
2029 mOutBuffer.frameCount = 0;
2030}
2031
2032void AudioFlinger::MixerThread::OutputTrack::write(int16_t* data, uint32_t frames)
2033{
2034 Buffer *pInBuffer;
2035 Buffer inBuffer;
2036 uint32_t channels = mCblk->channels;
2037
2038 inBuffer.frameCount = frames;
2039 inBuffer.i16 = data;
2040
2041 if (mCblk->user == 0) {
Jean-Baptiste Queru02f54242009-07-29 14:25:07 -07002042 mOutputMixerThread->mAudioFlinger->mLock.lock();
2043 bool isMusicActive = mOutputMixerThread->isMusicActive_l();
2044 mOutputMixerThread->mAudioFlinger->mLock.unlock();
2045 if (isMusicActive) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002046 mCblk->forceReady = 1;
2047 LOGV("OutputTrack::start() force ready");
2048 } else if (mCblk->frameCount > frames){
2049 if (mBufferQueue.size() < kMaxOutputTrackBuffers) {
2050 uint32_t startFrames = (mCblk->frameCount - frames);
2051 LOGV("OutputTrack::start() write %d frames", startFrames);
2052 pInBuffer = new Buffer;
2053 pInBuffer->mBuffer = new int16_t[startFrames * channels];
2054 pInBuffer->frameCount = startFrames;
2055 pInBuffer->i16 = pInBuffer->mBuffer;
2056 memset(pInBuffer->raw, 0, startFrames * channels * sizeof(int16_t));
2057 mBufferQueue.add(pInBuffer);
2058 } else {
2059 LOGW ("OutputTrack::write() no more buffers");
2060 }
2061 }
2062 }
2063
2064 while (1) {
2065 // First write pending buffers, then new data
2066 if (mBufferQueue.size()) {
2067 pInBuffer = mBufferQueue.itemAt(0);
2068 } else {
2069 pInBuffer = &inBuffer;
2070 }
2071
2072 if (pInBuffer->frameCount == 0) {
2073 break;
2074 }
2075
2076 if (mOutBuffer.frameCount == 0) {
2077 mOutBuffer.frameCount = pInBuffer->frameCount;
2078 if (obtainBuffer(&mOutBuffer) == (status_t)AudioTrack::NO_MORE_BUFFERS) {
2079 break;
2080 }
2081 }
2082
2083 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount : pInBuffer->frameCount;
2084 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * channels * sizeof(int16_t));
2085 mCblk->stepUser(outFrames);
2086 pInBuffer->frameCount -= outFrames;
2087 pInBuffer->i16 += outFrames * channels;
2088 mOutBuffer.frameCount -= outFrames;
2089 mOutBuffer.i16 += outFrames * channels;
2090
2091 if (pInBuffer->frameCount == 0) {
2092 if (mBufferQueue.size()) {
2093 mBufferQueue.removeAt(0);
2094 delete [] pInBuffer->mBuffer;
2095 delete pInBuffer;
2096 } else {
2097 break;
2098 }
2099 }
2100 }
2101
2102 // If we could not write all frames, allocate a buffer and queue it for next time.
2103 if (inBuffer.frameCount) {
2104 if (mBufferQueue.size() < kMaxOutputTrackBuffers) {
2105 pInBuffer = new Buffer;
2106 pInBuffer->mBuffer = new int16_t[inBuffer.frameCount * channels];
2107 pInBuffer->frameCount = inBuffer.frameCount;
2108 pInBuffer->i16 = pInBuffer->mBuffer;
2109 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * channels * sizeof(int16_t));
2110 mBufferQueue.add(pInBuffer);
2111 } else {
2112 LOGW("OutputTrack::write() no more buffers");
2113 }
2114 }
2115
2116 // Calling write() with a 0 length buffer, means that no more data will be written:
2117 // If no more buffers are pending, fill output track buffer to make sure it is started
2118 // by output mixer.
2119 if (frames == 0 && mBufferQueue.size() == 0 && mCblk->user < mCblk->frameCount) {
2120 frames = mCblk->frameCount - mCblk->user;
2121 pInBuffer = new Buffer;
2122 pInBuffer->mBuffer = new int16_t[frames * channels];
2123 pInBuffer->frameCount = frames;
2124 pInBuffer->i16 = pInBuffer->mBuffer;
2125 memset(pInBuffer->raw, 0, frames * channels * sizeof(int16_t));
2126 mBufferQueue.add(pInBuffer);
2127 }
2128
2129}
2130
2131status_t AudioFlinger::MixerThread::OutputTrack::obtainBuffer(AudioBufferProvider::Buffer* buffer)
2132{
2133 int active;
2134 int timeout = 0;
2135 status_t result;
2136 audio_track_cblk_t* cblk = mCblk;
2137 uint32_t framesReq = buffer->frameCount;
2138
2139 LOGV("OutputTrack::obtainBuffer user %d, server %d", cblk->user, cblk->server);
2140 buffer->frameCount = 0;
2141
2142 uint32_t framesAvail = cblk->framesAvailable();
2143
2144 if (framesAvail == 0) {
2145 return AudioTrack::NO_MORE_BUFFERS;
2146 }
2147
2148 if (framesReq > framesAvail) {
2149 framesReq = framesAvail;
2150 }
2151
2152 uint32_t u = cblk->user;
2153 uint32_t bufferEnd = cblk->userBase + cblk->frameCount;
2154
2155 if (u + framesReq > bufferEnd) {
2156 framesReq = bufferEnd - u;
2157 }
2158
2159 buffer->frameCount = framesReq;
2160 buffer->raw = (void *)cblk->buffer(u);
2161 return NO_ERROR;
2162}
2163
2164
2165void AudioFlinger::MixerThread::OutputTrack::clearBufferQueue()
2166{
2167 size_t size = mBufferQueue.size();
2168 Buffer *pBuffer;
2169
2170 for (size_t i = 0; i < size; i++) {
2171 pBuffer = mBufferQueue.itemAt(i);
2172 delete [] pBuffer->mBuffer;
2173 delete pBuffer;
2174 }
2175 mBufferQueue.clear();
2176}
2177
2178// ----------------------------------------------------------------------------
2179
2180AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
2181 : RefBase(),
2182 mAudioFlinger(audioFlinger),
2183 mMemoryDealer(new MemoryDealer(1024*1024)),
2184 mPid(pid)
2185{
2186 // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
2187}
2188
2189AudioFlinger::Client::~Client()
2190{
2191 mAudioFlinger->removeClient(mPid);
2192}
2193
2194const sp<MemoryDealer>& AudioFlinger::Client::heap() const
2195{
2196 return mMemoryDealer;
2197}
2198
2199// ----------------------------------------------------------------------------
2200
2201AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::MixerThread::Track>& track)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002202 : BnAudioTrack(),
2203 mTrack(track)
2204{
2205}
2206
2207AudioFlinger::TrackHandle::~TrackHandle() {
2208 // just stop the track on deletion, associated resources
2209 // will be freed from the main thread once all pending buffers have
2210 // been played. Unless it's not in the active track list, in which
2211 // case we free everything now...
2212 mTrack->destroy();
2213}
2214
2215status_t AudioFlinger::TrackHandle::start() {
2216 return mTrack->start();
2217}
2218
2219void AudioFlinger::TrackHandle::stop() {
2220 mTrack->stop();
2221}
2222
2223void AudioFlinger::TrackHandle::flush() {
2224 mTrack->flush();
2225}
2226
2227void AudioFlinger::TrackHandle::mute(bool e) {
2228 mTrack->mute(e);
2229}
2230
2231void AudioFlinger::TrackHandle::pause() {
2232 mTrack->pause();
2233}
2234
2235void AudioFlinger::TrackHandle::setVolume(float left, float right) {
2236 mTrack->setVolume(left, right);
2237}
2238
2239sp<IMemory> AudioFlinger::TrackHandle::getCblk() const {
2240 return mTrack->getCblk();
2241}
2242
2243status_t AudioFlinger::TrackHandle::onTransact(
2244 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
2245{
2246 return BnAudioTrack::onTransact(code, data, reply, flags);
2247}
2248
2249// ----------------------------------------------------------------------------
2250
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002251sp<IAudioRecord> AudioFlinger::openRecord(
2252 pid_t pid,
Jean-Baptiste Queru4d3b5c12009-07-21 11:16:54 -07002253 int inputSource,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002254 uint32_t sampleRate,
2255 int format,
2256 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002257 int frameCount,
2258 uint32_t flags,
2259 status_t *status)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002260{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002261 sp<MixerThread::RecordTrack> recordTrack;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002262 sp<RecordHandle> recordHandle;
2263 sp<Client> client;
2264 wp<Client> wclient;
2265 AudioStreamIn* input = 0;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002266 int inFrameCount;
2267 size_t inputBufferSize;
2268 status_t lStatus;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002269
2270 // check calling permissions
2271 if (!recordingAllowed()) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002272 lStatus = PERMISSION_DENIED;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002273 goto Exit;
2274 }
2275
Jean-Baptiste Queru4d3b5c12009-07-21 11:16:54 -07002276 if (uint32_t(inputSource) >= AudioRecord::NUM_INPUT_SOURCES) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002277 LOGE("invalid stream type");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002278 lStatus = BAD_VALUE;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002279 goto Exit;
2280 }
2281
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002282 if (mAudioRecordThread == 0) {
2283 LOGE("Audio record thread not started");
2284 lStatus = NO_INIT;
2285 goto Exit;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002286 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002287
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002288
2289 // Check that audio input stream accepts requested audio parameters
2290 inputBufferSize = mAudioHardware->getInputBufferSize(sampleRate, format, channelCount);
2291 if (inputBufferSize == 0) {
2292 lStatus = BAD_VALUE;
2293 LOGE("Bad audio input parameters: sampling rate %u, format %d, channels %d", sampleRate, format, channelCount);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002294 goto Exit;
2295 }
2296
2297 // add client to list
The Android Open Source Project22f8def2009-03-09 11:52:12 -07002298 { // scope for mLock
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002299 Mutex::Autolock _l(mLock);
2300 wclient = mClients.valueFor(pid);
2301 if (wclient != NULL) {
2302 client = wclient.promote();
2303 } else {
2304 client = new Client(this, pid);
2305 mClients.add(pid, client);
2306 }
The Android Open Source Project22f8def2009-03-09 11:52:12 -07002307
2308 // frameCount must be a multiple of input buffer size
2309 inFrameCount = inputBufferSize/channelCount/sizeof(short);
2310 frameCount = ((frameCount - 1)/inFrameCount + 1) * inFrameCount;
2311
2312 // create new record track. The record track uses one track in mHardwareMixerThread by convention.
Jean-Baptiste Queru4d3b5c12009-07-21 11:16:54 -07002313 recordTrack = new MixerThread::RecordTrack(mHardwareMixerThread, client, inputSource, sampleRate,
The Android Open Source Project22f8def2009-03-09 11:52:12 -07002314 format, channelCount, frameCount, flags);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002315 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002316 if (recordTrack->getCblk() == NULL) {
2317 recordTrack.clear();
2318 lStatus = NO_MEMORY;
2319 goto Exit;
2320 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002321
2322 // return to handle to client
2323 recordHandle = new RecordHandle(recordTrack);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002324 lStatus = NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002325
2326Exit:
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002327 if (status) {
2328 *status = lStatus;
2329 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002330 return recordHandle;
2331}
2332
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002333status_t AudioFlinger::startRecord(MixerThread::RecordTrack* recordTrack) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002334 if (mAudioRecordThread != 0) {
2335 return mAudioRecordThread->start(recordTrack);
2336 }
2337 return NO_INIT;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002338}
2339
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002340void AudioFlinger::stopRecord(MixerThread::RecordTrack* recordTrack) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002341 if (mAudioRecordThread != 0) {
2342 mAudioRecordThread->stop(recordTrack);
2343 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002344}
2345
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002346// ----------------------------------------------------------------------------
2347
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002348AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::MixerThread::RecordTrack>& recordTrack)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002349 : BnAudioRecord(),
2350 mRecordTrack(recordTrack)
2351{
2352}
2353
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002354AudioFlinger::RecordHandle::~RecordHandle() {
2355 stop();
2356}
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002357
2358status_t AudioFlinger::RecordHandle::start() {
2359 LOGV("RecordHandle::start()");
2360 return mRecordTrack->start();
2361}
2362
2363void AudioFlinger::RecordHandle::stop() {
2364 LOGV("RecordHandle::stop()");
2365 mRecordTrack->stop();
2366}
2367
2368sp<IMemory> AudioFlinger::RecordHandle::getCblk() const {
2369 return mRecordTrack->getCblk();
2370}
2371
2372status_t AudioFlinger::RecordHandle::onTransact(
2373 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
2374{
2375 return BnAudioRecord::onTransact(code, data, reply, flags);
2376}
2377
2378// ----------------------------------------------------------------------------
2379
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -07002380AudioFlinger::AudioRecordThread::AudioRecordThread(AudioHardwareInterface* audioHardware,
2381 const sp<AudioFlinger>& audioFlinger) :
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002382 mAudioHardware(audioHardware),
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -07002383 mAudioFlinger(audioFlinger),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002384 mActive(false)
2385{
2386}
2387
2388AudioFlinger::AudioRecordThread::~AudioRecordThread()
2389{
2390}
2391
2392bool AudioFlinger::AudioRecordThread::threadLoop()
2393{
2394 LOGV("AudioRecordThread: start record loop");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002395 AudioBufferProvider::Buffer buffer;
2396 int inBufferSize = 0;
2397 int inFrameCount = 0;
2398 AudioStreamIn* input = 0;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002399
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002400 mActive = 0;
2401
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002402 // start recording
2403 while (!exitPending()) {
2404 if (!mActive) {
2405 mLock.lock();
2406 if (!mActive && !exitPending()) {
2407 LOGV("AudioRecordThread: loop stopping");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002408 if (input) {
2409 delete input;
2410 input = 0;
2411 }
2412 mRecordTrack.clear();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002413 mStopped.signal();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002414
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002415 mWaitWorkCV.wait(mLock);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002416
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002417 LOGV("AudioRecordThread: loop starting");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002418 if (mRecordTrack != 0) {
Jean-Baptiste Queru4d3b5c12009-07-21 11:16:54 -07002419 input = mAudioHardware->openInputStream(
2420 mRecordTrack->inputSource(),
2421 mRecordTrack->format(),
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002422 mRecordTrack->channelCount(),
2423 mRecordTrack->sampleRate(),
2424 &mStartStatus,
2425 (AudioSystem::audio_in_acoustics)(mRecordTrack->mFlags >> 16));
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002426 if (input != 0) {
2427 inBufferSize = input->bufferSize();
2428 inFrameCount = inBufferSize/input->frameSize();
2429 }
2430 } else {
2431 mStartStatus = NO_INIT;
2432 }
2433 if (mStartStatus !=NO_ERROR) {
2434 LOGW("record start failed, status %d", mStartStatus);
2435 mActive = false;
2436 mRecordTrack.clear();
2437 }
2438 mWaitWorkCV.signal();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002439 }
2440 mLock.unlock();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002441 } else if (mRecordTrack != 0) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002442
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002443 buffer.frameCount = inFrameCount;
The Android Open Source Project22f8def2009-03-09 11:52:12 -07002444 if (LIKELY(mRecordTrack->getNextBuffer(&buffer) == NO_ERROR &&
2445 (int)buffer.frameCount == inFrameCount)) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002446 LOGV("AudioRecordThread read: %d frames", buffer.frameCount);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002447 ssize_t bytesRead = input->read(buffer.raw, inBufferSize);
2448 if (bytesRead < 0) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002449 LOGE("Error reading audio input");
2450 sleep(1);
2451 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002452 mRecordTrack->releaseBuffer(&buffer);
2453 mRecordTrack->overflow();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002454 }
2455
2456 // client isn't retrieving buffers fast enough
2457 else {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002458 if (!mRecordTrack->setOverflow())
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002459 LOGW("AudioRecordThread: buffer overflow");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002460 // Release the processor for a while before asking for a new buffer.
2461 // This will give the application more chance to read from the buffer and
2462 // clear the overflow.
2463 usleep(5000);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002464 }
2465 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002466 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002467
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002468
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002469 if (input) {
2470 delete input;
2471 }
2472 mRecordTrack.clear();
2473
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002474 return false;
2475}
2476
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002477status_t AudioFlinger::AudioRecordThread::start(MixerThread::RecordTrack* recordTrack)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002478{
2479 LOGV("AudioRecordThread::start");
2480 AutoMutex lock(&mLock);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002481 mActive = true;
2482 // If starting the active track, just reset mActive in case a stop
2483 // was pending and exit
2484 if (recordTrack == mRecordTrack.get()) return NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002485
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002486 if (mRecordTrack != 0) return -EBUSY;
2487
2488 mRecordTrack = recordTrack;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002489
2490 // signal thread to start
2491 LOGV("Signal record thread");
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002492 mWaitWorkCV.signal();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002493 mWaitWorkCV.wait(mLock);
2494 LOGV("Record started, status %d", mStartStatus);
2495 return mStartStatus;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002496}
2497
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002498void AudioFlinger::AudioRecordThread::stop(MixerThread::RecordTrack* recordTrack) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002499 LOGV("AudioRecordThread::stop");
2500 AutoMutex lock(&mLock);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002501 if (mActive && (recordTrack == mRecordTrack.get())) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002502 mActive = false;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002503 mStopped.wait(mLock);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002504 }
2505}
2506
2507void AudioFlinger::AudioRecordThread::exit()
2508{
2509 LOGV("AudioRecordThread::exit");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002510 {
2511 AutoMutex lock(&mLock);
2512 requestExit();
2513 mWaitWorkCV.signal();
2514 }
2515 requestExitAndWait();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002516}
2517
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002518status_t AudioFlinger::AudioRecordThread::dump(int fd, const Vector<String16>& args)
2519{
2520 const size_t SIZE = 256;
2521 char buffer[SIZE];
2522 String8 result;
2523 pid_t pid = 0;
2524
2525 if (mRecordTrack != 0 && mRecordTrack->mClient != 0) {
2526 snprintf(buffer, SIZE, "Record client pid: %d\n", mRecordTrack->mClient->pid());
2527 result.append(buffer);
2528 } else {
2529 result.append("No record client\n");
2530 }
2531 write(fd, result.string(), result.size());
2532 return NO_ERROR;
2533}
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002534
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002535status_t AudioFlinger::onTransact(
2536 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
2537{
2538 return BnAudioFlinger::onTransact(code, data, reply, flags);
2539}
2540
2541// ----------------------------------------------------------------------------
2542void AudioFlinger::instantiate() {
2543 defaultServiceManager()->addService(
2544 String16("media.audio_flinger"), new AudioFlinger());
2545}
2546
2547}; // namespace android