blob: 3c81a47812d08e1f835bd532285686f876d1e299 [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 Projecte09fd9e2008-12-17 18:05:43 -080061//static const nsecs_t kStandbyTimeInNsecs = seconds(3);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070062static const unsigned long kBufferRecoveryInUsecs = 2000;
63static const unsigned long kMaxBufferRecoveryInUsecs = 20000;
64static const float MAX_GAIN = 4096.0f;
65
66// retry counts for buffer fill timeout
67// 50 * ~20msecs = 1 second
68static const int8_t kMaxTrackRetries = 50;
69static const int8_t kMaxTrackStartupRetries = 50;
70
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080071static const int kStartSleepTime = 30000;
72static const int kStopSleepTime = 30000;
73
The Android Open Source Project22f8def2009-03-09 11:52:12 -070074static const int kDumpLockRetries = 50;
75static const int kDumpLockSleep = 20000;
76
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080077// Maximum number of pending buffers allocated by OutputTrack::write()
78static const uint8_t kMaxOutputTrackBuffers = 5;
79
80
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070081#define AUDIOFLINGER_SECURITY_ENABLED 1
82
83// ----------------------------------------------------------------------------
84
85static bool recordingAllowed() {
86#ifndef HAVE_ANDROID_OS
87 return true;
88#endif
89#if AUDIOFLINGER_SECURITY_ENABLED
90 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
91 bool ok = checkCallingPermission(String16("android.permission.RECORD_AUDIO"));
92 if (!ok) LOGE("Request requires android.permission.RECORD_AUDIO");
93 return ok;
94#else
95 if (!checkCallingPermission(String16("android.permission.RECORD_AUDIO")))
96 LOGW("WARNING: Need to add android.permission.RECORD_AUDIO to manifest");
97 return true;
98#endif
99}
100
101static bool settingsAllowed() {
102#ifndef HAVE_ANDROID_OS
103 return true;
104#endif
105#if AUDIOFLINGER_SECURITY_ENABLED
106 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
107 bool ok = checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS"));
108 if (!ok) LOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS");
109 return ok;
110#else
111 if (!checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS")))
112 LOGW("WARNING: Need to add android.permission.MODIFY_AUDIO_SETTINGS to manifest");
113 return true;
114#endif
115}
116
117// ----------------------------------------------------------------------------
118
119AudioFlinger::AudioFlinger()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800120 : BnAudioFlinger(),
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700121 mAudioHardware(0), mA2dpAudioInterface(0), mA2dpEnabled(false), mNotifyA2dpChange(false),
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700122 mForcedSpeakerCount(0), mA2dpDisableCount(0), mA2dpSuppressed(false), mForcedRoute(0),
123 mRouteRestoreTime(0), mMusicMuteSaved(false)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700124{
125 mHardwareStatus = AUDIO_HW_IDLE;
126 mAudioHardware = AudioHardwareInterface::create();
127 mHardwareStatus = AUDIO_HW_INIT;
128 if (mAudioHardware->initCheck() == NO_ERROR) {
129 // open 16-bit output stream for s/w mixer
130 mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800131 status_t status;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800132 AudioStreamOut *hwOutput = mAudioHardware->openOutputStream(AudioSystem::PCM_16_BIT, 0, 0, &status);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700133 mHardwareStatus = AUDIO_HW_IDLE;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800134 if (hwOutput) {
135 mHardwareMixerThread = new MixerThread(this, hwOutput, AudioSystem::AUDIO_OUTPUT_HARDWARE);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700136 } else {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800137 LOGE("Failed to initialize hardware output stream, status: %d", status);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700138 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800139
140#ifdef WITH_A2DP
141 // Create A2DP interface
142 mA2dpAudioInterface = new A2dpAudioInterface();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800143 AudioStreamOut *a2dpOutput = mA2dpAudioInterface->openOutputStream(AudioSystem::PCM_16_BIT, 0, 0, &status);
144 if (a2dpOutput) {
145 mA2dpMixerThread = new MixerThread(this, a2dpOutput, AudioSystem::AUDIO_OUTPUT_A2DP);
146 if (hwOutput) {
147 uint32_t frameCount = ((a2dpOutput->bufferSize()/a2dpOutput->frameSize()) * hwOutput->sampleRate()) / a2dpOutput->sampleRate();
148 MixerThread::OutputTrack *a2dpOutTrack = new MixerThread::OutputTrack(mA2dpMixerThread,
149 hwOutput->sampleRate(),
150 AudioSystem::PCM_16_BIT,
151 hwOutput->channelCount(),
152 frameCount);
153 mHardwareMixerThread->setOuputTrack(a2dpOutTrack);
154 }
155 } else {
156 LOGE("Failed to initialize A2DP output stream, status: %d", status);
157 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800158#endif
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800159
160 // FIXME - this should come from settings
161 setRouting(AudioSystem::MODE_NORMAL, AudioSystem::ROUTE_SPEAKER, AudioSystem::ROUTE_ALL);
162 setRouting(AudioSystem::MODE_RINGTONE, AudioSystem::ROUTE_SPEAKER, AudioSystem::ROUTE_ALL);
163 setRouting(AudioSystem::MODE_IN_CALL, AudioSystem::ROUTE_EARPIECE, AudioSystem::ROUTE_ALL);
164 setMode(AudioSystem::MODE_NORMAL);
165
166 setMasterVolume(1.0f);
167 setMasterMute(false);
168
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800169 // Start record thread
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700170 mAudioRecordThread = new AudioRecordThread(mAudioHardware, this);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800171 if (mAudioRecordThread != 0) {
172 mAudioRecordThread->run("AudioRecordThread", PRIORITY_URGENT_AUDIO);
173 }
174 } else {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700175 LOGE("Couldn't even initialize the stubbed audio hardware!");
176 }
177}
178
179AudioFlinger::~AudioFlinger()
180{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800181 if (mAudioRecordThread != 0) {
182 mAudioRecordThread->exit();
183 mAudioRecordThread.clear();
184 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800185 mHardwareMixerThread.clear();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700186 delete mAudioHardware;
The Android Open Source Project27629322009-01-09 17:51:23 -0800187 // deleting mA2dpAudioInterface also deletes mA2dpOutput;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800188#ifdef WITH_A2DP
189 mA2dpMixerThread.clear();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800190 delete mA2dpAudioInterface;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800191#endif
The Android Open Source Project27629322009-01-09 17:51:23 -0800192}
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800193
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700194
The Android Open Source Projecte41dd752009-01-22 00:13:42 -0800195#ifdef WITH_A2DP
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700196// setA2dpEnabled_l() must be called with AudioFlinger::mLock held
197void AudioFlinger::setA2dpEnabled_l(bool enable)
The Android Open Source Projecte41dd752009-01-22 00:13:42 -0800198{
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700199 SortedVector < sp<MixerThread::Track> > tracks;
200 SortedVector < wp<MixerThread::Track> > activeTracks;
201
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800202 LOGV_IF(enable, "set output to A2DP\n");
203 LOGV_IF(!enable, "set output to hardware audio\n");
204
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700205 // Transfer tracks playing on MUSIC stream from one mixer to the other
206 if (enable) {
207 mHardwareMixerThread->getTracks_l(tracks, activeTracks);
208 mA2dpMixerThread->putTracks_l(tracks, activeTracks);
209 } else {
210 mA2dpMixerThread->getTracks_l(tracks, activeTracks);
211 mHardwareMixerThread->putTracks_l(tracks, activeTracks);
212 }
213 mA2dpEnabled = enable;
214 mNotifyA2dpChange = true;
215 mWaitWorkCV.broadcast();
The Android Open Source Projecte41dd752009-01-22 00:13:42 -0800216}
217
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700218// checkA2dpEnabledChange_l() must be called with AudioFlinger::mLock held
219void AudioFlinger::checkA2dpEnabledChange_l()
The Android Open Source Projecte41dd752009-01-22 00:13:42 -0800220{
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700221 if (mNotifyA2dpChange) {
222 // Notify AudioSystem of the A2DP activation/deactivation
223 size_t size = mNotificationClients.size();
224 for (size_t i = 0; i < size; i++) {
225 sp<IBinder> binder = mNotificationClients.itemAt(i).promote();
226 if (binder != NULL) {
227 LOGV("Notifying output change to client %p", binder.get());
228 sp<IAudioFlingerClient> client = interface_cast<IAudioFlingerClient> (binder);
229 client->a2dpEnabledChanged(mA2dpEnabled);
230 }
231 }
232 mNotifyA2dpChange = false;
The Android Open Source Projecte41dd752009-01-22 00:13:42 -0800233 }
234}
235#endif // WITH_A2DP
236
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800237bool AudioFlinger::streamForcedToSpeaker(int streamType)
238{
239 // NOTE that streams listed here must not be routed to A2DP by default:
240 // AudioSystem::routedToA2dpOutput(streamType) == false
241 return (streamType == AudioSystem::RING ||
242 streamType == AudioSystem::ALARM ||
243 streamType == AudioSystem::NOTIFICATION);
244}
245
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700246bool AudioFlinger::streamDisablesA2dp(int streamType)
247{
248 return (streamType == AudioSystem::VOICE_CALL ||
249 streamType == AudioSystem::BLUETOOTH_SCO);
250}
251
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700252status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args)
253{
254 const size_t SIZE = 256;
255 char buffer[SIZE];
256 String8 result;
257
258 result.append("Clients:\n");
259 for (size_t i = 0; i < mClients.size(); ++i) {
260 wp<Client> wClient = mClients.valueAt(i);
261 if (wClient != 0) {
262 sp<Client> client = wClient.promote();
263 if (client != 0) {
264 snprintf(buffer, SIZE, " pid: %d\n", client->pid());
265 result.append(buffer);
266 }
267 }
268 }
269 write(fd, result.string(), result.size());
270 return NO_ERROR;
271}
272
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700273
274status_t AudioFlinger::dumpInternals(int fd, const Vector<String16>& args)
275{
276 const size_t SIZE = 256;
277 char buffer[SIZE];
278 String8 result;
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700279 int hardwareStatus = mHardwareStatus;
280
281 if (hardwareStatus == AUDIO_HW_IDLE && mHardwareMixerThread->mStandby) {
282 hardwareStatus = AUDIO_HW_STANDBY;
283 }
284 snprintf(buffer, SIZE, "Hardware status: %d\n", hardwareStatus);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700285 result.append(buffer);
286 write(fd, result.string(), result.size());
287 return NO_ERROR;
288}
289
290status_t AudioFlinger::dumpPermissionDenial(int fd, const Vector<String16>& args)
291{
292 const size_t SIZE = 256;
293 char buffer[SIZE];
294 String8 result;
295 snprintf(buffer, SIZE, "Permission Denial: "
296 "can't dump AudioFlinger from pid=%d, uid=%d\n",
297 IPCThreadState::self()->getCallingPid(),
298 IPCThreadState::self()->getCallingUid());
299 result.append(buffer);
300 write(fd, result.string(), result.size());
301 return NO_ERROR;
302}
303
304status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
305{
306 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
307 dumpPermissionDenial(fd, args);
308 } else {
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700309 bool locked = false;
310 for (int i = 0; i < kDumpLockRetries; ++i) {
311 if (mLock.tryLock() == NO_ERROR) {
312 locked = true;
313 break;
314 }
315 usleep(kDumpLockSleep);
316 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700317
318 dumpClients(fd, args);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700319 dumpInternals(fd, args);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800320 mHardwareMixerThread->dump(fd, args);
321#ifdef WITH_A2DP
322 mA2dpMixerThread->dump(fd, args);
323#endif
324
325 // dump record client
326 if (mAudioRecordThread != 0) mAudioRecordThread->dump(fd, args);
327
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700328 if (mAudioHardware) {
329 mAudioHardware->dumpState(fd, args);
330 }
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700331 if (locked) mLock.unlock();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700332 }
333 return NO_ERROR;
334}
335
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700336// IAudioFlinger interface
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800337
338
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700339sp<IAudioTrack> AudioFlinger::createTrack(
340 pid_t pid,
341 int streamType,
342 uint32_t sampleRate,
343 int format,
344 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800345 int frameCount,
346 uint32_t flags,
347 const sp<IMemory>& sharedBuffer,
348 status_t *status)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700349{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800350 sp<MixerThread::Track> track;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700351 sp<TrackHandle> trackHandle;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700352 sp<Client> client;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800353 wp<Client> wclient;
354 status_t lStatus;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700355
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800356 if (streamType >= AudioSystem::NUM_STREAM_TYPES) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800357 LOGE("invalid stream type");
358 lStatus = BAD_VALUE;
359 goto Exit;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700360 }
361
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800362 {
363 Mutex::Autolock _l(mLock);
364
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800365 wclient = mClients.valueFor(pid);
366
367 if (wclient != NULL) {
368 client = wclient.promote();
369 } else {
370 client = new Client(this, pid);
371 mClients.add(pid, client);
372 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800373#ifdef WITH_A2DP
374 if (isA2dpEnabled() && AudioSystem::routedToA2dpOutput(streamType)) {
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700375 track = mA2dpMixerThread->createTrack_l(client, streamType, sampleRate, format,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800376 channelCount, frameCount, sharedBuffer, &lStatus);
377 } else
378#endif
379 {
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700380 track = mHardwareMixerThread->createTrack_l(client, streamType, sampleRate, format,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800381 channelCount, frameCount, sharedBuffer, &lStatus);
382 }
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700383 }
384 if (lStatus == NO_ERROR) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800385 trackHandle = new TrackHandle(track);
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700386 } else {
387 track.clear();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800388 }
389
390Exit:
391 if(status) {
392 *status = lStatus;
393 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700394 return trackHandle;
395}
396
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800397uint32_t AudioFlinger::sampleRate(int output) const
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700398{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800399#ifdef WITH_A2DP
400 if (output == AudioSystem::AUDIO_OUTPUT_A2DP) {
401 return mA2dpMixerThread->sampleRate();
402 }
403#endif
404 return mHardwareMixerThread->sampleRate();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700405}
406
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800407int AudioFlinger::channelCount(int output) const
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700408{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800409#ifdef WITH_A2DP
410 if (output == AudioSystem::AUDIO_OUTPUT_A2DP) {
411 return mA2dpMixerThread->channelCount();
412 }
413#endif
414 return mHardwareMixerThread->channelCount();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700415}
416
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800417int AudioFlinger::format(int output) const
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700418{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800419#ifdef WITH_A2DP
420 if (output == AudioSystem::AUDIO_OUTPUT_A2DP) {
421 return mA2dpMixerThread->format();
422 }
423#endif
424 return mHardwareMixerThread->format();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700425}
426
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800427size_t AudioFlinger::frameCount(int output) const
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700428{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800429#ifdef WITH_A2DP
430 if (output == AudioSystem::AUDIO_OUTPUT_A2DP) {
431 return mA2dpMixerThread->frameCount();
432 }
433#endif
434 return mHardwareMixerThread->frameCount();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700435}
436
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800437uint32_t AudioFlinger::latency(int output) const
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800438{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800439#ifdef WITH_A2DP
440 if (output == AudioSystem::AUDIO_OUTPUT_A2DP) {
441 return mA2dpMixerThread->latency();
442 }
443#endif
444 return mHardwareMixerThread->latency();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800445}
446
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700447status_t AudioFlinger::setMasterVolume(float value)
448{
449 // check calling permissions
450 if (!settingsAllowed()) {
451 return PERMISSION_DENIED;
452 }
453
454 // when hw supports master volume, don't scale in sw mixer
455 AutoMutex lock(mHardwareLock);
456 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
457 if (mAudioHardware->setMasterVolume(value) == NO_ERROR) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800458 value = 1.0f;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700459 }
460 mHardwareStatus = AUDIO_HW_IDLE;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800461 mHardwareMixerThread->setMasterVolume(value);
462#ifdef WITH_A2DP
463 mA2dpMixerThread->setMasterVolume(value);
464#endif
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700465
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700466 return NO_ERROR;
467}
468
469status_t AudioFlinger::setRouting(int mode, uint32_t routes, uint32_t mask)
470{
The Android Open Source Project27629322009-01-09 17:51:23 -0800471 status_t err = NO_ERROR;
472
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700473 // check calling permissions
474 if (!settingsAllowed()) {
475 return PERMISSION_DENIED;
476 }
477 if ((mode < AudioSystem::MODE_CURRENT) || (mode >= AudioSystem::NUM_MODES)) {
478 LOGW("Illegal value: setRouting(%d, %u, %u)", mode, routes, mask);
479 return BAD_VALUE;
480 }
481
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800482#ifdef WITH_A2DP
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800483 LOGD("setRouting %d %d %d, tid %d, calling tid %d\n", mode, routes, mask, gettid(), IPCThreadState::self()->getCallingPid());
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800484 if (mode == AudioSystem::MODE_NORMAL &&
485 (mask & AudioSystem::ROUTE_BLUETOOTH_A2DP)) {
The Android Open Source Projecte41dd752009-01-22 00:13:42 -0800486 AutoMutex lock(&mLock);
487
488 bool enableA2dp = false;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800489 if (routes & AudioSystem::ROUTE_BLUETOOTH_A2DP) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800490 enableA2dp = true;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800491 }
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700492 if (mA2dpDisableCount > 0) {
493 mA2dpSuppressed = enableA2dp;
494 } else {
495 setA2dpEnabled_l(enableA2dp);
496 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800497 LOGV("setOutput done\n");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800498 }
499#endif
500
The Android Open Source Project27629322009-01-09 17:51:23 -0800501 // do nothing if only A2DP routing is affected
502 mask &= ~AudioSystem::ROUTE_BLUETOOTH_A2DP;
503 if (mask) {
504 AutoMutex lock(mHardwareLock);
505 mHardwareStatus = AUDIO_HW_GET_ROUTING;
506 uint32_t r;
507 err = mAudioHardware->getRouting(mode, &r);
508 if (err == NO_ERROR) {
509 r = (r & ~mask) | (routes & mask);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800510 if (mode == AudioSystem::MODE_NORMAL ||
511 (mode == AudioSystem::MODE_CURRENT && getMode() == AudioSystem::MODE_NORMAL)) {
512 mSavedRoute = r;
513 r |= mForcedRoute;
514 LOGV("setRouting mSavedRoute %08x mForcedRoute %08x\n", mSavedRoute, mForcedRoute);
515 }
The Android Open Source Project27629322009-01-09 17:51:23 -0800516 mHardwareStatus = AUDIO_HW_SET_ROUTING;
517 err = mAudioHardware->setRouting(mode, r);
518 }
519 mHardwareStatus = AUDIO_HW_IDLE;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700520 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700521 return err;
522}
523
524uint32_t AudioFlinger::getRouting(int mode) const
525{
526 uint32_t routes = 0;
527 if ((mode >= AudioSystem::MODE_CURRENT) && (mode < AudioSystem::NUM_MODES)) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800528 if (mode == AudioSystem::MODE_NORMAL ||
529 (mode == AudioSystem::MODE_CURRENT && getMode() == AudioSystem::MODE_NORMAL)) {
530 routes = mSavedRoute;
531 } else {
532 mHardwareStatus = AUDIO_HW_GET_ROUTING;
533 mAudioHardware->getRouting(mode, &routes);
534 mHardwareStatus = AUDIO_HW_IDLE;
535 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700536 } else {
537 LOGW("Illegal value: getRouting(%d)", mode);
538 }
539 return routes;
540}
541
542status_t AudioFlinger::setMode(int mode)
543{
544 // check calling permissions
545 if (!settingsAllowed()) {
546 return PERMISSION_DENIED;
547 }
548 if ((mode < 0) || (mode >= AudioSystem::NUM_MODES)) {
549 LOGW("Illegal value: setMode(%d)", mode);
550 return BAD_VALUE;
551 }
552
553 AutoMutex lock(mHardwareLock);
554 mHardwareStatus = AUDIO_HW_SET_MODE;
555 status_t ret = mAudioHardware->setMode(mode);
556 mHardwareStatus = AUDIO_HW_IDLE;
557 return ret;
558}
559
560int AudioFlinger::getMode() const
561{
562 int mode = AudioSystem::MODE_INVALID;
563 mHardwareStatus = AUDIO_HW_SET_MODE;
564 mAudioHardware->getMode(&mode);
565 mHardwareStatus = AUDIO_HW_IDLE;
566 return mode;
567}
568
569status_t AudioFlinger::setMicMute(bool state)
570{
571 // check calling permissions
572 if (!settingsAllowed()) {
573 return PERMISSION_DENIED;
574 }
575
576 AutoMutex lock(mHardwareLock);
577 mHardwareStatus = AUDIO_HW_SET_MIC_MUTE;
578 status_t ret = mAudioHardware->setMicMute(state);
579 mHardwareStatus = AUDIO_HW_IDLE;
580 return ret;
581}
582
583bool AudioFlinger::getMicMute() const
584{
585 bool state = AudioSystem::MODE_INVALID;
586 mHardwareStatus = AUDIO_HW_GET_MIC_MUTE;
587 mAudioHardware->getMicMute(&state);
588 mHardwareStatus = AUDIO_HW_IDLE;
589 return state;
590}
591
592status_t AudioFlinger::setMasterMute(bool muted)
593{
594 // check calling permissions
595 if (!settingsAllowed()) {
596 return PERMISSION_DENIED;
597 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800598 mHardwareMixerThread->setMasterMute(muted);
599#ifdef WITH_A2DP
600 mA2dpMixerThread->setMasterMute(muted);
601#endif
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700602 return NO_ERROR;
603}
604
605float AudioFlinger::masterVolume() const
606{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800607 return mHardwareMixerThread->masterVolume();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700608}
609
610bool AudioFlinger::masterMute() const
611{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800612 return mHardwareMixerThread->masterMute();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700613}
614
615status_t AudioFlinger::setStreamVolume(int stream, float value)
616{
617 // check calling permissions
618 if (!settingsAllowed()) {
619 return PERMISSION_DENIED;
620 }
621
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800622 if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700623 return BAD_VALUE;
624 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800625
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700626 status_t ret = NO_ERROR;
Jean-Baptiste Queru732ca392009-03-18 11:33:14 -0700627
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800628 if (stream == AudioSystem::VOICE_CALL ||
629 stream == AudioSystem::BLUETOOTH_SCO) {
Jean-Baptiste Queru732ca392009-03-18 11:33:14 -0700630 float hwValue = value;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800631 if (stream == AudioSystem::VOICE_CALL) {
Jean-Baptiste Queru732ca392009-03-18 11:33:14 -0700632 hwValue = (float)AudioSystem::logToLinear(value)/100.0f;
633 // FIXME: This is a temporary fix to re-base the internally
634 // generated in-call audio so that it is never muted, which is
635 // already the case for the hardware routed in-call audio.
636 // When audio stream handling is reworked, this should be
637 // addressed more cleanly. Fixes #1324; see discussion at
638 // http://review.source.android.com/8224
639 value = value * 0.99 + 0.01;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800640 } else { // (type == AudioSystem::BLUETOOTH_SCO)
Jean-Baptiste Queru732ca392009-03-18 11:33:14 -0700641 hwValue = 1.0f;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800642 }
643
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700644 AutoMutex lock(mHardwareLock);
645 mHardwareStatus = AUDIO_SET_VOICE_VOLUME;
Jean-Baptiste Queru732ca392009-03-18 11:33:14 -0700646 ret = mAudioHardware->setVoiceVolume(hwValue);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700647 mHardwareStatus = AUDIO_HW_IDLE;
Jean-Baptiste Queru732ca392009-03-18 11:33:14 -0700648
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700649 }
Jean-Baptiste Queru732ca392009-03-18 11:33:14 -0700650
651 mHardwareMixerThread->setStreamVolume(stream, value);
652#ifdef WITH_A2DP
653 mA2dpMixerThread->setStreamVolume(stream, value);
654#endif
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800655
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700656 return ret;
657}
658
659status_t AudioFlinger::setStreamMute(int stream, bool muted)
660{
661 // check calling permissions
662 if (!settingsAllowed()) {
663 return PERMISSION_DENIED;
664 }
665
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800666 if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700667 return BAD_VALUE;
668 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800669
670#ifdef WITH_A2DP
671 mA2dpMixerThread->setStreamMute(stream, muted);
672#endif
673 if (stream == AudioSystem::MUSIC)
674 {
675 AutoMutex lock(&mHardwareLock);
676 if (mForcedRoute != 0)
677 mMusicMuteSaved = muted;
678 else
679 mHardwareMixerThread->setStreamMute(stream, muted);
680 } else {
681 mHardwareMixerThread->setStreamMute(stream, muted);
682 }
683
684
685
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700686 return NO_ERROR;
687}
688
689float AudioFlinger::streamVolume(int stream) const
690{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800691 if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700692 return 0.0f;
693 }
Jean-Baptiste Queru732ca392009-03-18 11:33:14 -0700694 float value = mHardwareMixerThread->streamVolume(stream);
695
696 if (stream == AudioSystem::VOICE_CALL) {
James E. Blair6015dfc2009-01-17 13:30:20 -0800697 // FIXME: Re-base internally generated in-call audio,
698 // reverse of above in setStreamVolume.
Jean-Baptiste Queru732ca392009-03-18 11:33:14 -0700699 value = (value - 0.01) / 0.99;
James E. Blair6015dfc2009-01-17 13:30:20 -0800700 }
Jean-Baptiste Queru732ca392009-03-18 11:33:14 -0700701
702 return value;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700703}
704
705bool AudioFlinger::streamMute(int stream) const
706{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800707 if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700708 return true;
709 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800710
711 if (stream == AudioSystem::MUSIC && mForcedRoute != 0)
712 {
713 return mMusicMuteSaved;
714 }
715 return mHardwareMixerThread->streamMute(stream);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700716}
717
718bool AudioFlinger::isMusicActive() const
719{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800720 #ifdef WITH_A2DP
721 if (isA2dpEnabled()) {
722 return mA2dpMixerThread->isMusicActive();
723 }
724 #endif
725 return mHardwareMixerThread->isMusicActive();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700726}
727
728status_t AudioFlinger::setParameter(const char* key, const char* value)
729{
The Android Open Source Project8a7a6752009-01-15 16:12:10 -0800730 status_t result, result2;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700731 AutoMutex lock(mHardwareLock);
732 mHardwareStatus = AUDIO_SET_PARAMETER;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800733
734 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 -0700735 result = mAudioHardware->setParameter(key, value);
The Android Open Source Project8a7a6752009-01-15 16:12:10 -0800736 if (mA2dpAudioInterface) {
737 result2 = mA2dpAudioInterface->setParameter(key, value);
738 if (result2)
739 result = result2;
740 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700741 mHardwareStatus = AUDIO_HW_IDLE;
742 return result;
743}
744
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800745size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
746{
747 return mAudioHardware->getInputBufferSize(sampleRate, format, channelCount);
748}
749
750void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
751{
752
753 LOGV("registerClient() %p, tid %d, calling tid %d", client.get(), gettid(), IPCThreadState::self()->getCallingPid());
754 Mutex::Autolock _l(mLock);
755
756 sp<IBinder> binder = client->asBinder();
757 if (mNotificationClients.indexOf(binder) < 0) {
758 LOGV("Adding notification client %p", binder.get());
759 binder->linkToDeath(this);
760 mNotificationClients.add(binder);
761 client->a2dpEnabledChanged(isA2dpEnabled());
762 }
763}
764
765void AudioFlinger::binderDied(const wp<IBinder>& who) {
766
767 LOGV("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(), IPCThreadState::self()->getCallingPid());
768 Mutex::Autolock _l(mLock);
769
770 IBinder *binder = who.unsafe_get();
771
772 if (binder != NULL) {
773 int index = mNotificationClients.indexOf(binder);
774 if (index >= 0) {
775 LOGV("Removing notification client %p", binder);
776 mNotificationClients.removeAt(index);
777 }
778 }
779}
780
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700781void AudioFlinger::removeClient(pid_t pid)
782{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800783 LOGV("removeClient() pid %d, tid %d, calling tid %d", pid, gettid(), IPCThreadState::self()->getCallingPid());
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700784 Mutex::Autolock _l(mLock);
785 mClients.removeItem(pid);
786}
787
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800788bool AudioFlinger::isA2dpEnabled() const
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700789{
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700790 return mA2dpEnabled;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800791}
792
793void AudioFlinger::handleForcedSpeakerRoute(int command)
794{
795 switch(command) {
796 case ACTIVE_TRACK_ADDED:
797 {
798 AutoMutex lock(mHardwareLock);
799 if (mForcedSpeakerCount++ == 0) {
800 mRouteRestoreTime = 0;
801 mMusicMuteSaved = mHardwareMixerThread->streamMute(AudioSystem::MUSIC);
802 if (mForcedRoute == 0 && !(mSavedRoute & AudioSystem::ROUTE_SPEAKER)) {
803 LOGV("Route forced to Speaker ON %08x", mSavedRoute | AudioSystem::ROUTE_SPEAKER);
804 mHardwareMixerThread->setStreamMute(AudioSystem::MUSIC, true);
805 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
806 mAudioHardware->setMasterVolume(0);
807 usleep(mHardwareMixerThread->latency()*1000);
808 mHardwareStatus = AUDIO_HW_SET_ROUTING;
809 mAudioHardware->setRouting(AudioSystem::MODE_NORMAL, mSavedRoute | AudioSystem::ROUTE_SPEAKER);
810 mHardwareStatus = AUDIO_HW_IDLE;
811 // delay track start so that audio hardware has time to siwtch routes
812 usleep(kStartSleepTime);
813 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
814 mAudioHardware->setMasterVolume(mHardwareMixerThread->masterVolume());
815 mHardwareStatus = AUDIO_HW_IDLE;
816 }
817 mForcedRoute = AudioSystem::ROUTE_SPEAKER;
818 }
819 LOGV("mForcedSpeakerCount incremented to %d", mForcedSpeakerCount);
820 }
821 break;
822 case ACTIVE_TRACK_REMOVED:
823 {
824 AutoMutex lock(mHardwareLock);
825 if (mForcedSpeakerCount > 0){
826 if (--mForcedSpeakerCount == 0) {
827 mRouteRestoreTime = systemTime() + milliseconds(kStopSleepTime/1000);
828 }
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700829 LOGV("mForcedSpeakerCount decremented to %d", mForcedSpeakerCount);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800830 } else {
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700831 LOGE("mForcedSpeakerCount is already zero");
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700832 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800833 }
834 break;
835 case CHECK_ROUTE_RESTORE_TIME:
836 case FORCE_ROUTE_RESTORE:
837 if (mRouteRestoreTime) {
838 AutoMutex lock(mHardwareLock);
839 if (mRouteRestoreTime &&
840 (systemTime() > mRouteRestoreTime || command == FORCE_ROUTE_RESTORE)) {
841 mHardwareMixerThread->setStreamMute(AudioSystem::MUSIC, mMusicMuteSaved);
842 mForcedRoute = 0;
843 if (!(mSavedRoute & AudioSystem::ROUTE_SPEAKER)) {
844 mHardwareStatus = AUDIO_HW_SET_ROUTING;
845 mAudioHardware->setRouting(AudioSystem::MODE_NORMAL, mSavedRoute);
846 mHardwareStatus = AUDIO_HW_IDLE;
847 LOGV("Route forced to Speaker OFF %08x", mSavedRoute);
848 }
849 mRouteRestoreTime = 0;
850 }
851 }
852 break;
853 }
854}
855
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700856#ifdef WITH_A2DP
The Android Open Source Projectebad1472009-03-13 13:04:22 -0700857// handleStreamDisablesA2dp_l() must be called with AudioFlinger::mLock held
858void AudioFlinger::handleStreamDisablesA2dp_l(int command)
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700859{
860 switch(command) {
861 case ACTIVE_TRACK_ADDED:
862 {
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700863 if (mA2dpDisableCount++ == 0) {
864 if (mA2dpEnabled) {
865 setA2dpEnabled_l(false);
866 mA2dpSuppressed = true;
867 }
868 }
869 LOGV("mA2dpDisableCount incremented to %d", mA2dpDisableCount);
870 }
871 break;
872 case ACTIVE_TRACK_REMOVED:
873 {
The Android Open Source Projectebad1472009-03-13 13:04:22 -0700874 if (mA2dpDisableCount > 0) {
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700875 if (--mA2dpDisableCount == 0) {
876 if (mA2dpSuppressed) {
877 setA2dpEnabled_l(true);
878 mA2dpSuppressed = false;
879 }
880 }
881 LOGV("mA2dpDisableCount decremented to %d", mA2dpDisableCount);
882 } else {
883 LOGE("mA2dpDisableCount is already zero");
884 }
885 }
886 break;
887 }
888}
889#endif
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800890
891// ----------------------------------------------------------------------------
892
893AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int outputType)
894 : Thread(false),
895 mAudioFlinger(audioFlinger), mAudioMixer(0), mOutput(output), mOutputType(outputType),
896 mSampleRate(0), mFrameCount(0), mChannelCount(0), mFormat(0), mMixBuffer(0),
897 mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mStandby(false),
898 mInWrite(false)
899{
900 mSampleRate = output->sampleRate();
901 mChannelCount = output->channelCount();
902
903 // FIXME - Current mixer implementation only supports stereo output
904 if (mChannelCount == 1) {
905 LOGE("Invalid audio hardware channel count");
906 }
907
908 mFormat = output->format();
909 mFrameCount = output->bufferSize() / output->channelCount() / sizeof(int16_t);
910 mAudioMixer = new AudioMixer(mFrameCount, output->sampleRate());
911
912 // FIXME - Current mixer implementation only supports stereo output: Always
913 // Allocate a stereo buffer even if HW output is mono.
914 mMixBuffer = new int16_t[mFrameCount * 2];
915 memset(mMixBuffer, 0, mFrameCount * 2 * sizeof(int16_t));
916}
917
918AudioFlinger::MixerThread::~MixerThread()
919{
920 delete [] mMixBuffer;
921 delete mAudioMixer;
922}
923
924status_t AudioFlinger::MixerThread::dump(int fd, const Vector<String16>& args)
925{
926 dumpInternals(fd, args);
927 dumpTracks(fd, args);
928 return NO_ERROR;
929}
930
931status_t AudioFlinger::MixerThread::dumpTracks(int fd, const Vector<String16>& args)
932{
933 const size_t SIZE = 256;
934 char buffer[SIZE];
935 String8 result;
936
937 snprintf(buffer, SIZE, "Output %d mixer thread tracks\n", mOutputType);
938 result.append(buffer);
939 result.append(" Name Clien Typ Fmt Chn Buf S M F SRate LeftV RighV Serv User\n");
940 for (size_t i = 0; i < mTracks.size(); ++i) {
941 wp<Track> wTrack = mTracks[i];
942 if (wTrack != 0) {
943 sp<Track> track = wTrack.promote();
944 if (track != 0) {
945 track->dump(buffer, SIZE);
946 result.append(buffer);
947 }
948 }
949 }
950
951 snprintf(buffer, SIZE, "Output %d mixer thread active tracks\n", mOutputType);
952 result.append(buffer);
953 result.append(" Name Clien Typ Fmt Chn Buf S M F SRate LeftV RighV Serv User\n");
954 for (size_t i = 0; i < mActiveTracks.size(); ++i) {
955 wp<Track> wTrack = mTracks[i];
956 if (wTrack != 0) {
957 sp<Track> track = wTrack.promote();
958 if (track != 0) {
959 track->dump(buffer, SIZE);
960 result.append(buffer);
961 }
962 }
963 }
964 write(fd, result.string(), result.size());
965 return NO_ERROR;
966}
967
968status_t AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>& args)
969{
970 const size_t SIZE = 256;
971 char buffer[SIZE];
972 String8 result;
973
974 snprintf(buffer, SIZE, "Output %d mixer thread internals\n", mOutputType);
975 result.append(buffer);
976 snprintf(buffer, SIZE, "AudioMixer tracks: %08x\n", mAudioMixer->trackNames());
977 result.append(buffer);
978 snprintf(buffer, SIZE, "last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime));
979 result.append(buffer);
980 snprintf(buffer, SIZE, "total writes: %d\n", mNumWrites);
981 result.append(buffer);
982 snprintf(buffer, SIZE, "delayed writes: %d\n", mNumDelayedWrites);
983 result.append(buffer);
984 snprintf(buffer, SIZE, "blocked in write: %d\n", mInWrite);
985 result.append(buffer);
986 snprintf(buffer, SIZE, "standby: %d\n", mStandby);
987 result.append(buffer);
988 write(fd, result.string(), result.size());
989 return NO_ERROR;
990}
991
992// Thread virtuals
993bool AudioFlinger::MixerThread::threadLoop()
994{
995 unsigned long sleepTime = kBufferRecoveryInUsecs;
996 int16_t* curBuf = mMixBuffer;
997 Vector< sp<Track> > tracksToRemove;
998 size_t enabledTracks = 0;
999 nsecs_t standbyTime = systemTime();
1000 size_t mixBufferSize = mFrameCount*mChannelCount*sizeof(int16_t);
1001 nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 2;
1002
1003#ifdef WITH_A2DP
1004 bool outputTrackActive = false;
1005#endif
1006
1007 do {
1008 enabledTracks = 0;
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001009 { // scope for the AudioFlinger::mLock
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001010
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001011 Mutex::Autolock _l(mAudioFlinger->mLock);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001012
1013#ifdef WITH_A2DP
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001014 if (mOutputTrack != NULL && !mAudioFlinger->isA2dpEnabled()) {
1015 if (outputTrackActive) {
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001016 mAudioFlinger->mLock.unlock();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001017 mOutputTrack->stop();
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001018 mAudioFlinger->mLock.lock();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001019 outputTrackActive = false;
1020 }
1021 }
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001022 mAudioFlinger->checkA2dpEnabledChange_l();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001023#endif
1024
1025 const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
1026
1027 // put audio hardware into standby after short delay
1028 if UNLIKELY(!activeTracks.size() && systemTime() > standbyTime) {
1029 // wait until we have something to do...
1030 LOGV("Audio hardware entering standby, output %d\n", mOutputType);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001031 if (!mStandby) {
1032 mOutput->standby();
1033 mStandby = true;
1034 }
1035
1036#ifdef WITH_A2DP
1037 if (outputTrackActive) {
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001038 mAudioFlinger->mLock.unlock();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001039 mOutputTrack->stop();
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001040 mAudioFlinger->mLock.lock();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001041 outputTrackActive = false;
1042 }
1043#endif
1044 if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) {
1045 mAudioFlinger->handleForcedSpeakerRoute(FORCE_ROUTE_RESTORE);
1046 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001047 // we're about to wait, flush the binder command buffer
1048 IPCThreadState::self()->flushCommands();
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001049 mAudioFlinger->mWaitWorkCV.wait(mAudioFlinger->mLock);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001050 LOGV("Audio hardware exiting standby, output %d\n", mOutputType);
1051
1052 if (mMasterMute == false) {
1053 char value[PROPERTY_VALUE_MAX];
1054 property_get("ro.audio.silent", value, "0");
1055 if (atoi(value)) {
1056 LOGD("Silence is golden");
1057 setMasterMute(true);
1058 }
1059 }
1060
1061 standbyTime = systemTime() + kStandbyTimeInNsecs;
1062 continue;
1063 }
1064
1065 // Forced route to speaker is handled by hardware mixer thread
1066 if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) {
1067 mAudioFlinger->handleForcedSpeakerRoute(CHECK_ROUTE_RESTORE_TIME);
1068 }
1069
1070 // find out which tracks need to be processed
1071 size_t count = activeTracks.size();
1072 for (size_t i=0 ; i<count ; i++) {
1073 sp<Track> t = activeTracks[i].promote();
1074 if (t == 0) continue;
1075
1076 Track* const track = t.get();
1077 audio_track_cblk_t* cblk = track->cblk();
1078
1079 // The first time a track is added we wait
1080 // for all its buffers to be filled before processing it
1081 mAudioMixer->setActiveTrack(track->name());
1082 if (cblk->framesReady() && (track->isReady() || track->isStopped()) &&
1083 !track->isPaused())
1084 {
1085 //LOGV("track %d u=%08x, s=%08x [OK]", track->name(), cblk->user, cblk->server);
1086
1087 // compute volume for this track
1088 int16_t left, right;
1089 if (track->isMuted() || mMasterMute || track->isPausing()) {
1090 left = right = 0;
1091 if (track->isPausing()) {
1092 LOGV("paused(%d)", track->name());
1093 track->setPaused();
1094 }
1095 } else {
1096 float typeVolume = mStreamTypes[track->type()].volume;
1097 float v = mMasterVolume * typeVolume;
1098 float v_clamped = v * cblk->volume[0];
1099 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
1100 left = int16_t(v_clamped);
1101 v_clamped = v * cblk->volume[1];
1102 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
1103 right = int16_t(v_clamped);
1104 }
1105
1106 // XXX: these things DON'T need to be done each time
1107 mAudioMixer->setBufferProvider(track);
1108 mAudioMixer->enable(AudioMixer::MIXING);
1109
1110 int param;
1111 if ( track->mFillingUpStatus == Track::FS_FILLED) {
1112 // no ramp for the first volume setting
1113 track->mFillingUpStatus = Track::FS_ACTIVE;
1114 if (track->mState == TrackBase::RESUMING) {
1115 track->mState = TrackBase::ACTIVE;
1116 param = AudioMixer::RAMP_VOLUME;
1117 } else {
1118 param = AudioMixer::VOLUME;
1119 }
1120 } else {
1121 param = AudioMixer::RAMP_VOLUME;
1122 }
1123 mAudioMixer->setParameter(param, AudioMixer::VOLUME0, left);
1124 mAudioMixer->setParameter(param, AudioMixer::VOLUME1, right);
1125 mAudioMixer->setParameter(
1126 AudioMixer::TRACK,
1127 AudioMixer::FORMAT, track->format());
1128 mAudioMixer->setParameter(
1129 AudioMixer::TRACK,
1130 AudioMixer::CHANNEL_COUNT, track->channelCount());
1131 mAudioMixer->setParameter(
1132 AudioMixer::RESAMPLE,
1133 AudioMixer::SAMPLE_RATE,
1134 int(cblk->sampleRate));
1135
1136 // reset retry count
1137 track->mRetryCount = kMaxTrackRetries;
1138 enabledTracks++;
1139 } else {
1140 //LOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
1141 if (track->isStopped()) {
1142 track->reset();
1143 }
1144 if (track->isTerminated() || track->isStopped() || track->isPaused()) {
1145 // We have consumed all the buffers of this track.
1146 // Remove it from the list of active tracks.
1147 LOGV("remove(%d) from active list", track->name());
1148 tracksToRemove.add(track);
1149 } else {
1150 // No buffers for this track. Give it a few chances to
1151 // fill a buffer, then remove it from active list.
1152 if (--(track->mRetryCount) <= 0) {
1153 LOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
1154 tracksToRemove.add(track);
1155 }
1156 }
1157 // LOGV("disable(%d)", track->name());
1158 mAudioMixer->disable(AudioMixer::MIXING);
1159 }
1160 }
1161
1162 // remove all the tracks that need to be...
1163 count = tracksToRemove.size();
1164 if (UNLIKELY(count)) {
1165 for (size_t i=0 ; i<count ; i++) {
1166 const sp<Track>& track = tracksToRemove[i];
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001167 removeActiveTrack_l(track);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001168 if (track->isTerminated()) {
1169 mTracks.remove(track);
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001170 deleteTrackName_l(track->mName);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001171 }
1172 }
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001173 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001174 }
1175
1176 if (LIKELY(enabledTracks)) {
1177 // mix buffers...
1178 mAudioMixer->process(curBuf);
1179
1180#ifdef WITH_A2DP
1181 if (mOutputTrack != NULL && mAudioFlinger->isA2dpEnabled()) {
1182 if (!outputTrackActive) {
1183 LOGV("starting output track in mixer for output %d", mOutputType);
1184 mOutputTrack->start();
1185 outputTrackActive = true;
1186 }
1187 mOutputTrack->write(curBuf, mFrameCount);
1188 }
1189#endif
1190
1191 // output audio to hardware
1192 mLastWriteTime = systemTime();
1193 mInWrite = true;
1194 mOutput->write(curBuf, mixBufferSize);
1195 mNumWrites++;
1196 mInWrite = false;
1197 mStandby = false;
1198 nsecs_t temp = systemTime();
1199 standbyTime = temp + kStandbyTimeInNsecs;
1200 nsecs_t delta = temp - mLastWriteTime;
1201 if (delta > maxPeriod) {
1202 LOGW("write blocked for %llu msecs", ns2ms(delta));
1203 mNumDelayedWrites++;
1204 }
1205 sleepTime = kBufferRecoveryInUsecs;
1206 } else {
1207#ifdef WITH_A2DP
1208 if (mOutputTrack != NULL && mAudioFlinger->isA2dpEnabled()) {
1209 if (outputTrackActive) {
1210 mOutputTrack->write(curBuf, 0);
1211 if (mOutputTrack->bufferQueueEmpty()) {
1212 mOutputTrack->stop();
1213 outputTrackActive = false;
1214 } else {
1215 standbyTime = systemTime() + kStandbyTimeInNsecs;
1216 }
1217 }
1218 }
1219#endif
1220 // There was nothing to mix this round, which means all
1221 // active tracks were late. Sleep a little bit to give
1222 // them another chance. If we're too late, the audio
1223 // hardware will zero-fill for us.
1224 //LOGV("no buffers - usleep(%lu)", sleepTime);
1225 usleep(sleepTime);
1226 if (sleepTime < kMaxBufferRecoveryInUsecs) {
1227 sleepTime += kBufferRecoveryInUsecs;
1228 }
1229 }
1230
1231 // finally let go of all our tracks, without the lock held
1232 // since we can't guarantee the destructors won't acquire that
1233 // same lock.
1234 tracksToRemove.clear();
1235 } while (true);
1236
1237 return false;
1238}
1239
1240status_t AudioFlinger::MixerThread::readyToRun()
1241{
1242 if (mSampleRate == 0) {
1243 LOGE("No working audio driver found.");
1244 return NO_INIT;
1245 }
1246 LOGI("AudioFlinger's thread ready to run for output %d", mOutputType);
1247 return NO_ERROR;
1248}
1249
1250void AudioFlinger::MixerThread::onFirstRef()
1251{
1252 const size_t SIZE = 256;
1253 char buffer[SIZE];
1254
1255 snprintf(buffer, SIZE, "Mixer Thread for output %d", mOutputType);
1256
1257 run(buffer, ANDROID_PRIORITY_URGENT_AUDIO);
1258}
1259
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001260// MixerThread::createTrack_l() must be called with AudioFlinger::mLock held
1261sp<AudioFlinger::MixerThread::Track> AudioFlinger::MixerThread::createTrack_l(
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001262 const sp<AudioFlinger::Client>& client,
1263 int streamType,
1264 uint32_t sampleRate,
1265 int format,
1266 int channelCount,
1267 int frameCount,
1268 const sp<IMemory>& sharedBuffer,
1269 status_t *status)
1270{
1271 sp<Track> track;
1272 status_t lStatus;
1273
1274 // Resampler implementation limits input sampling rate to 2 x output sampling rate.
1275 if (sampleRate > MAX_SAMPLE_RATE || sampleRate > mSampleRate*2) {
1276 LOGE("Sample rate out of range: %d mSampleRate %d", sampleRate, mSampleRate);
1277 lStatus = BAD_VALUE;
1278 goto Exit;
1279 }
1280
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001281
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001282 if (mSampleRate == 0) {
1283 LOGE("Audio driver not initialized.");
1284 lStatus = NO_INIT;
1285 goto Exit;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001286 }
1287
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001288 track = new Track(this, client, streamType, sampleRate, format,
1289 channelCount, frameCount, sharedBuffer);
1290 if (track->getCblk() == NULL) {
1291 lStatus = NO_MEMORY;
1292 goto Exit;
1293 }
1294 mTracks.add(track);
1295 lStatus = NO_ERROR;
1296
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001297Exit:
1298 if(status) {
1299 *status = lStatus;
1300 }
1301 return track;
1302}
1303
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001304// getTracks_l() must be called with AudioFlinger::mLock held
1305void AudioFlinger::MixerThread::getTracks_l(
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001306 SortedVector < sp<Track> >& tracks,
1307 SortedVector < wp<Track> >& activeTracks)
1308{
1309 size_t size = mTracks.size();
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001310 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 -08001311 for (size_t i = 0; i < size; i++) {
1312 sp<Track> t = mTracks[i];
1313 if (AudioSystem::routedToA2dpOutput(t->mStreamType)) {
1314 tracks.add(t);
1315 int j = mActiveTracks.indexOf(t);
1316 if (j >= 0) {
1317 t = mActiveTracks[j].promote();
1318 if (t != NULL) {
1319 activeTracks.add(t);
1320 }
1321 }
1322 }
1323 }
1324
1325 size = activeTracks.size();
1326 for (size_t i = 0; i < size; i++) {
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001327 removeActiveTrack_l(activeTracks[i]);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001328 }
1329
1330 size = tracks.size();
1331 for (size_t i = 0; i < size; i++) {
1332 sp<Track> t = tracks[i];
1333 mTracks.remove(t);
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001334 deleteTrackName_l(t->name());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001335 }
1336}
1337
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001338// putTracks_l() must be called with AudioFlinger::mLock held
1339void AudioFlinger::MixerThread::putTracks_l(
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001340 SortedVector < sp<Track> >& tracks,
1341 SortedVector < wp<Track> >& activeTracks)
1342{
1343
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001344 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 -08001345
1346 size_t size = tracks.size();
1347 for (size_t i = 0; i < size ; i++) {
1348 sp<Track> t = tracks[i];
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001349 int name = getTrackName_l();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001350
1351 if (name < 0) return;
1352
1353 t->mName = name;
1354 t->mMixerThread = this;
1355 mTracks.add(t);
1356
1357 int j = activeTracks.indexOf(t);
1358 if (j >= 0) {
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001359 addActiveTrack_l(t);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001360 }
1361 }
1362}
1363
1364uint32_t AudioFlinger::MixerThread::sampleRate() const
1365{
1366 return mSampleRate;
1367}
1368
1369int AudioFlinger::MixerThread::channelCount() const
1370{
1371 return mChannelCount;
1372}
1373
1374int AudioFlinger::MixerThread::format() const
1375{
1376 return mFormat;
1377}
1378
1379size_t AudioFlinger::MixerThread::frameCount() const
1380{
1381 return mFrameCount;
1382}
1383
1384uint32_t AudioFlinger::MixerThread::latency() const
1385{
1386 if (mOutput) {
1387 return mOutput->latency();
1388 }
1389 else {
1390 return 0;
1391 }
1392}
1393
1394status_t AudioFlinger::MixerThread::setMasterVolume(float value)
1395{
1396 mMasterVolume = value;
1397 return NO_ERROR;
1398}
1399
1400status_t AudioFlinger::MixerThread::setMasterMute(bool muted)
1401{
1402 mMasterMute = muted;
1403 return NO_ERROR;
1404}
1405
1406float AudioFlinger::MixerThread::masterVolume() const
1407{
1408 return mMasterVolume;
1409}
1410
1411bool AudioFlinger::MixerThread::masterMute() const
1412{
1413 return mMasterMute;
1414}
1415
1416status_t AudioFlinger::MixerThread::setStreamVolume(int stream, float value)
1417{
1418 mStreamTypes[stream].volume = value;
1419 return NO_ERROR;
1420}
1421
1422status_t AudioFlinger::MixerThread::setStreamMute(int stream, bool muted)
1423{
1424 mStreamTypes[stream].mute = muted;
1425 return NO_ERROR;
1426}
1427
1428float AudioFlinger::MixerThread::streamVolume(int stream) const
1429{
1430 return mStreamTypes[stream].volume;
1431}
1432
1433bool AudioFlinger::MixerThread::streamMute(int stream) const
1434{
1435 return mStreamTypes[stream].mute;
1436}
1437
1438bool AudioFlinger::MixerThread::isMusicActive() const
1439{
1440 size_t count = mActiveTracks.size();
1441 for (size_t i = 0 ; i < count ; ++i) {
1442 sp<Track> t = mActiveTracks[i].promote();
1443 if (t == 0) continue;
1444 Track* const track = t.get();
1445 if (t->mStreamType == AudioSystem::MUSIC)
1446 return true;
1447 }
1448 return false;
1449}
1450
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001451// addTrack_l() must be called with AudioFlinger::mLock held
1452status_t AudioFlinger::MixerThread::addTrack_l(const sp<Track>& track)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001453{
1454 status_t status = ALREADY_EXISTS;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001455
1456 // here the track could be either new, or restarted
1457 // in both cases "unstop" the track
1458 if (track->isPaused()) {
1459 track->mState = TrackBase::RESUMING;
1460 LOGV("PAUSED => RESUMING (%d)", track->name());
1461 } else {
1462 track->mState = TrackBase::ACTIVE;
1463 LOGV("? => ACTIVE (%d)", track->name());
1464 }
1465 // set retry count for buffer fill
1466 track->mRetryCount = kMaxTrackStartupRetries;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001467 if (mActiveTracks.indexOf(track) < 0) {
1468 // the track is newly added, make sure it fills up all its
1469 // buffers before playing. This is to ensure the client will
1470 // effectively get the latency it requested.
1471 track->mFillingUpStatus = Track::FS_FILLING;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001472 track->mResetDone = false;
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001473 addActiveTrack_l(track);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001474 status = NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001475 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001476
1477 LOGV("mWaitWorkCV.broadcast");
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001478 mAudioFlinger->mWaitWorkCV.broadcast();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001479
1480 return status;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001481}
1482
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001483// removeTrack_l() must be called with AudioFlinger::mLock held
1484void AudioFlinger::MixerThread::removeTrack_l(wp<Track> track, int name)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001485{
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001486 sp<Track> t = track.promote();
1487 if (t!=NULL && (t->mState <= TrackBase::STOPPED)) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001488 t->reset();
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001489 deleteTrackName_l(name);
1490 removeActiveTrack_l(track);
1491 mAudioFlinger->mWaitWorkCV.broadcast();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001492 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001493}
1494
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001495// destroyTrack_l() must be called with AudioFlinger::mLock held
1496void AudioFlinger::MixerThread::destroyTrack_l(const sp<Track>& track)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001497{
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001498 track->mState = TrackBase::TERMINATED;
1499 if (mActiveTracks.indexOf(track) < 0) {
1500 LOGV("remove track (%d) and delete from mixer", track->name());
1501 mTracks.remove(track);
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001502 deleteTrackName_l(track->name());
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001503 }
1504}
1505
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001506// addActiveTrack_l() must be called with AudioFlinger::mLock held
1507void AudioFlinger::MixerThread::addActiveTrack_l(const wp<Track>& t)
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001508{
1509 mActiveTracks.add(t);
1510
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001511 // Force routing to speaker for certain stream types
1512 // The forced routing to speaker is managed by hardware mixer
1513 if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) {
1514 sp<Track> track = t.promote();
1515 if (track == NULL) return;
1516
1517 if (streamForcedToSpeaker(track->type())) {
1518 mAudioFlinger->handleForcedSpeakerRoute(ACTIVE_TRACK_ADDED);
1519 }
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001520#ifdef WITH_A2DP
The Android Open Source Projectebad1472009-03-13 13:04:22 -07001521 // AudioFlinger::mLock must be locked before calling
1522 // handleStreamDisablesA2dp_l because it calls setA2dpEnabled_l().
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -07001523 if (streamDisablesA2dp(track->type())) {
The Android Open Source Projectebad1472009-03-13 13:04:22 -07001524 mAudioFlinger->handleStreamDisablesA2dp_l(ACTIVE_TRACK_ADDED);
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001525 }
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001526#endif
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001527 }
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001528}
1529
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001530// removeActiveTrack_l() must be called with AudioFlinger::mLock held
1531void AudioFlinger::MixerThread::removeActiveTrack_l(const wp<Track>& t)
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001532{
1533 mActiveTracks.remove(t);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001534
1535 // Force routing to speaker for certain stream types
1536 // The forced routing to speaker is managed by hardware mixer
1537 if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) {
1538 sp<Track> track = t.promote();
1539 if (track == NULL) return;
1540
1541 if (streamForcedToSpeaker(track->type())) {
1542 mAudioFlinger->handleForcedSpeakerRoute(ACTIVE_TRACK_REMOVED);
1543 }
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001544#ifdef WITH_A2DP
The Android Open Source Projectebad1472009-03-13 13:04:22 -07001545 // AudioFlinger::mLock must be locked before calling
1546 // handleStreamDisablesA2dp_l because it calls setA2dpEnabled_l().
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -07001547 if (streamDisablesA2dp(track->type())) {
The Android Open Source Projectebad1472009-03-13 13:04:22 -07001548 mAudioFlinger->handleStreamDisablesA2dp_l(ACTIVE_TRACK_REMOVED);
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -07001549 }
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001550#endif
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001551 }
1552}
1553
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001554// getTrackName_l() must be called with AudioFlinger::mLock held
1555int AudioFlinger::MixerThread::getTrackName_l()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001556{
1557 return mAudioMixer->getTrackName();
1558}
1559
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001560// deleteTrackName_l() must be called with AudioFlinger::mLock held
1561void AudioFlinger::MixerThread::deleteTrackName_l(int name)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001562{
1563 mAudioMixer->deleteTrackName(name);
1564}
1565
1566size_t AudioFlinger::MixerThread::getOutputFrameCount()
1567{
1568 return mOutput->bufferSize() / mOutput->channelCount() / sizeof(int16_t);
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001569}
1570
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001571// ----------------------------------------------------------------------------
1572
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001573// TrackBase constructor must be called with AudioFlinger::mLock held
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001574AudioFlinger::MixerThread::TrackBase::TrackBase(
1575 const sp<MixerThread>& mixerThread,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001576 const sp<Client>& client,
1577 int streamType,
1578 uint32_t sampleRate,
1579 int format,
1580 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001581 int frameCount,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001582 uint32_t flags,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001583 const sp<IMemory>& sharedBuffer)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001584 : RefBase(),
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001585 mMixerThread(mixerThread),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001586 mClient(client),
1587 mStreamType(streamType),
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001588 mFrameCount(0),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001589 mState(IDLE),
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001590 mClientTid(-1),
1591 mFormat(format),
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001592 mFlags(flags & ~SYSTEM_FLAGS_MASK)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001593{
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001594 mName = mixerThread->getTrackName_l();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001595 LOGV("TrackBase contructor name %d, calling thread %d", mName, IPCThreadState::self()->getCallingPid());
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001596 if (mName < 0) {
1597 LOGE("no more track names availlable");
1598 return;
1599 }
1600
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001601 LOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size());
1602
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001603 // LOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001604 size_t size = sizeof(audio_track_cblk_t);
1605 size_t bufferSize = frameCount*channelCount*sizeof(int16_t);
1606 if (sharedBuffer == 0) {
1607 size += bufferSize;
1608 }
1609
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001610 if (client != NULL) {
1611 mCblkMemory = client->heap()->allocate(size);
1612 if (mCblkMemory != 0) {
1613 mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer());
1614 if (mCblk) { // construct the shared structure in-place.
1615 new(mCblk) audio_track_cblk_t();
1616 // clear all buffers
1617 mCblk->frameCount = frameCount;
1618 mCblk->sampleRate = sampleRate;
1619 mCblk->channels = channelCount;
1620 if (sharedBuffer == 0) {
1621 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
1622 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
1623 // Force underrun condition to avoid false underrun callback until first data is
1624 // written to buffer
1625 mCblk->flowControlFlag = 1;
1626 } else {
1627 mBuffer = sharedBuffer->pointer();
1628 }
1629 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001630 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001631 } else {
1632 LOGE("not enough memory for AudioTrack size=%u", size);
1633 client->heap()->dump("AudioTrack");
1634 return;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001635 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001636 } else {
1637 mCblk = (audio_track_cblk_t *)(new uint8_t[size]);
1638 if (mCblk) { // construct the shared structure in-place.
1639 new(mCblk) audio_track_cblk_t();
1640 // clear all buffers
1641 mCblk->frameCount = frameCount;
1642 mCblk->sampleRate = sampleRate;
1643 mCblk->channels = channelCount;
1644 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
1645 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
1646 // Force underrun condition to avoid false underrun callback until first data is
1647 // written to buffer
1648 mCblk->flowControlFlag = 1;
1649 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
1650 }
1651 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001652}
1653
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001654AudioFlinger::MixerThread::TrackBase::~TrackBase()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001655{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001656 if (mCblk) {
1657 mCblk->~audio_track_cblk_t(); // destroy our shared-structure.
1658 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001659 mCblkMemory.clear(); // and free the shared memory
1660 mClient.clear();
1661}
1662
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001663void AudioFlinger::MixerThread::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001664{
1665 buffer->raw = 0;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001666 mFrameCount = buffer->frameCount;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001667 step();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001668 buffer->frameCount = 0;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001669}
1670
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001671bool AudioFlinger::MixerThread::TrackBase::step() {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001672 bool result;
1673 audio_track_cblk_t* cblk = this->cblk();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001674
1675 result = cblk->stepServer(mFrameCount);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001676 if (!result) {
1677 LOGV("stepServer failed acquiring cblk mutex");
1678 mFlags |= STEPSERVER_FAILED;
1679 }
1680 return result;
1681}
1682
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001683void AudioFlinger::MixerThread::TrackBase::reset() {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001684 audio_track_cblk_t* cblk = this->cblk();
1685
1686 cblk->user = 0;
1687 cblk->server = 0;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001688 cblk->userBase = 0;
1689 cblk->serverBase = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001690 mFlags &= (uint32_t)(~SYSTEM_FLAGS_MASK);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001691 LOGV("TrackBase::reset");
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001692}
1693
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001694sp<IMemory> AudioFlinger::MixerThread::TrackBase::getCblk() const
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001695{
1696 return mCblkMemory;
1697}
1698
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001699int AudioFlinger::MixerThread::TrackBase::sampleRate() const {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001700 return mCblk->sampleRate;
1701}
1702
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001703int AudioFlinger::MixerThread::TrackBase::channelCount() const {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001704 return mCblk->channels;
1705}
1706
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001707void* AudioFlinger::MixerThread::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001708 audio_track_cblk_t* cblk = this->cblk();
1709 int16_t *bufferStart = (int16_t *)mBuffer + (offset-cblk->serverBase)*cblk->channels;
1710 int16_t *bufferEnd = bufferStart + frames * cblk->channels;
1711
1712 // Check validity of returned pointer in case the track control block would have been corrupted.
1713 if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd) {
1714 LOGW("TrackBase::getBuffer buffer out of range:\n start: %p, end %p , mBuffer %p mBufferEnd %p\n \
1715 server %d, serverBase %d, user %d, userBase %d",
1716 bufferStart, bufferEnd, mBuffer, mBufferEnd,
1717 cblk->server, cblk->serverBase, cblk->user, cblk->userBase);
1718 return 0;
1719 }
1720
1721 return bufferStart;
1722}
1723
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001724// ----------------------------------------------------------------------------
1725
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001726// Track constructor must be called with AudioFlinger::mLock held
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001727AudioFlinger::MixerThread::Track::Track(
1728 const sp<MixerThread>& mixerThread,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001729 const sp<Client>& client,
1730 int streamType,
1731 uint32_t sampleRate,
1732 int format,
1733 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001734 int frameCount,
1735 const sp<IMemory>& sharedBuffer)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001736 : TrackBase(mixerThread, client, streamType, sampleRate, format, channelCount, frameCount, 0, sharedBuffer)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001737{
1738 mVolume[0] = 1.0f;
1739 mVolume[1] = 1.0f;
1740 mMute = false;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001741 mSharedBuffer = sharedBuffer;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001742}
1743
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001744AudioFlinger::MixerThread::Track::~Track()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001745{
1746 wp<Track> weak(this); // never create a strong ref from the dtor
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001747 Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001748 mState = TERMINATED;
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001749 mMixerThread->removeTrack_l(weak, mName);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001750}
1751
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001752void AudioFlinger::MixerThread::Track::destroy()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001753{
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001754 // NOTE: destroyTrack_l() can remove a strong reference to this Track
1755 // by removing it from mTracks vector, so there is a risk that this Tracks's
1756 // desctructor is called. As the destructor needs to lock AudioFlinger::mLock,
1757 // we must acquire a strong reference on this Track before locking AudioFlinger::mLock
1758 // here so that the destructor is called only when exiting this function.
1759 // On the other hand, as long as Track::destroy() is only called by
1760 // TrackHandle destructor, the TrackHandle still holds a strong ref on
1761 // this Track with its member mTrack.
1762 sp<Track> keep(this);
1763 { // scope for AudioFlinger::mLock
1764 Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
1765 mMixerThread->destroyTrack_l(this);
1766 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001767}
1768
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001769void AudioFlinger::MixerThread::Track::dump(char* buffer, size_t size)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001770{
1771 snprintf(buffer, size, " %5d %5d %3u %3u %3u %3u %1d %1d %1d %5u %5u %5u %04x %04x\n",
1772 mName - AudioMixer::TRACK0,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001773 (mClient == NULL) ? getpid() : mClient->pid(),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001774 mStreamType,
1775 mFormat,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001776 mCblk->channels,
1777 mFrameCount,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001778 mState,
1779 mMute,
1780 mFillingUpStatus,
1781 mCblk->sampleRate,
1782 mCblk->volume[0],
1783 mCblk->volume[1],
1784 mCblk->server,
1785 mCblk->user);
1786}
1787
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001788status_t AudioFlinger::MixerThread::Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001789{
1790 audio_track_cblk_t* cblk = this->cblk();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001791 uint32_t framesReady;
1792 uint32_t framesReq = buffer->frameCount;
1793
1794 // Check if last stepServer failed, try to step now
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001795 if (mFlags & TrackBase::STEPSERVER_FAILED) {
1796 if (!step()) goto getNextBuffer_exit;
1797 LOGV("stepServer recovered");
1798 mFlags &= ~TrackBase::STEPSERVER_FAILED;
1799 }
1800
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001801 framesReady = cblk->framesReady();
1802
1803 if (LIKELY(framesReady)) {
1804 uint32_t s = cblk->server;
1805 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
1806
1807 bufferEnd = (cblk->loopEnd < bufferEnd) ? cblk->loopEnd : bufferEnd;
1808 if (framesReq > framesReady) {
1809 framesReq = framesReady;
1810 }
1811 if (s + framesReq > bufferEnd) {
1812 framesReq = bufferEnd - s;
1813 }
1814
1815 buffer->raw = getBuffer(s, framesReq);
1816 if (buffer->raw == 0) goto getNextBuffer_exit;
1817
1818 buffer->frameCount = framesReq;
1819 return NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001820 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001821
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001822getNextBuffer_exit:
1823 buffer->raw = 0;
1824 buffer->frameCount = 0;
1825 return NOT_ENOUGH_DATA;
1826}
1827
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001828bool AudioFlinger::MixerThread::Track::isReady() const {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001829 if (mFillingUpStatus != FS_FILLING) return true;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001830
1831 if (mCblk->framesReady() >= mCblk->frameCount ||
1832 mCblk->forceReady) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001833 mFillingUpStatus = FS_FILLED;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001834 mCblk->forceReady = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001835 LOGV("Track::isReady() track %d for output %d", mName, mMixerThread->mOutputType);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001836 return true;
1837 }
1838 return false;
1839}
1840
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001841status_t AudioFlinger::MixerThread::Track::start()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001842{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001843 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 -07001844 Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
1845 mMixerThread->addTrack_l(this);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001846 return NO_ERROR;
1847}
1848
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001849void AudioFlinger::MixerThread::Track::stop()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001850{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001851 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 -07001852 Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001853 if (mState > STOPPED) {
1854 mState = STOPPED;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001855 // If the track is not active (PAUSED and buffers full), flush buffers
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001856 if (mMixerThread->mActiveTracks.indexOf(this) < 0) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001857 reset();
1858 }
1859 LOGV("(> STOPPED) => STOPPED (%d)", mName);
1860 }
1861}
1862
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001863void AudioFlinger::MixerThread::Track::pause()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001864{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001865 LOGV("pause(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001866 Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001867 if (mState == ACTIVE || mState == RESUMING) {
1868 mState = PAUSING;
1869 LOGV("ACTIVE/RESUMING => PAUSING (%d)", mName);
1870 }
1871}
1872
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001873void AudioFlinger::MixerThread::Track::flush()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001874{
1875 LOGV("flush(%d)", mName);
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001876 Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001877 if (mState != STOPPED && mState != PAUSED && mState != PAUSING) {
1878 return;
1879 }
1880 // No point remaining in PAUSED state after a flush => go to
1881 // STOPPED state
1882 mState = STOPPED;
1883
1884 // NOTE: reset() will reset cblk->user and cblk->server with
1885 // the risk that at the same time, the AudioMixer is trying to read
1886 // data. In this case, getNextBuffer() would return a NULL pointer
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001887 // as audio buffer => the AudioMixer code MUST always test that pointer
1888 // returned by getNextBuffer() is not NULL!
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001889 reset();
1890}
1891
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001892void AudioFlinger::MixerThread::Track::reset()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001893{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001894 // Do not reset twice to avoid discarding data written just after a flush and before
1895 // the audioflinger thread detects the track is stopped.
1896 if (!mResetDone) {
1897 TrackBase::reset();
1898 // Force underrun condition to avoid false underrun callback until first data is
1899 // written to buffer
1900 mCblk->flowControlFlag = 1;
1901 mCblk->forceReady = 0;
1902 mFillingUpStatus = FS_FILLING;
1903 mResetDone = true;
1904 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001905}
1906
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001907void AudioFlinger::MixerThread::Track::mute(bool muted)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001908{
1909 mMute = muted;
1910}
1911
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001912void AudioFlinger::MixerThread::Track::setVolume(float left, float right)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001913{
1914 mVolume[0] = left;
1915 mVolume[1] = right;
1916}
1917
1918// ----------------------------------------------------------------------------
1919
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001920// RecordTrack constructor must be called with AudioFlinger::mLock held
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001921AudioFlinger::MixerThread::RecordTrack::RecordTrack(
1922 const sp<MixerThread>& mixerThread,
1923 const sp<Client>& client,
1924 int streamType,
1925 uint32_t sampleRate,
1926 int format,
1927 int channelCount,
1928 int frameCount,
1929 uint32_t flags)
1930 : TrackBase(mixerThread, client, streamType, sampleRate, format,
1931 channelCount, frameCount, flags, 0),
1932 mOverflow(false)
1933{
1934}
1935
1936AudioFlinger::MixerThread::RecordTrack::~RecordTrack()
1937{
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001938 Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
1939 mMixerThread->deleteTrackName_l(mName);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001940}
1941
1942status_t AudioFlinger::MixerThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
1943{
1944 audio_track_cblk_t* cblk = this->cblk();
1945 uint32_t framesAvail;
1946 uint32_t framesReq = buffer->frameCount;
1947
1948 // Check if last stepServer failed, try to step now
1949 if (mFlags & TrackBase::STEPSERVER_FAILED) {
1950 if (!step()) goto getNextBuffer_exit;
1951 LOGV("stepServer recovered");
1952 mFlags &= ~TrackBase::STEPSERVER_FAILED;
1953 }
1954
1955 framesAvail = cblk->framesAvailable_l();
1956
1957 if (LIKELY(framesAvail)) {
1958 uint32_t s = cblk->server;
1959 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
1960
1961 if (framesReq > framesAvail) {
1962 framesReq = framesAvail;
1963 }
1964 if (s + framesReq > bufferEnd) {
1965 framesReq = bufferEnd - s;
1966 }
1967
1968 buffer->raw = getBuffer(s, framesReq);
1969 if (buffer->raw == 0) goto getNextBuffer_exit;
1970
1971 buffer->frameCount = framesReq;
1972 return NO_ERROR;
1973 }
1974
1975getNextBuffer_exit:
1976 buffer->raw = 0;
1977 buffer->frameCount = 0;
1978 return NOT_ENOUGH_DATA;
1979}
1980
1981status_t AudioFlinger::MixerThread::RecordTrack::start()
1982{
1983 return mMixerThread->mAudioFlinger->startRecord(this);
1984}
1985
1986void AudioFlinger::MixerThread::RecordTrack::stop()
1987{
1988 mMixerThread->mAudioFlinger->stopRecord(this);
1989 TrackBase::reset();
1990 // Force overerrun condition to avoid false overrun callback until first data is
1991 // read from buffer
1992 mCblk->flowControlFlag = 1;
1993}
1994
1995
1996// ----------------------------------------------------------------------------
1997
1998AudioFlinger::MixerThread::OutputTrack::OutputTrack(
1999 const sp<MixerThread>& mixerThread,
2000 uint32_t sampleRate,
2001 int format,
2002 int channelCount,
2003 int frameCount)
2004 : Track(mixerThread, NULL, AudioSystem::SYSTEM, sampleRate, format, channelCount, frameCount, NULL),
2005 mOutputMixerThread(mixerThread)
2006{
2007
2008 mCblk->out = 1;
2009 mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
2010 mCblk->volume[0] = mCblk->volume[1] = 0x1000;
2011 mOutBuffer.frameCount = 0;
2012 mCblk->bufferTimeoutMs = 10;
2013
2014 LOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, mCblk->frameCount %d, mCblk->sampleRate %d, mCblk->channels %d mBufferEnd %p",
2015 mCblk, mBuffer, mCblk->buffers, mCblk->frameCount, mCblk->sampleRate, mCblk->channels, mBufferEnd);
2016
2017}
2018
2019AudioFlinger::MixerThread::OutputTrack::~OutputTrack()
2020{
2021 stop();
2022}
2023
2024status_t AudioFlinger::MixerThread::OutputTrack::start()
2025{
2026 status_t status = Track::start();
2027
2028 mRetryCount = 127;
2029 return status;
2030}
2031
2032void AudioFlinger::MixerThread::OutputTrack::stop()
2033{
2034 Track::stop();
2035 clearBufferQueue();
2036 mOutBuffer.frameCount = 0;
2037}
2038
2039void AudioFlinger::MixerThread::OutputTrack::write(int16_t* data, uint32_t frames)
2040{
2041 Buffer *pInBuffer;
2042 Buffer inBuffer;
2043 uint32_t channels = mCblk->channels;
2044
2045 inBuffer.frameCount = frames;
2046 inBuffer.i16 = data;
2047
2048 if (mCblk->user == 0) {
2049 if (mOutputMixerThread->isMusicActive()) {
2050 mCblk->forceReady = 1;
2051 LOGV("OutputTrack::start() force ready");
2052 } else if (mCblk->frameCount > frames){
2053 if (mBufferQueue.size() < kMaxOutputTrackBuffers) {
2054 uint32_t startFrames = (mCblk->frameCount - frames);
2055 LOGV("OutputTrack::start() write %d frames", startFrames);
2056 pInBuffer = new Buffer;
2057 pInBuffer->mBuffer = new int16_t[startFrames * channels];
2058 pInBuffer->frameCount = startFrames;
2059 pInBuffer->i16 = pInBuffer->mBuffer;
2060 memset(pInBuffer->raw, 0, startFrames * channels * sizeof(int16_t));
2061 mBufferQueue.add(pInBuffer);
2062 } else {
2063 LOGW ("OutputTrack::write() no more buffers");
2064 }
2065 }
2066 }
2067
2068 while (1) {
2069 // First write pending buffers, then new data
2070 if (mBufferQueue.size()) {
2071 pInBuffer = mBufferQueue.itemAt(0);
2072 } else {
2073 pInBuffer = &inBuffer;
2074 }
2075
2076 if (pInBuffer->frameCount == 0) {
2077 break;
2078 }
2079
2080 if (mOutBuffer.frameCount == 0) {
2081 mOutBuffer.frameCount = pInBuffer->frameCount;
2082 if (obtainBuffer(&mOutBuffer) == (status_t)AudioTrack::NO_MORE_BUFFERS) {
2083 break;
2084 }
2085 }
2086
2087 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount : pInBuffer->frameCount;
2088 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * channels * sizeof(int16_t));
2089 mCblk->stepUser(outFrames);
2090 pInBuffer->frameCount -= outFrames;
2091 pInBuffer->i16 += outFrames * channels;
2092 mOutBuffer.frameCount -= outFrames;
2093 mOutBuffer.i16 += outFrames * channels;
2094
2095 if (pInBuffer->frameCount == 0) {
2096 if (mBufferQueue.size()) {
2097 mBufferQueue.removeAt(0);
2098 delete [] pInBuffer->mBuffer;
2099 delete pInBuffer;
2100 } else {
2101 break;
2102 }
2103 }
2104 }
2105
2106 // If we could not write all frames, allocate a buffer and queue it for next time.
2107 if (inBuffer.frameCount) {
2108 if (mBufferQueue.size() < kMaxOutputTrackBuffers) {
2109 pInBuffer = new Buffer;
2110 pInBuffer->mBuffer = new int16_t[inBuffer.frameCount * channels];
2111 pInBuffer->frameCount = inBuffer.frameCount;
2112 pInBuffer->i16 = pInBuffer->mBuffer;
2113 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * channels * sizeof(int16_t));
2114 mBufferQueue.add(pInBuffer);
2115 } else {
2116 LOGW("OutputTrack::write() no more buffers");
2117 }
2118 }
2119
2120 // Calling write() with a 0 length buffer, means that no more data will be written:
2121 // If no more buffers are pending, fill output track buffer to make sure it is started
2122 // by output mixer.
2123 if (frames == 0 && mBufferQueue.size() == 0 && mCblk->user < mCblk->frameCount) {
2124 frames = mCblk->frameCount - mCblk->user;
2125 pInBuffer = new Buffer;
2126 pInBuffer->mBuffer = new int16_t[frames * channels];
2127 pInBuffer->frameCount = frames;
2128 pInBuffer->i16 = pInBuffer->mBuffer;
2129 memset(pInBuffer->raw, 0, frames * channels * sizeof(int16_t));
2130 mBufferQueue.add(pInBuffer);
2131 }
2132
2133}
2134
2135status_t AudioFlinger::MixerThread::OutputTrack::obtainBuffer(AudioBufferProvider::Buffer* buffer)
2136{
2137 int active;
2138 int timeout = 0;
2139 status_t result;
2140 audio_track_cblk_t* cblk = mCblk;
2141 uint32_t framesReq = buffer->frameCount;
2142
2143 LOGV("OutputTrack::obtainBuffer user %d, server %d", cblk->user, cblk->server);
2144 buffer->frameCount = 0;
2145
2146 uint32_t framesAvail = cblk->framesAvailable();
2147
2148 if (framesAvail == 0) {
2149 return AudioTrack::NO_MORE_BUFFERS;
2150 }
2151
2152 if (framesReq > framesAvail) {
2153 framesReq = framesAvail;
2154 }
2155
2156 uint32_t u = cblk->user;
2157 uint32_t bufferEnd = cblk->userBase + cblk->frameCount;
2158
2159 if (u + framesReq > bufferEnd) {
2160 framesReq = bufferEnd - u;
2161 }
2162
2163 buffer->frameCount = framesReq;
2164 buffer->raw = (void *)cblk->buffer(u);
2165 return NO_ERROR;
2166}
2167
2168
2169void AudioFlinger::MixerThread::OutputTrack::clearBufferQueue()
2170{
2171 size_t size = mBufferQueue.size();
2172 Buffer *pBuffer;
2173
2174 for (size_t i = 0; i < size; i++) {
2175 pBuffer = mBufferQueue.itemAt(i);
2176 delete [] pBuffer->mBuffer;
2177 delete pBuffer;
2178 }
2179 mBufferQueue.clear();
2180}
2181
2182// ----------------------------------------------------------------------------
2183
2184AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
2185 : RefBase(),
2186 mAudioFlinger(audioFlinger),
2187 mMemoryDealer(new MemoryDealer(1024*1024)),
2188 mPid(pid)
2189{
2190 // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
2191}
2192
2193AudioFlinger::Client::~Client()
2194{
2195 mAudioFlinger->removeClient(mPid);
2196}
2197
2198const sp<MemoryDealer>& AudioFlinger::Client::heap() const
2199{
2200 return mMemoryDealer;
2201}
2202
2203// ----------------------------------------------------------------------------
2204
2205AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::MixerThread::Track>& track)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002206 : BnAudioTrack(),
2207 mTrack(track)
2208{
2209}
2210
2211AudioFlinger::TrackHandle::~TrackHandle() {
2212 // just stop the track on deletion, associated resources
2213 // will be freed from the main thread once all pending buffers have
2214 // been played. Unless it's not in the active track list, in which
2215 // case we free everything now...
2216 mTrack->destroy();
2217}
2218
2219status_t AudioFlinger::TrackHandle::start() {
2220 return mTrack->start();
2221}
2222
2223void AudioFlinger::TrackHandle::stop() {
2224 mTrack->stop();
2225}
2226
2227void AudioFlinger::TrackHandle::flush() {
2228 mTrack->flush();
2229}
2230
2231void AudioFlinger::TrackHandle::mute(bool e) {
2232 mTrack->mute(e);
2233}
2234
2235void AudioFlinger::TrackHandle::pause() {
2236 mTrack->pause();
2237}
2238
2239void AudioFlinger::TrackHandle::setVolume(float left, float right) {
2240 mTrack->setVolume(left, right);
2241}
2242
2243sp<IMemory> AudioFlinger::TrackHandle::getCblk() const {
2244 return mTrack->getCblk();
2245}
2246
2247status_t AudioFlinger::TrackHandle::onTransact(
2248 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
2249{
2250 return BnAudioTrack::onTransact(code, data, reply, flags);
2251}
2252
2253// ----------------------------------------------------------------------------
2254
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002255sp<IAudioRecord> AudioFlinger::openRecord(
2256 pid_t pid,
2257 int streamType,
2258 uint32_t sampleRate,
2259 int format,
2260 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002261 int frameCount,
2262 uint32_t flags,
2263 status_t *status)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002264{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002265 sp<MixerThread::RecordTrack> recordTrack;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002266 sp<RecordHandle> recordHandle;
2267 sp<Client> client;
2268 wp<Client> wclient;
2269 AudioStreamIn* input = 0;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002270 int inFrameCount;
2271 size_t inputBufferSize;
2272 status_t lStatus;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002273
2274 // check calling permissions
2275 if (!recordingAllowed()) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002276 lStatus = PERMISSION_DENIED;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002277 goto Exit;
2278 }
2279
2280 if (uint32_t(streamType) >= AudioRecord::NUM_STREAM_TYPES) {
2281 LOGE("invalid stream type");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002282 lStatus = BAD_VALUE;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002283 goto Exit;
2284 }
2285
2286 if (sampleRate > MAX_SAMPLE_RATE) {
2287 LOGE("Sample rate out of range");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002288 lStatus = BAD_VALUE;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002289 goto Exit;
2290 }
2291
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002292 if (mAudioRecordThread == 0) {
2293 LOGE("Audio record thread not started");
2294 lStatus = NO_INIT;
2295 goto Exit;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002296 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002297
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002298
2299 // Check that audio input stream accepts requested audio parameters
2300 inputBufferSize = mAudioHardware->getInputBufferSize(sampleRate, format, channelCount);
2301 if (inputBufferSize == 0) {
2302 lStatus = BAD_VALUE;
2303 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 -07002304 goto Exit;
2305 }
2306
2307 // add client to list
The Android Open Source Project22f8def2009-03-09 11:52:12 -07002308 { // scope for mLock
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002309 Mutex::Autolock _l(mLock);
2310 wclient = mClients.valueFor(pid);
2311 if (wclient != NULL) {
2312 client = wclient.promote();
2313 } else {
2314 client = new Client(this, pid);
2315 mClients.add(pid, client);
2316 }
The Android Open Source Project22f8def2009-03-09 11:52:12 -07002317
2318 // frameCount must be a multiple of input buffer size
2319 inFrameCount = inputBufferSize/channelCount/sizeof(short);
2320 frameCount = ((frameCount - 1)/inFrameCount + 1) * inFrameCount;
2321
2322 // create new record track. The record track uses one track in mHardwareMixerThread by convention.
2323 recordTrack = new MixerThread::RecordTrack(mHardwareMixerThread, client, streamType, sampleRate,
2324 format, channelCount, frameCount, flags);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002325 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002326 if (recordTrack->getCblk() == NULL) {
2327 recordTrack.clear();
2328 lStatus = NO_MEMORY;
2329 goto Exit;
2330 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002331
2332 // return to handle to client
2333 recordHandle = new RecordHandle(recordTrack);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002334 lStatus = NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002335
2336Exit:
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002337 if (status) {
2338 *status = lStatus;
2339 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002340 return recordHandle;
2341}
2342
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002343status_t AudioFlinger::startRecord(MixerThread::RecordTrack* recordTrack) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002344 if (mAudioRecordThread != 0) {
2345 return mAudioRecordThread->start(recordTrack);
2346 }
2347 return NO_INIT;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002348}
2349
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002350void AudioFlinger::stopRecord(MixerThread::RecordTrack* recordTrack) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002351 if (mAudioRecordThread != 0) {
2352 mAudioRecordThread->stop(recordTrack);
2353 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002354}
2355
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002356// ----------------------------------------------------------------------------
2357
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002358AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::MixerThread::RecordTrack>& recordTrack)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002359 : BnAudioRecord(),
2360 mRecordTrack(recordTrack)
2361{
2362}
2363
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002364AudioFlinger::RecordHandle::~RecordHandle() {
2365 stop();
2366}
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002367
2368status_t AudioFlinger::RecordHandle::start() {
2369 LOGV("RecordHandle::start()");
2370 return mRecordTrack->start();
2371}
2372
2373void AudioFlinger::RecordHandle::stop() {
2374 LOGV("RecordHandle::stop()");
2375 mRecordTrack->stop();
2376}
2377
2378sp<IMemory> AudioFlinger::RecordHandle::getCblk() const {
2379 return mRecordTrack->getCblk();
2380}
2381
2382status_t AudioFlinger::RecordHandle::onTransact(
2383 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
2384{
2385 return BnAudioRecord::onTransact(code, data, reply, flags);
2386}
2387
2388// ----------------------------------------------------------------------------
2389
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -07002390AudioFlinger::AudioRecordThread::AudioRecordThread(AudioHardwareInterface* audioHardware,
2391 const sp<AudioFlinger>& audioFlinger) :
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002392 mAudioHardware(audioHardware),
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -07002393 mAudioFlinger(audioFlinger),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002394 mActive(false)
2395{
2396}
2397
2398AudioFlinger::AudioRecordThread::~AudioRecordThread()
2399{
2400}
2401
2402bool AudioFlinger::AudioRecordThread::threadLoop()
2403{
2404 LOGV("AudioRecordThread: start record loop");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002405 AudioBufferProvider::Buffer buffer;
2406 int inBufferSize = 0;
2407 int inFrameCount = 0;
2408 AudioStreamIn* input = 0;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002409
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002410 mActive = 0;
2411
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002412 // start recording
2413 while (!exitPending()) {
2414 if (!mActive) {
2415 mLock.lock();
2416 if (!mActive && !exitPending()) {
2417 LOGV("AudioRecordThread: loop stopping");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002418 if (input) {
2419 delete input;
2420 input = 0;
2421 }
2422 mRecordTrack.clear();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002423 mStopped.signal();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002424
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002425 mWaitWorkCV.wait(mLock);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002426
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002427 LOGV("AudioRecordThread: loop starting");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002428 if (mRecordTrack != 0) {
2429 input = mAudioHardware->openInputStream(mRecordTrack->format(),
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002430 mRecordTrack->channelCount(),
2431 mRecordTrack->sampleRate(),
2432 &mStartStatus,
2433 (AudioSystem::audio_in_acoustics)(mRecordTrack->mFlags >> 16));
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002434 if (input != 0) {
2435 inBufferSize = input->bufferSize();
2436 inFrameCount = inBufferSize/input->frameSize();
2437 }
2438 } else {
2439 mStartStatus = NO_INIT;
2440 }
2441 if (mStartStatus !=NO_ERROR) {
2442 LOGW("record start failed, status %d", mStartStatus);
2443 mActive = false;
2444 mRecordTrack.clear();
2445 }
2446 mWaitWorkCV.signal();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002447 }
2448 mLock.unlock();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002449 } else if (mRecordTrack != 0) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002450
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002451 buffer.frameCount = inFrameCount;
The Android Open Source Project22f8def2009-03-09 11:52:12 -07002452 if (LIKELY(mRecordTrack->getNextBuffer(&buffer) == NO_ERROR &&
2453 (int)buffer.frameCount == inFrameCount)) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002454 LOGV("AudioRecordThread read: %d frames", buffer.frameCount);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002455 ssize_t bytesRead = input->read(buffer.raw, inBufferSize);
2456 if (bytesRead < 0) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002457 LOGE("Error reading audio input");
2458 sleep(1);
2459 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002460 mRecordTrack->releaseBuffer(&buffer);
2461 mRecordTrack->overflow();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002462 }
2463
2464 // client isn't retrieving buffers fast enough
2465 else {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002466 if (!mRecordTrack->setOverflow())
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002467 LOGW("AudioRecordThread: buffer overflow");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002468 // Release the processor for a while before asking for a new buffer.
2469 // This will give the application more chance to read from the buffer and
2470 // clear the overflow.
2471 usleep(5000);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002472 }
2473 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002474 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002475
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002476
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002477 if (input) {
2478 delete input;
2479 }
2480 mRecordTrack.clear();
2481
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002482 return false;
2483}
2484
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002485status_t AudioFlinger::AudioRecordThread::start(MixerThread::RecordTrack* recordTrack)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002486{
2487 LOGV("AudioRecordThread::start");
2488 AutoMutex lock(&mLock);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002489 mActive = true;
2490 // If starting the active track, just reset mActive in case a stop
2491 // was pending and exit
2492 if (recordTrack == mRecordTrack.get()) return NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002493
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002494 if (mRecordTrack != 0) return -EBUSY;
2495
2496 mRecordTrack = recordTrack;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002497
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -07002498#ifdef WITH_A2DP
The Android Open Source Projectebad1472009-03-13 13:04:22 -07002499 { // scope for lock2
2500
2501 // AudioFlinger::mLock must be locked before calling
2502 // handleStreamDisablesA2dp_l because it calls setA2dpEnabled_l().
2503 AutoMutex lock2(&mAudioFlinger->mLock);
2504
2505 // Currently there is no way to detect if we are recording over SCO,
2506 // so we disable A2DP during any recording.
2507 mAudioFlinger->handleStreamDisablesA2dp_l(ACTIVE_TRACK_ADDED);
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -07002508 }
2509#endif
2510
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002511 // signal thread to start
2512 LOGV("Signal record thread");
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002513 mWaitWorkCV.signal();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002514 mWaitWorkCV.wait(mLock);
2515 LOGV("Record started, status %d", mStartStatus);
2516 return mStartStatus;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002517}
2518
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002519void AudioFlinger::AudioRecordThread::stop(MixerThread::RecordTrack* recordTrack) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002520 LOGV("AudioRecordThread::stop");
2521 AutoMutex lock(&mLock);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002522 if (mActive && (recordTrack == mRecordTrack.get())) {
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -07002523#ifdef WITH_A2DP
The Android Open Source Projectebad1472009-03-13 13:04:22 -07002524 { // scope for lock2
2525
2526 // AudioFlinger::mLock must be locked before calling
2527 // handleStreamDisablesA2dp_l because it calls setA2dpEnabled_l().
2528 AutoMutex lock2(&mAudioFlinger->mLock);
2529
2530 // Currently there is no way to detect if we are recording over SCO,
2531 // so we disable A2DP during any recording.
2532 mAudioFlinger->handleStreamDisablesA2dp_l(ACTIVE_TRACK_REMOVED);
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -07002533 }
2534#endif
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002535 mActive = false;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002536 mStopped.wait(mLock);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002537 }
2538}
2539
2540void AudioFlinger::AudioRecordThread::exit()
2541{
2542 LOGV("AudioRecordThread::exit");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002543 {
2544 AutoMutex lock(&mLock);
2545 requestExit();
2546 mWaitWorkCV.signal();
2547 }
2548 requestExitAndWait();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002549}
2550
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002551status_t AudioFlinger::AudioRecordThread::dump(int fd, const Vector<String16>& args)
2552{
2553 const size_t SIZE = 256;
2554 char buffer[SIZE];
2555 String8 result;
2556 pid_t pid = 0;
2557
2558 if (mRecordTrack != 0 && mRecordTrack->mClient != 0) {
2559 snprintf(buffer, SIZE, "Record client pid: %d\n", mRecordTrack->mClient->pid());
2560 result.append(buffer);
2561 } else {
2562 result.append("No record client\n");
2563 }
2564 write(fd, result.string(), result.size());
2565 return NO_ERROR;
2566}
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002567
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002568status_t AudioFlinger::onTransact(
2569 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
2570{
2571 return BnAudioFlinger::onTransact(code, data, reply, flags);
2572}
2573
2574// ----------------------------------------------------------------------------
2575void AudioFlinger::instantiate() {
2576 defaultServiceManager()->addService(
2577 String16("media.audio_flinger"), new AudioFlinger());
2578}
2579
2580}; // namespace android