blob: 790221285517c4309deec70785287dc52249d333 [file] [log] [blame]
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001/* //device/include/server/AudioFlinger/AudioFlinger.cpp
2**
3** Copyright 2007, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18
19#define LOG_TAG "AudioFlinger"
20//#define LOG_NDEBUG 0
21
22#include <math.h>
23#include <signal.h>
24#include <sys/time.h>
25#include <sys/resource.h>
26
Mathias Agopian07952722009-05-19 19:08:10 -070027#include <binder/IServiceManager.h>
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070028#include <utils/Log.h>
Mathias Agopian07952722009-05-19 19:08:10 -070029#include <binder/Parcel.h>
30#include <binder/IPCThreadState.h>
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070031#include <utils/String16.h>
32#include <utils/threads.h>
33
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -080034#include <cutils/properties.h>
35
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070036#include <media/AudioTrack.h>
37#include <media/AudioRecord.h>
38
39#include <private/media/AudioTrackShared.h>
40
The Android Open Source Project9266c552009-01-15 16:12:10 -080041#include <hardware_legacy/AudioHardwareInterface.h>
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070042
43#include "AudioMixer.h"
44#include "AudioFlinger.h"
45
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -080046#ifdef WITH_A2DP
47#include "A2dpAudioInterface.h"
48#endif
49
Glenn Kasten871c16c2010-03-05 12:18:01 -080050#ifdef LVMX
51#include "lifevibes.h"
52#endif
53
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054// ----------------------------------------------------------------------------
55// the sim build doesn't have gettid
56
57#ifndef HAVE_GETTID
58# define gettid getpid
59#endif
60
61// ----------------------------------------------------------------------------
62
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070063namespace android {
64
The Android Open Source Project10592532009-03-18 17:39:46 -070065static const char* kDeadlockedString = "AudioFlinger may be deadlocked\n";
66static const char* kHardwareLockedString = "Hardware lock is taken\n";
67
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -080068//static const nsecs_t kStandbyTimeInNsecs = seconds(3);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070069static const float MAX_GAIN = 4096.0f;
70
71// retry counts for buffer fill timeout
72// 50 * ~20msecs = 1 second
73static const int8_t kMaxTrackRetries = 50;
74static const int8_t kMaxTrackStartupRetries = 50;
75
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070076static const int kDumpLockRetries = 50;
77static const int kDumpLockSleep = 20000;
78
Dave Sparksd0ac8c02009-09-30 03:09:03 -070079static const nsecs_t kWarningThrottle = seconds(5);
80
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070082#define AUDIOFLINGER_SECURITY_ENABLED 1
83
84// ----------------------------------------------------------------------------
85
86static bool recordingAllowed() {
87#ifndef HAVE_ANDROID_OS
88 return true;
89#endif
90#if AUDIOFLINGER_SECURITY_ENABLED
91 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
92 bool ok = checkCallingPermission(String16("android.permission.RECORD_AUDIO"));
93 if (!ok) LOGE("Request requires android.permission.RECORD_AUDIO");
94 return ok;
95#else
96 if (!checkCallingPermission(String16("android.permission.RECORD_AUDIO")))
97 LOGW("WARNING: Need to add android.permission.RECORD_AUDIO to manifest");
98 return true;
99#endif
100}
101
102static bool settingsAllowed() {
103#ifndef HAVE_ANDROID_OS
104 return true;
105#endif
106#if AUDIOFLINGER_SECURITY_ENABLED
107 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
108 bool ok = checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS"));
109 if (!ok) LOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS");
110 return ok;
111#else
112 if (!checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS")))
113 LOGW("WARNING: Need to add android.permission.MODIFY_AUDIO_SETTINGS to manifest");
114 return true;
115#endif
116}
117
118// ----------------------------------------------------------------------------
119
120AudioFlinger::AudioFlinger()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800121 : BnAudioFlinger(),
Eric Laurentddb78e72009-07-28 08:44:33 -0700122 mAudioHardware(0), mMasterVolume(1.0f), mMasterMute(false), mNextThreadId(0)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700123{
124 mHardwareStatus = AUDIO_HW_IDLE;
Eric Laurenta553c252009-07-17 12:17:14 -0700125
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700126 mAudioHardware = AudioHardwareInterface::create();
Eric Laurenta553c252009-07-17 12:17:14 -0700127
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700128 mHardwareStatus = AUDIO_HW_INIT;
129 if (mAudioHardware->initCheck() == NO_ERROR) {
130 // open 16-bit output stream for s/w mixer
Eric Laurenta553c252009-07-17 12:17:14 -0700131
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800132 setMode(AudioSystem::MODE_NORMAL);
133
134 setMasterVolume(1.0f);
135 setMasterMute(false);
Eric Laurenta553c252009-07-17 12:17:14 -0700136 } else {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700137 LOGE("Couldn't even initialize the stubbed audio hardware!");
138 }
Glenn Kasten871c16c2010-03-05 12:18:01 -0800139#ifdef LVMX
140 LifeVibes::init();
141#endif
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700142}
143
144AudioFlinger::~AudioFlinger()
145{
Eric Laurent7954c462009-08-28 10:39:03 -0700146 while (!mRecordThreads.isEmpty()) {
147 // closeInput() will remove first entry from mRecordThreads
148 closeInput(mRecordThreads.keyAt(0));
149 }
150 while (!mPlaybackThreads.isEmpty()) {
151 // closeOutput() will remove first entry from mPlaybackThreads
152 closeOutput(mPlaybackThreads.keyAt(0));
153 }
154 if (mAudioHardware) {
155 delete mAudioHardware;
156 }
The Android Open Source Projectb7986892009-01-09 17:51:23 -0800157}
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800158
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700159
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -0700160
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700161status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args)
162{
163 const size_t SIZE = 256;
164 char buffer[SIZE];
165 String8 result;
166
167 result.append("Clients:\n");
168 for (size_t i = 0; i < mClients.size(); ++i) {
169 wp<Client> wClient = mClients.valueAt(i);
170 if (wClient != 0) {
171 sp<Client> client = wClient.promote();
172 if (client != 0) {
173 snprintf(buffer, SIZE, " pid: %d\n", client->pid());
174 result.append(buffer);
175 }
176 }
177 }
178 write(fd, result.string(), result.size());
179 return NO_ERROR;
180}
181
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700182
183status_t AudioFlinger::dumpInternals(int fd, const Vector<String16>& args)
184{
185 const size_t SIZE = 256;
186 char buffer[SIZE];
187 String8 result;
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700188 int hardwareStatus = mHardwareStatus;
Eric Laurenta553c252009-07-17 12:17:14 -0700189
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700190 snprintf(buffer, SIZE, "Hardware status: %d\n", hardwareStatus);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700191 result.append(buffer);
192 write(fd, result.string(), result.size());
193 return NO_ERROR;
194}
195
196status_t AudioFlinger::dumpPermissionDenial(int fd, const Vector<String16>& args)
197{
198 const size_t SIZE = 256;
199 char buffer[SIZE];
200 String8 result;
201 snprintf(buffer, SIZE, "Permission Denial: "
202 "can't dump AudioFlinger from pid=%d, uid=%d\n",
203 IPCThreadState::self()->getCallingPid(),
204 IPCThreadState::self()->getCallingUid());
205 result.append(buffer);
206 write(fd, result.string(), result.size());
207 return NO_ERROR;
208}
209
The Android Open Source Project10592532009-03-18 17:39:46 -0700210static bool tryLock(Mutex& mutex)
211{
212 bool locked = false;
213 for (int i = 0; i < kDumpLockRetries; ++i) {
214 if (mutex.tryLock() == NO_ERROR) {
215 locked = true;
216 break;
217 }
218 usleep(kDumpLockSleep);
219 }
220 return locked;
221}
222
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700223status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
224{
225 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
226 dumpPermissionDenial(fd, args);
227 } else {
The Android Open Source Project10592532009-03-18 17:39:46 -0700228 // get state of hardware lock
229 bool hardwareLocked = tryLock(mHardwareLock);
230 if (!hardwareLocked) {
231 String8 result(kHardwareLockedString);
232 write(fd, result.string(), result.size());
233 } else {
234 mHardwareLock.unlock();
235 }
236
237 bool locked = tryLock(mLock);
238
239 // failed to lock - AudioFlinger is probably deadlocked
240 if (!locked) {
241 String8 result(kDeadlockedString);
242 write(fd, result.string(), result.size());
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700243 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700244
245 dumpClients(fd, args);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700246 dumpInternals(fd, args);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800247
Eric Laurenta553c252009-07-17 12:17:14 -0700248 // dump playback threads
249 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurentddb78e72009-07-28 08:44:33 -0700250 mPlaybackThreads.valueAt(i)->dump(fd, args);
Eric Laurenta553c252009-07-17 12:17:14 -0700251 }
252
253 // dump record threads
Eric Laurent102313a2009-07-23 13:35:01 -0700254 for (size_t i = 0; i < mRecordThreads.size(); i++) {
Eric Laurentddb78e72009-07-28 08:44:33 -0700255 mRecordThreads.valueAt(i)->dump(fd, args);
Eric Laurenta553c252009-07-17 12:17:14 -0700256 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800257
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700258 if (mAudioHardware) {
259 mAudioHardware->dumpState(fd, args);
260 }
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700261 if (locked) mLock.unlock();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700262 }
263 return NO_ERROR;
264}
265
Eric Laurenta553c252009-07-17 12:17:14 -0700266
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700267// IAudioFlinger interface
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800268
269
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700270sp<IAudioTrack> AudioFlinger::createTrack(
271 pid_t pid,
272 int streamType,
273 uint32_t sampleRate,
274 int format,
275 int channelCount,
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800276 int frameCount,
277 uint32_t flags,
278 const sp<IMemory>& sharedBuffer,
Eric Laurentddb78e72009-07-28 08:44:33 -0700279 int output,
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800280 status_t *status)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700281{
Eric Laurenta553c252009-07-17 12:17:14 -0700282 sp<PlaybackThread::Track> track;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700283 sp<TrackHandle> trackHandle;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700284 sp<Client> client;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800285 wp<Client> wclient;
286 status_t lStatus;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700287
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288 if (streamType >= AudioSystem::NUM_STREAM_TYPES) {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800289 LOGE("invalid stream type");
290 lStatus = BAD_VALUE;
291 goto Exit;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700292 }
293
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800294 {
295 Mutex::Autolock _l(mLock);
Eric Laurenta553c252009-07-17 12:17:14 -0700296 PlaybackThread *thread = checkPlaybackThread_l(output);
297 if (thread == NULL) {
298 LOGE("unknown output thread");
299 lStatus = BAD_VALUE;
300 goto Exit;
301 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800302
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800303 wclient = mClients.valueFor(pid);
304
305 if (wclient != NULL) {
306 client = wclient.promote();
307 } else {
308 client = new Client(this, pid);
309 mClients.add(pid, client);
310 }
Eric Laurenta553c252009-07-17 12:17:14 -0700311 track = thread->createTrack_l(client, streamType, sampleRate, format,
312 channelCount, frameCount, sharedBuffer, &lStatus);
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700313 }
314 if (lStatus == NO_ERROR) {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800315 trackHandle = new TrackHandle(track);
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700316 } else {
Eric Laurentb9481d82009-09-17 05:12:56 -0700317 // remove local strong reference to Client before deleting the Track so that the Client
318 // destructor is called by the TrackBase destructor with mLock held
319 client.clear();
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700320 track.clear();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800321 }
322
323Exit:
324 if(status) {
325 *status = lStatus;
326 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700327 return trackHandle;
328}
329
Eric Laurentddb78e72009-07-28 08:44:33 -0700330uint32_t AudioFlinger::sampleRate(int output) const
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700331{
Eric Laurenta553c252009-07-17 12:17:14 -0700332 Mutex::Autolock _l(mLock);
333 PlaybackThread *thread = checkPlaybackThread_l(output);
334 if (thread == NULL) {
Eric Laurentddb78e72009-07-28 08:44:33 -0700335 LOGW("sampleRate() unknown thread %d", output);
Eric Laurenta553c252009-07-17 12:17:14 -0700336 return 0;
337 }
338 return thread->sampleRate();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700339}
340
Eric Laurentddb78e72009-07-28 08:44:33 -0700341int AudioFlinger::channelCount(int output) const
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700342{
Eric Laurenta553c252009-07-17 12:17:14 -0700343 Mutex::Autolock _l(mLock);
344 PlaybackThread *thread = checkPlaybackThread_l(output);
345 if (thread == NULL) {
Eric Laurentddb78e72009-07-28 08:44:33 -0700346 LOGW("channelCount() unknown thread %d", output);
Eric Laurenta553c252009-07-17 12:17:14 -0700347 return 0;
348 }
349 return thread->channelCount();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700350}
351
Eric Laurentddb78e72009-07-28 08:44:33 -0700352int AudioFlinger::format(int output) const
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700353{
Eric Laurenta553c252009-07-17 12:17:14 -0700354 Mutex::Autolock _l(mLock);
355 PlaybackThread *thread = checkPlaybackThread_l(output);
356 if (thread == NULL) {
Eric Laurentddb78e72009-07-28 08:44:33 -0700357 LOGW("format() unknown thread %d", output);
Eric Laurenta553c252009-07-17 12:17:14 -0700358 return 0;
359 }
360 return thread->format();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700361}
362
Eric Laurentddb78e72009-07-28 08:44:33 -0700363size_t AudioFlinger::frameCount(int output) const
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700364{
Eric Laurenta553c252009-07-17 12:17:14 -0700365 Mutex::Autolock _l(mLock);
366 PlaybackThread *thread = checkPlaybackThread_l(output);
367 if (thread == NULL) {
Eric Laurentddb78e72009-07-28 08:44:33 -0700368 LOGW("frameCount() unknown thread %d", output);
Eric Laurenta553c252009-07-17 12:17:14 -0700369 return 0;
370 }
371 return thread->frameCount();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700372}
373
Eric Laurentddb78e72009-07-28 08:44:33 -0700374uint32_t AudioFlinger::latency(int output) const
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800375{
Eric Laurenta553c252009-07-17 12:17:14 -0700376 Mutex::Autolock _l(mLock);
377 PlaybackThread *thread = checkPlaybackThread_l(output);
378 if (thread == NULL) {
Eric Laurentddb78e72009-07-28 08:44:33 -0700379 LOGW("latency() unknown thread %d", output);
Eric Laurenta553c252009-07-17 12:17:14 -0700380 return 0;
381 }
382 return thread->latency();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800383}
384
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700385status_t AudioFlinger::setMasterVolume(float value)
386{
387 // check calling permissions
388 if (!settingsAllowed()) {
389 return PERMISSION_DENIED;
390 }
391
392 // when hw supports master volume, don't scale in sw mixer
393 AutoMutex lock(mHardwareLock);
394 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
395 if (mAudioHardware->setMasterVolume(value) == NO_ERROR) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800396 value = 1.0f;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700397 }
398 mHardwareStatus = AUDIO_HW_IDLE;
Eric Laurenta553c252009-07-17 12:17:14 -0700399
400 mMasterVolume = value;
401 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
Eric Laurentddb78e72009-07-28 08:44:33 -0700402 mPlaybackThreads.valueAt(i)->setMasterVolume(value);
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700403
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700404 return NO_ERROR;
405}
406
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700407status_t AudioFlinger::setMode(int mode)
408{
409 // check calling permissions
410 if (!settingsAllowed()) {
411 return PERMISSION_DENIED;
412 }
413 if ((mode < 0) || (mode >= AudioSystem::NUM_MODES)) {
414 LOGW("Illegal value: setMode(%d)", mode);
415 return BAD_VALUE;
416 }
417
418 AutoMutex lock(mHardwareLock);
419 mHardwareStatus = AUDIO_HW_SET_MODE;
420 status_t ret = mAudioHardware->setMode(mode);
Glenn Kasten871c16c2010-03-05 12:18:01 -0800421#ifdef LVMX
422 if (NO_ERROR == ret) {
423 LifeVibes::setMode(mode);
424 }
425#endif
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700426 mHardwareStatus = AUDIO_HW_IDLE;
427 return ret;
428}
429
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700430status_t AudioFlinger::setMicMute(bool state)
431{
432 // check calling permissions
433 if (!settingsAllowed()) {
434 return PERMISSION_DENIED;
435 }
436
437 AutoMutex lock(mHardwareLock);
438 mHardwareStatus = AUDIO_HW_SET_MIC_MUTE;
439 status_t ret = mAudioHardware->setMicMute(state);
440 mHardwareStatus = AUDIO_HW_IDLE;
441 return ret;
442}
443
444bool AudioFlinger::getMicMute() const
445{
446 bool state = AudioSystem::MODE_INVALID;
447 mHardwareStatus = AUDIO_HW_GET_MIC_MUTE;
448 mAudioHardware->getMicMute(&state);
449 mHardwareStatus = AUDIO_HW_IDLE;
450 return state;
451}
452
453status_t AudioFlinger::setMasterMute(bool muted)
454{
455 // check calling permissions
456 if (!settingsAllowed()) {
457 return PERMISSION_DENIED;
458 }
Eric Laurenta553c252009-07-17 12:17:14 -0700459
460 mMasterMute = muted;
461 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
Eric Laurentddb78e72009-07-28 08:44:33 -0700462 mPlaybackThreads.valueAt(i)->setMasterMute(muted);
Eric Laurenta553c252009-07-17 12:17:14 -0700463
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700464 return NO_ERROR;
465}
466
467float AudioFlinger::masterVolume() const
468{
Eric Laurenta553c252009-07-17 12:17:14 -0700469 return mMasterVolume;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700470}
471
472bool AudioFlinger::masterMute() const
473{
Eric Laurenta553c252009-07-17 12:17:14 -0700474 return mMasterMute;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700475}
476
Eric Laurentddb78e72009-07-28 08:44:33 -0700477status_t AudioFlinger::setStreamVolume(int stream, float value, int output)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700478{
479 // check calling permissions
480 if (!settingsAllowed()) {
481 return PERMISSION_DENIED;
482 }
483
Eric Laurenta553c252009-07-17 12:17:14 -0700484 if (stream < 0 || uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700485 return BAD_VALUE;
486 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800487
Eric Laurenta553c252009-07-17 12:17:14 -0700488 AutoMutex lock(mLock);
489 PlaybackThread *thread = NULL;
490 if (output) {
491 thread = checkPlaybackThread_l(output);
492 if (thread == NULL) {
493 return BAD_VALUE;
494 }
495 }
496
Eric Laurenta553c252009-07-17 12:17:14 -0700497 mStreamTypes[stream].volume = value;
498
499 if (thread == NULL) {
Eric Laurent415f3e22009-10-21 08:14:22 -0700500 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurentddb78e72009-07-28 08:44:33 -0700501 mPlaybackThreads.valueAt(i)->setStreamVolume(stream, value);
Eric Laurent415f3e22009-10-21 08:14:22 -0700502 }
Eric Laurenta553c252009-07-17 12:17:14 -0700503 } else {
504 thread->setStreamVolume(stream, value);
505 }
Eric Laurentef028272009-04-21 07:56:33 -0700506
Eric Laurent415f3e22009-10-21 08:14:22 -0700507 return NO_ERROR;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700508}
509
510status_t AudioFlinger::setStreamMute(int stream, bool muted)
511{
512 // check calling permissions
513 if (!settingsAllowed()) {
514 return PERMISSION_DENIED;
515 }
516
Eric Laurenta553c252009-07-17 12:17:14 -0700517 if (stream < 0 || uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES ||
Eric Laurenteeea9222009-03-26 01:57:59 -0700518 uint32_t(stream) == AudioSystem::ENFORCED_AUDIBLE) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700519 return BAD_VALUE;
520 }
The Android Open Source Project10592532009-03-18 17:39:46 -0700521
Eric Laurenta553c252009-07-17 12:17:14 -0700522 mStreamTypes[stream].mute = muted;
523 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
Eric Laurentddb78e72009-07-28 08:44:33 -0700524 mPlaybackThreads.valueAt(i)->setStreamMute(stream, muted);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800525
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700526 return NO_ERROR;
527}
528
Eric Laurentddb78e72009-07-28 08:44:33 -0700529float AudioFlinger::streamVolume(int stream, int output) const
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700530{
Eric Laurenta553c252009-07-17 12:17:14 -0700531 if (stream < 0 || uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700532 return 0.0f;
533 }
Eric Laurenta553c252009-07-17 12:17:14 -0700534
535 AutoMutex lock(mLock);
536 float volume;
537 if (output) {
538 PlaybackThread *thread = checkPlaybackThread_l(output);
539 if (thread == NULL) {
540 return 0.0f;
541 }
542 volume = thread->streamVolume(stream);
543 } else {
544 volume = mStreamTypes[stream].volume;
545 }
546
Eric Laurentef028272009-04-21 07:56:33 -0700547 return volume;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700548}
549
550bool AudioFlinger::streamMute(int stream) const
551{
Eric Laurenta553c252009-07-17 12:17:14 -0700552 if (stream < 0 || stream >= (int)AudioSystem::NUM_STREAM_TYPES) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700553 return true;
554 }
Eric Laurenta553c252009-07-17 12:17:14 -0700555
556 return mStreamTypes[stream].mute;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700557}
558
Eric Laurent23f25cd2010-01-25 08:49:09 -0800559bool AudioFlinger::isStreamActive(int stream) const
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700560{
Eric Laurent4e646332009-07-09 03:20:57 -0700561 Mutex::Autolock _l(mLock);
Eric Laurenta553c252009-07-17 12:17:14 -0700562 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurent23f25cd2010-01-25 08:49:09 -0800563 if (mPlaybackThreads.valueAt(i)->isStreamActive(stream)) {
Eric Laurenta553c252009-07-17 12:17:14 -0700564 return true;
565 }
566 }
567 return false;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700568}
569
Eric Laurentddb78e72009-07-28 08:44:33 -0700570status_t AudioFlinger::setParameters(int ioHandle, const String8& keyValuePairs)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700571{
Eric Laurenta553c252009-07-17 12:17:14 -0700572 status_t result;
573
Eric Laurentddb78e72009-07-28 08:44:33 -0700574 LOGV("setParameters(): io %d, keyvalue %s, tid %d, calling tid %d",
Eric Laurenta553c252009-07-17 12:17:14 -0700575 ioHandle, keyValuePairs.string(), gettid(), IPCThreadState::self()->getCallingPid());
576 // check calling permissions
577 if (!settingsAllowed()) {
578 return PERMISSION_DENIED;
The Android Open Source Project9266c552009-01-15 16:12:10 -0800579 }
Eric Laurenta553c252009-07-17 12:17:14 -0700580
Glenn Kasten871c16c2010-03-05 12:18:01 -0800581#ifdef LVMX
582 AudioParameter param = AudioParameter(keyValuePairs);
583 LifeVibes::setParameters(ioHandle,keyValuePairs);
584 String8 key = String8(AudioParameter::keyRouting);
585 int device;
586 if (NO_ERROR != param.getInt(key, device)) {
587 device = -1;
588 }
589
590 key = String8(LifevibesTag);
591 String8 value;
592 int musicEnabled = -1;
593 if (NO_ERROR == param.get(key, value)) {
594 if (value == LifevibesEnable) {
595 musicEnabled = 1;
596 } else if (value == LifevibesDisable) {
597 musicEnabled = 0;
598 }
599 }
600#endif
601
Eric Laurenta553c252009-07-17 12:17:14 -0700602 // ioHandle == 0 means the parameters are global to the audio hardware interface
603 if (ioHandle == 0) {
604 AutoMutex lock(mHardwareLock);
605 mHardwareStatus = AUDIO_SET_PARAMETER;
606 result = mAudioHardware->setParameters(keyValuePairs);
Glenn Kasten871c16c2010-03-05 12:18:01 -0800607#ifdef LVMX
608 if ((NO_ERROR == result) && (musicEnabled != -1)) {
609 LifeVibes::enableMusic((bool) musicEnabled);
610 }
611#endif
Eric Laurenta553c252009-07-17 12:17:14 -0700612 mHardwareStatus = AUDIO_HW_IDLE;
613 return result;
614 }
615
Eric Laurentb7d94602009-09-29 11:12:57 -0700616 // hold a strong ref on thread in case closeOutput() or closeInput() is called
617 // and the thread is exited once the lock is released
618 sp<ThreadBase> thread;
619 {
620 Mutex::Autolock _l(mLock);
621 thread = checkPlaybackThread_l(ioHandle);
622 if (thread == NULL) {
623 thread = checkRecordThread_l(ioHandle);
624 }
Eric Laurenta553c252009-07-17 12:17:14 -0700625 }
Eric Laurentb7d94602009-09-29 11:12:57 -0700626 if (thread != NULL) {
Glenn Kasten871c16c2010-03-05 12:18:01 -0800627 result = thread->setParameters(keyValuePairs);
628#ifdef LVMX
629 if ((NO_ERROR == result) && (device != -1)) {
630 LifeVibes::setDevice(LifeVibes::threadIdToAudioOutputType(thread->id()), device);
631 }
632#endif
633 return result;
Eric Laurenta553c252009-07-17 12:17:14 -0700634 }
Eric Laurenta553c252009-07-17 12:17:14 -0700635 return BAD_VALUE;
636}
637
Eric Laurentddb78e72009-07-28 08:44:33 -0700638String8 AudioFlinger::getParameters(int ioHandle, const String8& keys)
Eric Laurenta553c252009-07-17 12:17:14 -0700639{
Eric Laurentddb78e72009-07-28 08:44:33 -0700640// LOGV("getParameters() io %d, keys %s, tid %d, calling tid %d",
Eric Laurenta553c252009-07-17 12:17:14 -0700641// ioHandle, keys.string(), gettid(), IPCThreadState::self()->getCallingPid());
642
643 if (ioHandle == 0) {
644 return mAudioHardware->getParameters(keys);
645 }
Eric Laurentb7d94602009-09-29 11:12:57 -0700646
647 Mutex::Autolock _l(mLock);
648
Eric Laurenta553c252009-07-17 12:17:14 -0700649 PlaybackThread *playbackThread = checkPlaybackThread_l(ioHandle);
650 if (playbackThread != NULL) {
651 return playbackThread->getParameters(keys);
652 }
653 RecordThread *recordThread = checkRecordThread_l(ioHandle);
654 if (recordThread != NULL) {
655 return recordThread->getParameters(keys);
656 }
657 return String8("");
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700658}
659
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800660size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
661{
662 return mAudioHardware->getInputBufferSize(sampleRate, format, channelCount);
663}
664
Eric Laurent47d0a922010-02-26 02:47:27 -0800665unsigned int AudioFlinger::getInputFramesLost(int ioHandle)
666{
667 if (ioHandle == 0) {
668 return 0;
669 }
670
671 Mutex::Autolock _l(mLock);
672
673 RecordThread *recordThread = checkRecordThread_l(ioHandle);
674 if (recordThread != NULL) {
675 return recordThread->getInputFramesLost();
676 }
677 return 0;
678}
679
Eric Laurent415f3e22009-10-21 08:14:22 -0700680status_t AudioFlinger::setVoiceVolume(float value)
681{
682 // check calling permissions
683 if (!settingsAllowed()) {
684 return PERMISSION_DENIED;
685 }
686
687 AutoMutex lock(mHardwareLock);
688 mHardwareStatus = AUDIO_SET_VOICE_VOLUME;
689 status_t ret = mAudioHardware->setVoiceVolume(value);
690 mHardwareStatus = AUDIO_HW_IDLE;
691
692 return ret;
693}
694
Eric Laurent0986e792010-01-19 17:37:09 -0800695status_t AudioFlinger::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int output)
696{
697 status_t status;
698
699 Mutex::Autolock _l(mLock);
700
701 PlaybackThread *playbackThread = checkPlaybackThread_l(output);
702 if (playbackThread != NULL) {
703 return playbackThread->getRenderPosition(halFrames, dspFrames);
704 }
705
706 return BAD_VALUE;
707}
708
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800709void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
710{
Eric Laurenta553c252009-07-17 12:17:14 -0700711
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800712 LOGV("registerClient() %p, tid %d, calling tid %d", client.get(), gettid(), IPCThreadState::self()->getCallingPid());
713 Mutex::Autolock _l(mLock);
714
715 sp<IBinder> binder = client->asBinder();
716 if (mNotificationClients.indexOf(binder) < 0) {
717 LOGV("Adding notification client %p", binder.get());
718 binder->linkToDeath(this);
719 mNotificationClients.add(binder);
Eric Laurenta553c252009-07-17 12:17:14 -0700720 }
721
722 // the config change is always sent from playback or record threads to avoid deadlock
723 // with AudioSystem::gLock
724 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurentddb78e72009-07-28 08:44:33 -0700725 mPlaybackThreads.valueAt(i)->sendConfigEvent(AudioSystem::OUTPUT_OPENED);
Eric Laurenta553c252009-07-17 12:17:14 -0700726 }
727
728 for (size_t i = 0; i < mRecordThreads.size(); i++) {
Eric Laurentddb78e72009-07-28 08:44:33 -0700729 mRecordThreads.valueAt(i)->sendConfigEvent(AudioSystem::INPUT_OPENED);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800730 }
731}
732
733void AudioFlinger::binderDied(const wp<IBinder>& who) {
Eric Laurenta553c252009-07-17 12:17:14 -0700734
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800735 LOGV("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(), IPCThreadState::self()->getCallingPid());
736 Mutex::Autolock _l(mLock);
737
738 IBinder *binder = who.unsafe_get();
739
740 if (binder != NULL) {
741 int index = mNotificationClients.indexOf(binder);
742 if (index >= 0) {
743 LOGV("Removing notification client %p", binder);
744 mNotificationClients.removeAt(index);
745 }
746 }
747}
748
Eric Laurent296a0ec2009-09-15 07:10:12 -0700749// audioConfigChanged_l() must be called with AudioFlinger::mLock held
Eric Laurent49f02be2009-11-19 09:00:56 -0800750void AudioFlinger::audioConfigChanged_l(int event, int ioHandle, void *param2) {
751 size_t size = mNotificationClients.size();
752 for (size_t i = 0; i < size; i++) {
753 sp<IBinder> binder = mNotificationClients.itemAt(i);
754 LOGV("audioConfigChanged_l() Notifying change to client %p", binder.get());
755 sp<IAudioFlingerClient> client = interface_cast<IAudioFlingerClient> (binder);
756 client->ioConfigChanged(event, ioHandle, param2);
Eric Laurenta553c252009-07-17 12:17:14 -0700757 }
758}
759
Eric Laurentb9481d82009-09-17 05:12:56 -0700760// removeClient_l() must be called with AudioFlinger::mLock held
761void AudioFlinger::removeClient_l(pid_t pid)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700762{
Eric Laurentb9481d82009-09-17 05:12:56 -0700763 LOGV("removeClient_l() pid %d, tid %d, calling tid %d", pid, gettid(), IPCThreadState::self()->getCallingPid());
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700764 mClients.removeItem(pid);
765}
766
Eric Laurenta553c252009-07-17 12:17:14 -0700767// ----------------------------------------------------------------------------
768
Eric Laurent49f02be2009-11-19 09:00:56 -0800769AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, int id)
Eric Laurenta553c252009-07-17 12:17:14 -0700770 : Thread(false),
771 mAudioFlinger(audioFlinger), mSampleRate(0), mFrameCount(0), mChannelCount(0),
Eric Laurent49f02be2009-11-19 09:00:56 -0800772 mFormat(0), mFrameSize(1), mStandby(false), mId(id), mExiting(false)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700773{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800774}
775
Eric Laurenta553c252009-07-17 12:17:14 -0700776AudioFlinger::ThreadBase::~ThreadBase()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800777{
Eric Laurent8fce46a2009-08-04 09:45:33 -0700778 mParamCond.broadcast();
779 mNewParameters.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800780}
781
Eric Laurenta553c252009-07-17 12:17:14 -0700782void AudioFlinger::ThreadBase::exit()
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -0700783{
Eric Laurentb7d94602009-09-29 11:12:57 -0700784 // keep a strong ref on ourself so that we wont get
Eric Laurenta553c252009-07-17 12:17:14 -0700785 // destroyed in the middle of requestExitAndWait()
786 sp <ThreadBase> strongMe = this;
787
788 LOGV("ThreadBase::exit");
789 {
790 AutoMutex lock(&mLock);
Eric Laurent49f02be2009-11-19 09:00:56 -0800791 mExiting = true;
Eric Laurenta553c252009-07-17 12:17:14 -0700792 requestExit();
793 mWaitWorkCV.signal();
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -0700794 }
Eric Laurenta553c252009-07-17 12:17:14 -0700795 requestExitAndWait();
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -0700796}
Eric Laurenta553c252009-07-17 12:17:14 -0700797
798uint32_t AudioFlinger::ThreadBase::sampleRate() const
799{
800 return mSampleRate;
801}
802
803int AudioFlinger::ThreadBase::channelCount() const
804{
805 return mChannelCount;
806}
807
808int AudioFlinger::ThreadBase::format() const
809{
810 return mFormat;
811}
812
813size_t AudioFlinger::ThreadBase::frameCount() const
814{
815 return mFrameCount;
816}
817
818status_t AudioFlinger::ThreadBase::setParameters(const String8& keyValuePairs)
819{
Eric Laurent8fce46a2009-08-04 09:45:33 -0700820 status_t status;
Eric Laurenta553c252009-07-17 12:17:14 -0700821
Eric Laurent8fce46a2009-08-04 09:45:33 -0700822 LOGV("ThreadBase::setParameters() %s", keyValuePairs.string());
Eric Laurenta553c252009-07-17 12:17:14 -0700823 Mutex::Autolock _l(mLock);
Eric Laurenta553c252009-07-17 12:17:14 -0700824
Eric Laurent8fce46a2009-08-04 09:45:33 -0700825 mNewParameters.add(keyValuePairs);
Eric Laurenta553c252009-07-17 12:17:14 -0700826 mWaitWorkCV.signal();
Eric Laurentb7d94602009-09-29 11:12:57 -0700827 // wait condition with timeout in case the thread loop has exited
828 // before the request could be processed
829 if (mParamCond.waitRelative(mLock, seconds(2)) == NO_ERROR) {
830 status = mParamStatus;
831 mWaitWorkCV.signal();
832 } else {
833 status = TIMED_OUT;
834 }
Eric Laurent8fce46a2009-08-04 09:45:33 -0700835 return status;
Eric Laurenta553c252009-07-17 12:17:14 -0700836}
837
838void AudioFlinger::ThreadBase::sendConfigEvent(int event, int param)
839{
840 Mutex::Autolock _l(mLock);
Eric Laurent8fce46a2009-08-04 09:45:33 -0700841 sendConfigEvent_l(event, param);
842}
843
844// sendConfigEvent_l() must be called with ThreadBase::mLock held
845void AudioFlinger::ThreadBase::sendConfigEvent_l(int event, int param)
846{
Eric Laurenta553c252009-07-17 12:17:14 -0700847 ConfigEvent *configEvent = new ConfigEvent();
848 configEvent->mEvent = event;
849 configEvent->mParam = param;
850 mConfigEvents.add(configEvent);
851 LOGV("sendConfigEvent() num events %d event %d, param %d", mConfigEvents.size(), event, param);
852 mWaitWorkCV.signal();
853}
854
855void AudioFlinger::ThreadBase::processConfigEvents()
856{
857 mLock.lock();
858 while(!mConfigEvents.isEmpty()) {
859 LOGV("processConfigEvents() remaining events %d", mConfigEvents.size());
860 ConfigEvent *configEvent = mConfigEvents[0];
861 mConfigEvents.removeAt(0);
Eric Laurent296a0ec2009-09-15 07:10:12 -0700862 // release mLock because audioConfigChanged() will lock AudioFlinger mLock
863 // before calling Audioflinger::audioConfigChanged_l() thus creating
Eric Laurenta553c252009-07-17 12:17:14 -0700864 // potential cross deadlock between AudioFlinger::mLock and mLock
865 mLock.unlock();
866 audioConfigChanged(configEvent->mEvent, configEvent->mParam);
867 delete configEvent;
868 mLock.lock();
869 }
870 mLock.unlock();
871}
872
Eric Laurent3fdb1262009-11-07 00:01:32 -0800873status_t AudioFlinger::ThreadBase::dumpBase(int fd, const Vector<String16>& args)
874{
875 const size_t SIZE = 256;
876 char buffer[SIZE];
877 String8 result;
878
879 bool locked = tryLock(mLock);
880 if (!locked) {
881 snprintf(buffer, SIZE, "thread %p maybe dead locked\n", this);
882 write(fd, buffer, strlen(buffer));
883 }
884
885 snprintf(buffer, SIZE, "standby: %d\n", mStandby);
886 result.append(buffer);
887 snprintf(buffer, SIZE, "Sample rate: %d\n", mSampleRate);
888 result.append(buffer);
889 snprintf(buffer, SIZE, "Frame count: %d\n", mFrameCount);
890 result.append(buffer);
891 snprintf(buffer, SIZE, "Channel Count: %d\n", mChannelCount);
892 result.append(buffer);
893 snprintf(buffer, SIZE, "Format: %d\n", mFormat);
894 result.append(buffer);
895 snprintf(buffer, SIZE, "Frame size: %d\n", mFrameSize);
896 result.append(buffer);
897
898 snprintf(buffer, SIZE, "\nPending setParameters commands: \n");
899 result.append(buffer);
900 result.append(" Index Command");
901 for (size_t i = 0; i < mNewParameters.size(); ++i) {
902 snprintf(buffer, SIZE, "\n %02d ", i);
903 result.append(buffer);
904 result.append(mNewParameters[i]);
905 }
906
907 snprintf(buffer, SIZE, "\n\nPending config events: \n");
908 result.append(buffer);
909 snprintf(buffer, SIZE, " Index event param\n");
910 result.append(buffer);
911 for (size_t i = 0; i < mConfigEvents.size(); i++) {
912 snprintf(buffer, SIZE, " %02d %02d %d\n", i, mConfigEvents[i]->mEvent, mConfigEvents[i]->mParam);
913 result.append(buffer);
914 }
915 result.append("\n");
916
917 write(fd, result.string(), result.size());
918
919 if (locked) {
920 mLock.unlock();
921 }
922 return NO_ERROR;
923}
924
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800925
926// ----------------------------------------------------------------------------
927
Eric Laurent49f02be2009-11-19 09:00:56 -0800928AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id)
929 : ThreadBase(audioFlinger, id),
Eric Laurentd5603c12009-08-06 08:49:39 -0700930 mMixBuffer(0), mSuspended(0), mBytesWritten(0), mOutput(output),
Eric Laurent2c817f52009-07-23 13:17:39 -0700931 mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800932{
Eric Laurenta553c252009-07-17 12:17:14 -0700933 readOutputParameters();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800934
Eric Laurenta553c252009-07-17 12:17:14 -0700935 mMasterVolume = mAudioFlinger->masterVolume();
936 mMasterMute = mAudioFlinger->masterMute();
937
938 for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
939 mStreamTypes[stream].volume = mAudioFlinger->streamVolumeInternal(stream);
940 mStreamTypes[stream].mute = mAudioFlinger->streamMute(stream);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800941 }
Eric Laurenta553c252009-07-17 12:17:14 -0700942 // notify client processes that a new input has been opened
943 sendConfigEvent(AudioSystem::OUTPUT_OPENED);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800944}
945
Eric Laurenta553c252009-07-17 12:17:14 -0700946AudioFlinger::PlaybackThread::~PlaybackThread()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800947{
948 delete [] mMixBuffer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800949}
950
Eric Laurenta553c252009-07-17 12:17:14 -0700951status_t AudioFlinger::PlaybackThread::dump(int fd, const Vector<String16>& args)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800952{
953 dumpInternals(fd, args);
954 dumpTracks(fd, args);
955 return NO_ERROR;
956}
957
Eric Laurenta553c252009-07-17 12:17:14 -0700958status_t AudioFlinger::PlaybackThread::dumpTracks(int fd, const Vector<String16>& args)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800959{
960 const size_t SIZE = 256;
961 char buffer[SIZE];
962 String8 result;
963
Eric Laurenta553c252009-07-17 12:17:14 -0700964 snprintf(buffer, SIZE, "Output thread %p tracks\n", this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800965 result.append(buffer);
Eric Laurent3fdb1262009-11-07 00:01:32 -0800966 result.append(" Name Clien Typ Fmt Chn Buf S M F SRate LeftV RighV Serv User\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800967 for (size_t i = 0; i < mTracks.size(); ++i) {
Eric Laurentd3b4d0c2009-03-31 14:34:35 -0700968 sp<Track> track = mTracks[i];
969 if (track != 0) {
970 track->dump(buffer, SIZE);
971 result.append(buffer);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800972 }
973 }
974
Eric Laurenta553c252009-07-17 12:17:14 -0700975 snprintf(buffer, SIZE, "Output thread %p active tracks\n", this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800976 result.append(buffer);
Eric Laurent3fdb1262009-11-07 00:01:32 -0800977 result.append(" Name Clien Typ Fmt Chn Buf S M F SRate LeftV RighV Serv User\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800978 for (size_t i = 0; i < mActiveTracks.size(); ++i) {
Eric Laurentd3b4d0c2009-03-31 14:34:35 -0700979 wp<Track> wTrack = mActiveTracks[i];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800980 if (wTrack != 0) {
981 sp<Track> track = wTrack.promote();
982 if (track != 0) {
983 track->dump(buffer, SIZE);
984 result.append(buffer);
985 }
986 }
987 }
988 write(fd, result.string(), result.size());
989 return NO_ERROR;
990}
991
Eric Laurenta553c252009-07-17 12:17:14 -0700992status_t AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String16>& args)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800993{
994 const size_t SIZE = 256;
995 char buffer[SIZE];
996 String8 result;
997
Eric Laurent3fdb1262009-11-07 00:01:32 -0800998 snprintf(buffer, SIZE, "\nOutput thread %p internals\n", this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800999 result.append(buffer);
1000 snprintf(buffer, SIZE, "last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime));
1001 result.append(buffer);
1002 snprintf(buffer, SIZE, "total writes: %d\n", mNumWrites);
1003 result.append(buffer);
1004 snprintf(buffer, SIZE, "delayed writes: %d\n", mNumDelayedWrites);
1005 result.append(buffer);
1006 snprintf(buffer, SIZE, "blocked in write: %d\n", mInWrite);
1007 result.append(buffer);
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08001008 snprintf(buffer, SIZE, "suspend count: %d\n", mSuspended);
1009 result.append(buffer);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001010 write(fd, result.string(), result.size());
Eric Laurent3fdb1262009-11-07 00:01:32 -08001011
1012 dumpBase(fd, args);
1013
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001014 return NO_ERROR;
1015}
1016
1017// Thread virtuals
Eric Laurenta553c252009-07-17 12:17:14 -07001018status_t AudioFlinger::PlaybackThread::readyToRun()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001019{
1020 if (mSampleRate == 0) {
1021 LOGE("No working audio driver found.");
1022 return NO_INIT;
1023 }
Eric Laurenta553c252009-07-17 12:17:14 -07001024 LOGI("AudioFlinger's thread %p ready to run", this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001025 return NO_ERROR;
1026}
1027
Eric Laurenta553c252009-07-17 12:17:14 -07001028void AudioFlinger::PlaybackThread::onFirstRef()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001029{
1030 const size_t SIZE = 256;
1031 char buffer[SIZE];
1032
Eric Laurenta553c252009-07-17 12:17:14 -07001033 snprintf(buffer, SIZE, "Playback Thread %p", this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001034
1035 run(buffer, ANDROID_PRIORITY_URGENT_AUDIO);
1036}
1037
Eric Laurenta553c252009-07-17 12:17:14 -07001038// PlaybackThread::createTrack_l() must be called with AudioFlinger::mLock held
1039sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrack_l(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001040 const sp<AudioFlinger::Client>& client,
1041 int streamType,
1042 uint32_t sampleRate,
1043 int format,
1044 int channelCount,
1045 int frameCount,
1046 const sp<IMemory>& sharedBuffer,
1047 status_t *status)
1048{
1049 sp<Track> track;
1050 status_t lStatus;
Eric Laurenta553c252009-07-17 12:17:14 -07001051
1052 if (mType == DIRECT) {
1053 if (sampleRate != mSampleRate || format != mFormat || channelCount != mChannelCount) {
1054 LOGE("createTrack_l() Bad parameter: sampleRate %d format %d, channelCount %d for output %p",
1055 sampleRate, format, channelCount, mOutput);
1056 lStatus = BAD_VALUE;
1057 goto Exit;
1058 }
1059 } else {
1060 // Resampler implementation limits input sampling rate to 2 x output sampling rate.
1061 if (sampleRate > mSampleRate*2) {
1062 LOGE("Sample rate out of range: %d mSampleRate %d", sampleRate, mSampleRate);
1063 lStatus = BAD_VALUE;
1064 goto Exit;
1065 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001066 }
1067
Eric Laurenta553c252009-07-17 12:17:14 -07001068 if (mOutput == 0) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001069 LOGE("Audio driver not initialized.");
1070 lStatus = NO_INIT;
1071 goto Exit;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001072 }
1073
Eric Laurenta553c252009-07-17 12:17:14 -07001074 { // scope for mLock
1075 Mutex::Autolock _l(mLock);
1076 track = new Track(this, client, streamType, sampleRate, format,
1077 channelCount, frameCount, sharedBuffer);
Eric Laurent73b60352009-11-09 04:45:39 -08001078 if (track->getCblk() == NULL || track->name() < 0) {
Eric Laurenta553c252009-07-17 12:17:14 -07001079 lStatus = NO_MEMORY;
1080 goto Exit;
1081 }
1082 mTracks.add(track);
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001083 }
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001084 lStatus = NO_ERROR;
1085
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001086Exit:
1087 if(status) {
1088 *status = lStatus;
1089 }
1090 return track;
1091}
1092
Eric Laurenta553c252009-07-17 12:17:14 -07001093uint32_t AudioFlinger::PlaybackThread::latency() const
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001094{
1095 if (mOutput) {
1096 return mOutput->latency();
1097 }
1098 else {
1099 return 0;
1100 }
1101}
1102
Eric Laurenta553c252009-07-17 12:17:14 -07001103status_t AudioFlinger::PlaybackThread::setMasterVolume(float value)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001104{
Glenn Kasten871c16c2010-03-05 12:18:01 -08001105#ifdef LVMX
1106 int audioOutputType = LifeVibes::getMixerType(mId, mType);
1107 if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) {
1108 LifeVibes::setMasterVolume(audioOutputType, value);
1109 }
1110#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001111 mMasterVolume = value;
1112 return NO_ERROR;
1113}
1114
Eric Laurenta553c252009-07-17 12:17:14 -07001115status_t AudioFlinger::PlaybackThread::setMasterMute(bool muted)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001116{
Glenn Kasten871c16c2010-03-05 12:18:01 -08001117#ifdef LVMX
1118 int audioOutputType = LifeVibes::getMixerType(mId, mType);
1119 if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) {
1120 LifeVibes::setMasterMute(audioOutputType, muted);
1121 }
1122#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001123 mMasterMute = muted;
1124 return NO_ERROR;
1125}
1126
Eric Laurenta553c252009-07-17 12:17:14 -07001127float AudioFlinger::PlaybackThread::masterVolume() const
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001128{
1129 return mMasterVolume;
1130}
1131
Eric Laurenta553c252009-07-17 12:17:14 -07001132bool AudioFlinger::PlaybackThread::masterMute() const
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001133{
1134 return mMasterMute;
1135}
1136
Eric Laurenta553c252009-07-17 12:17:14 -07001137status_t AudioFlinger::PlaybackThread::setStreamVolume(int stream, float value)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001138{
Glenn Kasten871c16c2010-03-05 12:18:01 -08001139#ifdef LVMX
1140 int audioOutputType = LifeVibes::getMixerType(mId, mType);
1141 if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) {
1142 LifeVibes::setStreamVolume(audioOutputType, stream, value);
1143 }
1144#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001145 mStreamTypes[stream].volume = value;
1146 return NO_ERROR;
1147}
1148
Eric Laurenta553c252009-07-17 12:17:14 -07001149status_t AudioFlinger::PlaybackThread::setStreamMute(int stream, bool muted)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001150{
Glenn Kasten871c16c2010-03-05 12:18:01 -08001151#ifdef LVMX
1152 int audioOutputType = LifeVibes::getMixerType(mId, mType);
1153 if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) {
1154 LifeVibes::setStreamMute(audioOutputType, stream, muted);
1155 }
1156#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001157 mStreamTypes[stream].mute = muted;
1158 return NO_ERROR;
1159}
1160
Eric Laurenta553c252009-07-17 12:17:14 -07001161float AudioFlinger::PlaybackThread::streamVolume(int stream) const
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001162{
1163 return mStreamTypes[stream].volume;
1164}
1165
Eric Laurenta553c252009-07-17 12:17:14 -07001166bool AudioFlinger::PlaybackThread::streamMute(int stream) const
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001167{
1168 return mStreamTypes[stream].mute;
1169}
1170
Eric Laurent23f25cd2010-01-25 08:49:09 -08001171bool AudioFlinger::PlaybackThread::isStreamActive(int stream) const
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001172{
Eric Laurenta553c252009-07-17 12:17:14 -07001173 Mutex::Autolock _l(mLock);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001174 size_t count = mActiveTracks.size();
1175 for (size_t i = 0 ; i < count ; ++i) {
1176 sp<Track> t = mActiveTracks[i].promote();
1177 if (t == 0) continue;
1178 Track* const track = t.get();
Eric Laurent23f25cd2010-01-25 08:49:09 -08001179 if (t->type() == stream)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001180 return true;
1181 }
1182 return false;
1183}
1184
Eric Laurenta553c252009-07-17 12:17:14 -07001185// addTrack_l() must be called with ThreadBase::mLock held
1186status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001187{
1188 status_t status = ALREADY_EXISTS;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001189
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001190 // set retry count for buffer fill
1191 track->mRetryCount = kMaxTrackStartupRetries;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001192 if (mActiveTracks.indexOf(track) < 0) {
1193 // the track is newly added, make sure it fills up all its
1194 // buffers before playing. This is to ensure the client will
1195 // effectively get the latency it requested.
1196 track->mFillingUpStatus = Track::FS_FILLING;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001197 track->mResetDone = false;
Eric Laurenta553c252009-07-17 12:17:14 -07001198 mActiveTracks.add(track);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001199 status = NO_ERROR;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001200 }
Eric Laurenta553c252009-07-17 12:17:14 -07001201
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001202 LOGV("mWaitWorkCV.broadcast");
Eric Laurenta553c252009-07-17 12:17:14 -07001203 mWaitWorkCV.broadcast();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001204
1205 return status;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001206}
1207
Eric Laurenta553c252009-07-17 12:17:14 -07001208// destroyTrack_l() must be called with ThreadBase::mLock held
1209void AudioFlinger::PlaybackThread::destroyTrack_l(const sp<Track>& track)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001210{
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001211 track->mState = TrackBase::TERMINATED;
1212 if (mActiveTracks.indexOf(track) < 0) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001213 mTracks.remove(track);
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001214 deleteTrackName_l(track->name());
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001215 }
1216}
1217
Eric Laurenta553c252009-07-17 12:17:14 -07001218String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys)
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -08001219{
Eric Laurenta553c252009-07-17 12:17:14 -07001220 return mOutput->getParameters(keys);
1221}
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -08001222
Eric Laurenta553c252009-07-17 12:17:14 -07001223void AudioFlinger::PlaybackThread::audioConfigChanged(int event, int param) {
1224 AudioSystem::OutputDescriptor desc;
1225 void *param2 = 0;
1226
1227 LOGV("PlaybackThread::audioConfigChanged, thread %p, event %d, param %d", this, event, param);
1228
1229 switch (event) {
1230 case AudioSystem::OUTPUT_OPENED:
1231 case AudioSystem::OUTPUT_CONFIG_CHANGED:
1232 desc.channels = mChannelCount;
1233 desc.samplingRate = mSampleRate;
1234 desc.format = mFormat;
1235 desc.frameCount = mFrameCount;
1236 desc.latency = latency();
1237 param2 = &desc;
1238 break;
1239
1240 case AudioSystem::STREAM_CONFIG_CHANGED:
1241 param2 = &param;
1242 case AudioSystem::OUTPUT_CLOSED:
1243 default:
1244 break;
1245 }
Eric Laurent296a0ec2009-09-15 07:10:12 -07001246 Mutex::Autolock _l(mAudioFlinger->mLock);
Eric Laurent49f02be2009-11-19 09:00:56 -08001247 mAudioFlinger->audioConfigChanged_l(event, mId, param2);
Eric Laurenta553c252009-07-17 12:17:14 -07001248}
1249
1250void AudioFlinger::PlaybackThread::readOutputParameters()
1251{
1252 mSampleRate = mOutput->sampleRate();
1253 mChannelCount = AudioSystem::popCount(mOutput->channels());
1254
1255 mFormat = mOutput->format();
1256 mFrameSize = mOutput->frameSize();
1257 mFrameCount = mOutput->bufferSize() / mFrameSize;
1258
Eric Laurenta553c252009-07-17 12:17:14 -07001259 // FIXME - Current mixer implementation only supports stereo output: Always
1260 // Allocate a stereo buffer even if HW output is mono.
1261 if (mMixBuffer != NULL) delete mMixBuffer;
1262 mMixBuffer = new int16_t[mFrameCount * 2];
1263 memset(mMixBuffer, 0, mFrameCount * 2 * sizeof(int16_t));
1264}
1265
Eric Laurent0986e792010-01-19 17:37:09 -08001266status_t AudioFlinger::PlaybackThread::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames)
1267{
1268 if (halFrames == 0 || dspFrames == 0) {
1269 return BAD_VALUE;
1270 }
1271 if (mOutput == 0) {
1272 return INVALID_OPERATION;
1273 }
1274 *halFrames = mBytesWritten/mOutput->frameSize();
1275
1276 return mOutput->getRenderPosition(dspFrames);
1277}
1278
Eric Laurenta553c252009-07-17 12:17:14 -07001279// ----------------------------------------------------------------------------
1280
Eric Laurent49f02be2009-11-19 09:00:56 -08001281AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id)
1282 : PlaybackThread(audioFlinger, output, id),
Eric Laurenta553c252009-07-17 12:17:14 -07001283 mAudioMixer(0)
1284{
1285 mType = PlaybackThread::MIXER;
1286 mAudioMixer = new AudioMixer(mFrameCount, mSampleRate);
1287
1288 // FIXME - Current mixer implementation only supports stereo output
1289 if (mChannelCount == 1) {
1290 LOGE("Invalid audio hardware channel count");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001291 }
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -08001292}
1293
Eric Laurenta553c252009-07-17 12:17:14 -07001294AudioFlinger::MixerThread::~MixerThread()
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -08001295{
Eric Laurenta553c252009-07-17 12:17:14 -07001296 delete mAudioMixer;
1297}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001298
Eric Laurenta553c252009-07-17 12:17:14 -07001299bool AudioFlinger::MixerThread::threadLoop()
1300{
Eric Laurenta553c252009-07-17 12:17:14 -07001301 int16_t* curBuf = mMixBuffer;
1302 Vector< sp<Track> > tracksToRemove;
Eric Laurent059b4be2009-11-09 23:32:22 -08001303 uint32_t mixerStatus = MIXER_IDLE;
Eric Laurenta553c252009-07-17 12:17:14 -07001304 nsecs_t standbyTime = systemTime();
1305 size_t mixBufferSize = mFrameCount * mFrameSize;
Dave Sparksd0ac8c02009-09-30 03:09:03 -07001306 // FIXME: Relaxed timing because of a certain device that can't meet latency
1307 // Should be reduced to 2x after the vendor fixes the driver issue
1308 nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 3;
1309 nsecs_t lastWarning = 0;
Eric Laurent059b4be2009-11-09 23:32:22 -08001310 bool longStandbyExit = false;
1311 uint32_t activeSleepTime = activeSleepTimeUs();
1312 uint32_t idleSleepTime = idleSleepTimeUs();
1313 uint32_t sleepTime = idleSleepTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001314
Eric Laurenta553c252009-07-17 12:17:14 -07001315 while (!exitPending())
1316 {
1317 processConfigEvents();
1318
Eric Laurent059b4be2009-11-09 23:32:22 -08001319 mixerStatus = MIXER_IDLE;
Eric Laurenta553c252009-07-17 12:17:14 -07001320 { // scope for mLock
1321
1322 Mutex::Autolock _l(mLock);
1323
1324 if (checkForNewParameters_l()) {
1325 mixBufferSize = mFrameCount * mFrameSize;
Dave Sparksd0ac8c02009-09-30 03:09:03 -07001326 // FIXME: Relaxed timing because of a certain device that can't meet latency
1327 // Should be reduced to 2x after the vendor fixes the driver issue
1328 maxPeriod = seconds(mFrameCount) / mSampleRate * 3;
Eric Laurent059b4be2009-11-09 23:32:22 -08001329 activeSleepTime = activeSleepTimeUs();
1330 idleSleepTime = idleSleepTimeUs();
Eric Laurenta553c252009-07-17 12:17:14 -07001331 }
1332
1333 const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
1334
1335 // put audio hardware into standby after short delay
1336 if UNLIKELY((!activeTracks.size() && systemTime() > standbyTime) ||
1337 mSuspended) {
1338 if (!mStandby) {
1339 LOGV("Audio hardware entering standby, mixer %p, mSuspended %d\n", this, mSuspended);
1340 mOutput->standby();
1341 mStandby = true;
1342 mBytesWritten = 0;
1343 }
1344
1345 if (!activeTracks.size() && mConfigEvents.isEmpty()) {
1346 // we're about to wait, flush the binder command buffer
1347 IPCThreadState::self()->flushCommands();
1348
1349 if (exitPending()) break;
1350
1351 // wait until we have something to do...
1352 LOGV("MixerThread %p TID %d going to sleep\n", this, gettid());
1353 mWaitWorkCV.wait(mLock);
1354 LOGV("MixerThread %p TID %d waking up\n", this, gettid());
1355
1356 if (mMasterMute == false) {
1357 char value[PROPERTY_VALUE_MAX];
1358 property_get("ro.audio.silent", value, "0");
1359 if (atoi(value)) {
1360 LOGD("Silence is golden");
1361 setMasterMute(true);
1362 }
1363 }
1364
1365 standbyTime = systemTime() + kStandbyTimeInNsecs;
Eric Laurent059b4be2009-11-09 23:32:22 -08001366 sleepTime = idleSleepTime;
Eric Laurenta553c252009-07-17 12:17:14 -07001367 continue;
1368 }
1369 }
1370
Eric Laurent059b4be2009-11-09 23:32:22 -08001371 mixerStatus = prepareTracks_l(activeTracks, &tracksToRemove);
Eric Laurenta553c252009-07-17 12:17:14 -07001372 }
1373
Eric Laurent059b4be2009-11-09 23:32:22 -08001374 if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
Eric Laurentf69a3f82009-09-22 00:35:48 -07001375 // mix buffers...
1376 mAudioMixer->process(curBuf);
1377 sleepTime = 0;
1378 standbyTime = systemTime() + kStandbyTimeInNsecs;
Eric Laurent96c08a62009-09-07 08:38:38 -07001379 } else {
Eric Laurent62443f52009-10-05 20:29:18 -07001380 // If no tracks are ready, sleep once for the duration of an output
1381 // buffer size, then write 0s to the output
1382 if (sleepTime == 0) {
Eric Laurent059b4be2009-11-09 23:32:22 -08001383 if (mixerStatus == MIXER_TRACKS_ENABLED) {
1384 sleepTime = activeSleepTime;
1385 } else {
1386 sleepTime = idleSleepTime;
1387 }
1388 } else if (mBytesWritten != 0 ||
1389 (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)) {
Eric Laurentf69a3f82009-09-22 00:35:48 -07001390 memset (curBuf, 0, mixBufferSize);
Eric Laurent96c08a62009-09-07 08:38:38 -07001391 sleepTime = 0;
Eric Laurent059b4be2009-11-09 23:32:22 -08001392 LOGV_IF((mBytesWritten == 0 && (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)), "anticipated start");
Eric Laurent96c08a62009-09-07 08:38:38 -07001393 }
Eric Laurentf69a3f82009-09-22 00:35:48 -07001394 }
1395
1396 if (mSuspended) {
Eric Laurent059b4be2009-11-09 23:32:22 -08001397 sleepTime = idleSleepTime;
Eric Laurentf69a3f82009-09-22 00:35:48 -07001398 }
1399 // sleepTime == 0 means we must write to audio hardware
1400 if (sleepTime == 0) {
1401 mLastWriteTime = systemTime();
1402 mInWrite = true;
Eric Laurent0986e792010-01-19 17:37:09 -08001403 mBytesWritten += mixBufferSize;
Glenn Kasten871c16c2010-03-05 12:18:01 -08001404#ifdef LVMX
1405 int audioOutputType = LifeVibes::getMixerType(mId, mType);
1406 if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) {
1407 LifeVibes::process(audioOutputType, curBuf, mixBufferSize);
1408 }
1409#endif
Eric Laurentf69a3f82009-09-22 00:35:48 -07001410 int bytesWritten = (int)mOutput->write(curBuf, mixBufferSize);
Eric Laurent0986e792010-01-19 17:37:09 -08001411 if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
Eric Laurentf69a3f82009-09-22 00:35:48 -07001412 mNumWrites++;
1413 mInWrite = false;
Dave Sparksd0ac8c02009-09-30 03:09:03 -07001414 nsecs_t now = systemTime();
1415 nsecs_t delta = now - mLastWriteTime;
Eric Laurentf69a3f82009-09-22 00:35:48 -07001416 if (delta > maxPeriod) {
Eric Laurentf69a3f82009-09-22 00:35:48 -07001417 mNumDelayedWrites++;
Dave Sparksd0ac8c02009-09-30 03:09:03 -07001418 if ((now - lastWarning) > kWarningThrottle) {
1419 LOGW("write blocked for %llu msecs, %d delayed writes, thread %p",
1420 ns2ms(delta), mNumDelayedWrites, this);
1421 lastWarning = now;
1422 }
Eric Laurent059b4be2009-11-09 23:32:22 -08001423 if (mStandby) {
1424 longStandbyExit = true;
1425 }
Eric Laurenta553c252009-07-17 12:17:14 -07001426 }
Eric Laurent059b4be2009-11-09 23:32:22 -08001427 mStandby = false;
Eric Laurentf69a3f82009-09-22 00:35:48 -07001428 } else {
1429 usleep(sleepTime);
Eric Laurenta553c252009-07-17 12:17:14 -07001430 }
1431
1432 // finally let go of all our tracks, without the lock held
1433 // since we can't guarantee the destructors won't acquire that
1434 // same lock.
1435 tracksToRemove.clear();
1436 }
1437
1438 if (!mStandby) {
1439 mOutput->standby();
1440 }
Eric Laurenta553c252009-07-17 12:17:14 -07001441
1442 LOGV("MixerThread %p exiting", this);
1443 return false;
1444}
1445
1446// prepareTracks_l() must be called with ThreadBase::mLock held
Eric Laurent059b4be2009-11-09 23:32:22 -08001447uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove)
Eric Laurenta553c252009-07-17 12:17:14 -07001448{
1449
Eric Laurent059b4be2009-11-09 23:32:22 -08001450 uint32_t mixerStatus = MIXER_IDLE;
Eric Laurenta553c252009-07-17 12:17:14 -07001451 // find out which tracks need to be processed
1452 size_t count = activeTracks.size();
Glenn Kasten871c16c2010-03-05 12:18:01 -08001453
1454 float masterVolume = mMasterVolume;
1455 bool masterMute = mMasterMute;
1456
1457#ifdef LVMX
1458 bool tracksConnectedChanged = false;
1459 bool stateChanged = false;
1460
1461 int audioOutputType = LifeVibes::getMixerType(mId, mType);
1462 if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType))
1463 {
1464 int activeTypes = 0;
1465 for (size_t i=0 ; i<count ; i++) {
1466 sp<Track> t = activeTracks[i].promote();
1467 if (t == 0) continue;
1468 Track* const track = t.get();
1469 int iTracktype=track->type();
1470 activeTypes |= 1<<track->type();
1471 }
1472 LifeVibes::computeVolumes(audioOutputType, activeTypes, tracksConnectedChanged, stateChanged, masterVolume, masterMute);
1473 }
1474#endif
1475
Eric Laurenta553c252009-07-17 12:17:14 -07001476 for (size_t i=0 ; i<count ; i++) {
1477 sp<Track> t = activeTracks[i].promote();
1478 if (t == 0) continue;
1479
1480 Track* const track = t.get();
1481 audio_track_cblk_t* cblk = track->cblk();
1482
1483 // The first time a track is added we wait
1484 // for all its buffers to be filled before processing it
1485 mAudioMixer->setActiveTrack(track->name());
1486 if (cblk->framesReady() && (track->isReady() || track->isStopped()) &&
1487 !track->isPaused())
1488 {
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08001489 //LOGV("track %d u=%08x, s=%08x [OK] on thread %p", track->name(), cblk->user, cblk->server, this);
Eric Laurenta553c252009-07-17 12:17:14 -07001490
1491 // compute volume for this track
1492 int16_t left, right;
Glenn Kasten871c16c2010-03-05 12:18:01 -08001493 if (track->isMuted() || masterMute || track->isPausing() ||
Eric Laurenta553c252009-07-17 12:17:14 -07001494 mStreamTypes[track->type()].mute) {
1495 left = right = 0;
1496 if (track->isPausing()) {
1497 track->setPaused();
1498 }
1499 } else {
Glenn Kasten871c16c2010-03-05 12:18:01 -08001500 // read original volumes with volume control
Eric Laurenta553c252009-07-17 12:17:14 -07001501 float typeVolume = mStreamTypes[track->type()].volume;
Glenn Kasten871c16c2010-03-05 12:18:01 -08001502#ifdef LVMX
1503 bool streamMute=false;
1504 // read the volume from the LivesVibes audio engine.
1505 if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType))
1506 {
1507 LifeVibes::getStreamVolumes(audioOutputType, track->type(), &typeVolume, &streamMute);
1508 if (streamMute) {
1509 typeVolume = 0;
1510 }
1511 }
1512#endif
1513 float v = masterVolume * typeVolume;
Eric Laurenta553c252009-07-17 12:17:14 -07001514 float v_clamped = v * cblk->volume[0];
1515 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
1516 left = int16_t(v_clamped);
1517 v_clamped = v * cblk->volume[1];
1518 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
1519 right = int16_t(v_clamped);
1520 }
1521
1522 // XXX: these things DON'T need to be done each time
1523 mAudioMixer->setBufferProvider(track);
1524 mAudioMixer->enable(AudioMixer::MIXING);
1525
Eric Laurenta160c6e2009-09-03 03:45:52 -07001526 int param = AudioMixer::VOLUME;
1527 if (track->mFillingUpStatus == Track::FS_FILLED) {
Eric Laurenta553c252009-07-17 12:17:14 -07001528 // no ramp for the first volume setting
1529 track->mFillingUpStatus = Track::FS_ACTIVE;
1530 if (track->mState == TrackBase::RESUMING) {
1531 track->mState = TrackBase::ACTIVE;
1532 param = AudioMixer::RAMP_VOLUME;
Eric Laurenta553c252009-07-17 12:17:14 -07001533 }
Eric Laurenta160c6e2009-09-03 03:45:52 -07001534 } else if (cblk->server != 0) {
1535 // If the track is stopped before the first frame was mixed,
1536 // do not apply ramp
Eric Laurenta553c252009-07-17 12:17:14 -07001537 param = AudioMixer::RAMP_VOLUME;
1538 }
Glenn Kasten871c16c2010-03-05 12:18:01 -08001539#ifdef LVMX
1540 if ( tracksConnectedChanged || stateChanged )
1541 {
1542 // only do the ramp when the volume is changed by the user / application
1543 param = AudioMixer::VOLUME;
1544 }
1545#endif
Eric Laurenta553c252009-07-17 12:17:14 -07001546 mAudioMixer->setParameter(param, AudioMixer::VOLUME0, left);
1547 mAudioMixer->setParameter(param, AudioMixer::VOLUME1, right);
1548 mAudioMixer->setParameter(
1549 AudioMixer::TRACK,
1550 AudioMixer::FORMAT, track->format());
1551 mAudioMixer->setParameter(
1552 AudioMixer::TRACK,
1553 AudioMixer::CHANNEL_COUNT, track->channelCount());
1554 mAudioMixer->setParameter(
1555 AudioMixer::RESAMPLE,
1556 AudioMixer::SAMPLE_RATE,
1557 int(cblk->sampleRate));
1558
1559 // reset retry count
1560 track->mRetryCount = kMaxTrackRetries;
Eric Laurent059b4be2009-11-09 23:32:22 -08001561 mixerStatus = MIXER_TRACKS_READY;
Eric Laurenta553c252009-07-17 12:17:14 -07001562 } else {
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08001563 //LOGV("track %d u=%08x, s=%08x [NOT READY] on thread %p", track->name(), cblk->user, cblk->server, this);
Eric Laurenta553c252009-07-17 12:17:14 -07001564 if (track->isStopped()) {
1565 track->reset();
1566 }
1567 if (track->isTerminated() || track->isStopped() || track->isPaused()) {
1568 // We have consumed all the buffers of this track.
1569 // Remove it from the list of active tracks.
1570 tracksToRemove->add(track);
1571 mAudioMixer->disable(AudioMixer::MIXING);
1572 } else {
1573 // No buffers for this track. Give it a few chances to
1574 // fill a buffer, then remove it from active list.
1575 if (--(track->mRetryCount) <= 0) {
Eric Laurent62443f52009-10-05 20:29:18 -07001576 LOGV("BUFFER TIMEOUT: remove(%d) from active list on thread %p", track->name(), this);
Eric Laurenta553c252009-07-17 12:17:14 -07001577 tracksToRemove->add(track);
Eric Laurent059b4be2009-11-09 23:32:22 -08001578 } else if (mixerStatus != MIXER_TRACKS_READY) {
1579 mixerStatus = MIXER_TRACKS_ENABLED;
Eric Laurenta553c252009-07-17 12:17:14 -07001580 }
Eric Laurent059b4be2009-11-09 23:32:22 -08001581
1582 mAudioMixer->disable(AudioMixer::MIXING);
Eric Laurenta553c252009-07-17 12:17:14 -07001583 }
1584 }
1585 }
1586
1587 // remove all the tracks that need to be...
1588 count = tracksToRemove->size();
1589 if (UNLIKELY(count)) {
1590 for (size_t i=0 ; i<count ; i++) {
1591 const sp<Track>& track = tracksToRemove->itemAt(i);
1592 mActiveTracks.remove(track);
1593 if (track->isTerminated()) {
1594 mTracks.remove(track);
1595 deleteTrackName_l(track->mName);
1596 }
1597 }
1598 }
1599
Eric Laurent059b4be2009-11-09 23:32:22 -08001600 return mixerStatus;
Eric Laurenta553c252009-07-17 12:17:14 -07001601}
1602
1603void AudioFlinger::MixerThread::getTracks(
1604 SortedVector < sp<Track> >& tracks,
1605 SortedVector < wp<Track> >& activeTracks,
1606 int streamType)
1607{
1608 LOGV ("MixerThread::getTracks() mixer %p, mTracks.size %d, mActiveTracks.size %d", this, mTracks.size(), mActiveTracks.size());
1609 Mutex::Autolock _l(mLock);
1610 size_t size = mTracks.size();
1611 for (size_t i = 0; i < size; i++) {
1612 sp<Track> t = mTracks[i];
1613 if (t->type() == streamType) {
1614 tracks.add(t);
1615 int j = mActiveTracks.indexOf(t);
1616 if (j >= 0) {
1617 t = mActiveTracks[j].promote();
1618 if (t != NULL) {
1619 activeTracks.add(t);
1620 }
1621 }
1622 }
1623 }
1624
1625 size = activeTracks.size();
1626 for (size_t i = 0; i < size; i++) {
1627 mActiveTracks.remove(activeTracks[i]);
1628 }
1629
1630 size = tracks.size();
1631 for (size_t i = 0; i < size; i++) {
1632 sp<Track> t = tracks[i];
1633 mTracks.remove(t);
1634 deleteTrackName_l(t->name());
1635 }
1636}
1637
1638void AudioFlinger::MixerThread::putTracks(
1639 SortedVector < sp<Track> >& tracks,
1640 SortedVector < wp<Track> >& activeTracks)
1641{
1642 LOGV ("MixerThread::putTracks() mixer %p, tracks.size %d, activeTracks.size %d", this, tracks.size(), activeTracks.size());
1643 Mutex::Autolock _l(mLock);
1644 size_t size = tracks.size();
1645 for (size_t i = 0; i < size ; i++) {
1646 sp<Track> t = tracks[i];
1647 int name = getTrackName_l();
1648
1649 if (name < 0) return;
1650
1651 t->mName = name;
1652 t->mThread = this;
1653 mTracks.add(t);
1654
1655 int j = activeTracks.indexOf(t);
1656 if (j >= 0) {
1657 mActiveTracks.add(t);
Eric Laurentd069f322009-09-01 05:56:26 -07001658 // force buffer refilling and no ramp volume when the track is mixed for the first time
1659 t->mFillingUpStatus = Track::FS_FILLING;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001660 }
1661 }
1662}
1663
Eric Laurenta553c252009-07-17 12:17:14 -07001664// getTrackName_l() must be called with ThreadBase::mLock held
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001665int AudioFlinger::MixerThread::getTrackName_l()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001666{
1667 return mAudioMixer->getTrackName();
1668}
1669
Eric Laurenta553c252009-07-17 12:17:14 -07001670// deleteTrackName_l() must be called with ThreadBase::mLock held
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001671void AudioFlinger::MixerThread::deleteTrackName_l(int name)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001672{
Eric Laurent0a080292009-12-07 10:53:10 -08001673 LOGV("remove track (%d) and delete from mixer", name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001674 mAudioMixer->deleteTrackName(name);
1675}
1676
Eric Laurenta553c252009-07-17 12:17:14 -07001677// checkForNewParameters_l() must be called with ThreadBase::mLock held
1678bool AudioFlinger::MixerThread::checkForNewParameters_l()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001679{
Eric Laurenta553c252009-07-17 12:17:14 -07001680 bool reconfig = false;
1681
Eric Laurent8fce46a2009-08-04 09:45:33 -07001682 while (!mNewParameters.isEmpty()) {
Eric Laurenta553c252009-07-17 12:17:14 -07001683 status_t status = NO_ERROR;
Eric Laurent8fce46a2009-08-04 09:45:33 -07001684 String8 keyValuePair = mNewParameters[0];
1685 AudioParameter param = AudioParameter(keyValuePair);
Eric Laurenta553c252009-07-17 12:17:14 -07001686 int value;
Eric Laurent8fce46a2009-08-04 09:45:33 -07001687
Eric Laurenta553c252009-07-17 12:17:14 -07001688 if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
1689 reconfig = true;
1690 }
1691 if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
1692 if (value != AudioSystem::PCM_16_BIT) {
1693 status = BAD_VALUE;
1694 } else {
1695 reconfig = true;
1696 }
1697 }
1698 if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
1699 if (value != AudioSystem::CHANNEL_OUT_STEREO) {
1700 status = BAD_VALUE;
1701 } else {
1702 reconfig = true;
1703 }
1704 }
1705 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
1706 // do not accept frame count changes if tracks are open as the track buffer
1707 // size depends on frame count and correct behavior would not be garantied
1708 // if frame count is changed after track creation
1709 if (!mTracks.isEmpty()) {
1710 status = INVALID_OPERATION;
1711 } else {
1712 reconfig = true;
1713 }
1714 }
1715 if (status == NO_ERROR) {
Eric Laurent8fce46a2009-08-04 09:45:33 -07001716 status = mOutput->setParameters(keyValuePair);
Eric Laurenta553c252009-07-17 12:17:14 -07001717 if (!mStandby && status == INVALID_OPERATION) {
1718 mOutput->standby();
1719 mStandby = true;
1720 mBytesWritten = 0;
Eric Laurent8fce46a2009-08-04 09:45:33 -07001721 status = mOutput->setParameters(keyValuePair);
Eric Laurenta553c252009-07-17 12:17:14 -07001722 }
1723 if (status == NO_ERROR && reconfig) {
1724 delete mAudioMixer;
1725 readOutputParameters();
1726 mAudioMixer = new AudioMixer(mFrameCount, mSampleRate);
1727 for (size_t i = 0; i < mTracks.size() ; i++) {
1728 int name = getTrackName_l();
1729 if (name < 0) break;
1730 mTracks[i]->mName = name;
Eric Laurent6f7e0972009-08-10 08:15:12 -07001731 // limit track sample rate to 2 x new output sample rate
1732 if (mTracks[i]->mCblk->sampleRate > 2 * sampleRate()) {
1733 mTracks[i]->mCblk->sampleRate = 2 * sampleRate();
1734 }
Eric Laurenta553c252009-07-17 12:17:14 -07001735 }
Eric Laurent8fce46a2009-08-04 09:45:33 -07001736 sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
Eric Laurenta553c252009-07-17 12:17:14 -07001737 }
1738 }
Eric Laurent3fdb1262009-11-07 00:01:32 -08001739
1740 mNewParameters.removeAt(0);
1741
Eric Laurenta553c252009-07-17 12:17:14 -07001742 mParamStatus = status;
Eric Laurenta553c252009-07-17 12:17:14 -07001743 mParamCond.signal();
Eric Laurent8fce46a2009-08-04 09:45:33 -07001744 mWaitWorkCV.wait(mLock);
Eric Laurenta553c252009-07-17 12:17:14 -07001745 }
1746 return reconfig;
1747}
1748
1749status_t AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>& args)
1750{
1751 const size_t SIZE = 256;
1752 char buffer[SIZE];
1753 String8 result;
1754
1755 PlaybackThread::dumpInternals(fd, args);
1756
1757 snprintf(buffer, SIZE, "AudioMixer tracks: %08x\n", mAudioMixer->trackNames());
1758 result.append(buffer);
1759 write(fd, result.string(), result.size());
1760 return NO_ERROR;
1761}
1762
Eric Laurent059b4be2009-11-09 23:32:22 -08001763uint32_t AudioFlinger::MixerThread::activeSleepTimeUs()
Eric Laurent62443f52009-10-05 20:29:18 -07001764{
Eric Laurent059b4be2009-11-09 23:32:22 -08001765 return (uint32_t)(mOutput->latency() * 1000) / 2;
1766}
1767
1768uint32_t AudioFlinger::MixerThread::idleSleepTimeUs()
1769{
1770 return (uint32_t)((mFrameCount * 1000) / mSampleRate) * 1000;
Eric Laurent62443f52009-10-05 20:29:18 -07001771}
1772
Eric Laurenta553c252009-07-17 12:17:14 -07001773// ----------------------------------------------------------------------------
Eric Laurent49f02be2009-11-19 09:00:56 -08001774AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id)
1775 : PlaybackThread(audioFlinger, output, id),
Eric Laurenta553c252009-07-17 12:17:14 -07001776 mLeftVolume (1.0), mRightVolume(1.0)
1777{
1778 mType = PlaybackThread::DIRECT;
1779}
1780
1781AudioFlinger::DirectOutputThread::~DirectOutputThread()
1782{
1783}
1784
1785
1786bool AudioFlinger::DirectOutputThread::threadLoop()
1787{
Eric Laurent059b4be2009-11-09 23:32:22 -08001788 uint32_t mixerStatus = MIXER_IDLE;
Eric Laurenta553c252009-07-17 12:17:14 -07001789 sp<Track> trackToRemove;
1790 sp<Track> activeTrack;
1791 nsecs_t standbyTime = systemTime();
1792 int8_t *curBuf;
1793 size_t mixBufferSize = mFrameCount*mFrameSize;
Eric Laurent059b4be2009-11-09 23:32:22 -08001794 uint32_t activeSleepTime = activeSleepTimeUs();
1795 uint32_t idleSleepTime = idleSleepTimeUs();
1796 uint32_t sleepTime = idleSleepTime;
1797
Eric Laurenta553c252009-07-17 12:17:14 -07001798
1799 while (!exitPending())
1800 {
1801 processConfigEvents();
1802
Eric Laurent059b4be2009-11-09 23:32:22 -08001803 mixerStatus = MIXER_IDLE;
1804
Eric Laurenta553c252009-07-17 12:17:14 -07001805 { // scope for the mLock
1806
1807 Mutex::Autolock _l(mLock);
1808
1809 if (checkForNewParameters_l()) {
1810 mixBufferSize = mFrameCount*mFrameSize;
Eric Laurent059b4be2009-11-09 23:32:22 -08001811 activeSleepTime = activeSleepTimeUs();
1812 idleSleepTime = idleSleepTimeUs();
Eric Laurenta553c252009-07-17 12:17:14 -07001813 }
1814
1815 // put audio hardware into standby after short delay
1816 if UNLIKELY((!mActiveTracks.size() && systemTime() > standbyTime) ||
1817 mSuspended) {
1818 // wait until we have something to do...
1819 if (!mStandby) {
1820 LOGV("Audio hardware entering standby, mixer %p\n", this);
1821 mOutput->standby();
1822 mStandby = true;
1823 mBytesWritten = 0;
1824 }
1825
1826 if (!mActiveTracks.size() && mConfigEvents.isEmpty()) {
1827 // we're about to wait, flush the binder command buffer
1828 IPCThreadState::self()->flushCommands();
1829
1830 if (exitPending()) break;
1831
1832 LOGV("DirectOutputThread %p TID %d going to sleep\n", this, gettid());
1833 mWaitWorkCV.wait(mLock);
1834 LOGV("DirectOutputThread %p TID %d waking up in active mode\n", this, gettid());
1835
1836 if (mMasterMute == false) {
1837 char value[PROPERTY_VALUE_MAX];
1838 property_get("ro.audio.silent", value, "0");
1839 if (atoi(value)) {
1840 LOGD("Silence is golden");
1841 setMasterMute(true);
1842 }
1843 }
1844
1845 standbyTime = systemTime() + kStandbyTimeInNsecs;
Eric Laurent059b4be2009-11-09 23:32:22 -08001846 sleepTime = idleSleepTime;
Eric Laurenta553c252009-07-17 12:17:14 -07001847 continue;
1848 }
1849 }
1850
1851 // find out which tracks need to be processed
1852 if (mActiveTracks.size() != 0) {
1853 sp<Track> t = mActiveTracks[0].promote();
1854 if (t == 0) continue;
1855
1856 Track* const track = t.get();
1857 audio_track_cblk_t* cblk = track->cblk();
1858
1859 // The first time a track is added we wait
1860 // for all its buffers to be filled before processing it
1861 if (cblk->framesReady() && (track->isReady() || track->isStopped()) &&
1862 !track->isPaused())
1863 {
1864 //LOGV("track %d u=%08x, s=%08x [OK]", track->name(), cblk->user, cblk->server);
1865
1866 // compute volume for this track
1867 float left, right;
1868 if (track->isMuted() || mMasterMute || track->isPausing() ||
1869 mStreamTypes[track->type()].mute) {
1870 left = right = 0;
1871 if (track->isPausing()) {
1872 track->setPaused();
1873 }
1874 } else {
1875 float typeVolume = mStreamTypes[track->type()].volume;
1876 float v = mMasterVolume * typeVolume;
1877 float v_clamped = v * cblk->volume[0];
1878 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
1879 left = v_clamped/MAX_GAIN;
1880 v_clamped = v * cblk->volume[1];
1881 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
1882 right = v_clamped/MAX_GAIN;
1883 }
1884
1885 if (left != mLeftVolume || right != mRightVolume) {
1886 mOutput->setVolume(left, right);
1887 left = mLeftVolume;
1888 right = mRightVolume;
1889 }
1890
1891 if (track->mFillingUpStatus == Track::FS_FILLED) {
1892 track->mFillingUpStatus = Track::FS_ACTIVE;
1893 if (track->mState == TrackBase::RESUMING) {
1894 track->mState = TrackBase::ACTIVE;
1895 }
1896 }
1897
1898 // reset retry count
1899 track->mRetryCount = kMaxTrackRetries;
1900 activeTrack = t;
Eric Laurent059b4be2009-11-09 23:32:22 -08001901 mixerStatus = MIXER_TRACKS_READY;
Eric Laurenta553c252009-07-17 12:17:14 -07001902 } else {
1903 //LOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
1904 if (track->isStopped()) {
1905 track->reset();
1906 }
1907 if (track->isTerminated() || track->isStopped() || track->isPaused()) {
1908 // We have consumed all the buffers of this track.
1909 // Remove it from the list of active tracks.
1910 trackToRemove = track;
1911 } else {
1912 // No buffers for this track. Give it a few chances to
1913 // fill a buffer, then remove it from active list.
1914 if (--(track->mRetryCount) <= 0) {
1915 LOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
1916 trackToRemove = track;
Eric Laurent059b4be2009-11-09 23:32:22 -08001917 } else {
1918 mixerStatus = MIXER_TRACKS_ENABLED;
Eric Laurenta553c252009-07-17 12:17:14 -07001919 }
Eric Laurent059b4be2009-11-09 23:32:22 -08001920 }
Eric Laurenta553c252009-07-17 12:17:14 -07001921 }
1922 }
1923
1924 // remove all the tracks that need to be...
1925 if (UNLIKELY(trackToRemove != 0)) {
1926 mActiveTracks.remove(trackToRemove);
1927 if (trackToRemove->isTerminated()) {
1928 mTracks.remove(trackToRemove);
1929 deleteTrackName_l(trackToRemove->mName);
1930 }
1931 }
1932 }
1933
Eric Laurent059b4be2009-11-09 23:32:22 -08001934 if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
Eric Laurentf69a3f82009-09-22 00:35:48 -07001935 AudioBufferProvider::Buffer buffer;
1936 size_t frameCount = mFrameCount;
1937 curBuf = (int8_t *)mMixBuffer;
1938 // output audio to hardware
1939 while(frameCount) {
1940 buffer.frameCount = frameCount;
1941 activeTrack->getNextBuffer(&buffer);
1942 if (UNLIKELY(buffer.raw == 0)) {
1943 memset(curBuf, 0, frameCount * mFrameSize);
1944 break;
1945 }
1946 memcpy(curBuf, buffer.raw, buffer.frameCount * mFrameSize);
1947 frameCount -= buffer.frameCount;
1948 curBuf += buffer.frameCount * mFrameSize;
1949 activeTrack->releaseBuffer(&buffer);
1950 }
1951 sleepTime = 0;
1952 standbyTime = systemTime() + kStandbyTimeInNsecs;
Eric Laurent96c08a62009-09-07 08:38:38 -07001953 } else {
Eric Laurent62443f52009-10-05 20:29:18 -07001954 if (sleepTime == 0) {
Eric Laurent059b4be2009-11-09 23:32:22 -08001955 if (mixerStatus == MIXER_TRACKS_ENABLED) {
1956 sleepTime = activeSleepTime;
1957 } else {
1958 sleepTime = idleSleepTime;
1959 }
Eric Laurent62443f52009-10-05 20:29:18 -07001960 } else if (mBytesWritten != 0 && AudioSystem::isLinearPCM(mFormat)) {
Eric Laurentf69a3f82009-09-22 00:35:48 -07001961 memset (mMixBuffer, 0, mFrameCount * mFrameSize);
Eric Laurent96c08a62009-09-07 08:38:38 -07001962 sleepTime = 0;
Eric Laurent96c08a62009-09-07 08:38:38 -07001963 }
Eric Laurentf69a3f82009-09-22 00:35:48 -07001964 }
Eric Laurent96c08a62009-09-07 08:38:38 -07001965
Eric Laurentf69a3f82009-09-22 00:35:48 -07001966 if (mSuspended) {
Eric Laurent059b4be2009-11-09 23:32:22 -08001967 sleepTime = idleSleepTime;
Eric Laurentf69a3f82009-09-22 00:35:48 -07001968 }
1969 // sleepTime == 0 means we must write to audio hardware
1970 if (sleepTime == 0) {
1971 mLastWriteTime = systemTime();
1972 mInWrite = true;
Eric Laurent0986e792010-01-19 17:37:09 -08001973 mBytesWritten += mixBufferSize;
Eric Laurentf69a3f82009-09-22 00:35:48 -07001974 int bytesWritten = (int)mOutput->write(mMixBuffer, mixBufferSize);
Eric Laurent0986e792010-01-19 17:37:09 -08001975 if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
Eric Laurentf69a3f82009-09-22 00:35:48 -07001976 mNumWrites++;
1977 mInWrite = false;
1978 mStandby = false;
1979 } else {
1980 usleep(sleepTime);
Eric Laurenta553c252009-07-17 12:17:14 -07001981 }
1982
1983 // finally let go of removed track, without the lock held
1984 // since we can't guarantee the destructors won't acquire that
1985 // same lock.
1986 trackToRemove.clear();
1987 activeTrack.clear();
1988 }
1989
1990 if (!mStandby) {
1991 mOutput->standby();
1992 }
Eric Laurenta553c252009-07-17 12:17:14 -07001993
1994 LOGV("DirectOutputThread %p exiting", this);
1995 return false;
1996}
1997
1998// getTrackName_l() must be called with ThreadBase::mLock held
1999int AudioFlinger::DirectOutputThread::getTrackName_l()
2000{
2001 return 0;
2002}
2003
2004// deleteTrackName_l() must be called with ThreadBase::mLock held
2005void AudioFlinger::DirectOutputThread::deleteTrackName_l(int name)
2006{
2007}
2008
2009// checkForNewParameters_l() must be called with ThreadBase::mLock held
2010bool AudioFlinger::DirectOutputThread::checkForNewParameters_l()
2011{
2012 bool reconfig = false;
2013
Eric Laurent8fce46a2009-08-04 09:45:33 -07002014 while (!mNewParameters.isEmpty()) {
Eric Laurenta553c252009-07-17 12:17:14 -07002015 status_t status = NO_ERROR;
Eric Laurent8fce46a2009-08-04 09:45:33 -07002016 String8 keyValuePair = mNewParameters[0];
2017 AudioParameter param = AudioParameter(keyValuePair);
Eric Laurenta553c252009-07-17 12:17:14 -07002018 int value;
Eric Laurent8fce46a2009-08-04 09:45:33 -07002019
Eric Laurenta553c252009-07-17 12:17:14 -07002020 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
2021 // do not accept frame count changes if tracks are open as the track buffer
2022 // size depends on frame count and correct behavior would not be garantied
2023 // if frame count is changed after track creation
2024 if (!mTracks.isEmpty()) {
2025 status = INVALID_OPERATION;
2026 } else {
2027 reconfig = true;
2028 }
2029 }
2030 if (status == NO_ERROR) {
Eric Laurent8fce46a2009-08-04 09:45:33 -07002031 status = mOutput->setParameters(keyValuePair);
Eric Laurenta553c252009-07-17 12:17:14 -07002032 if (!mStandby && status == INVALID_OPERATION) {
2033 mOutput->standby();
2034 mStandby = true;
2035 mBytesWritten = 0;
Eric Laurent8fce46a2009-08-04 09:45:33 -07002036 status = mOutput->setParameters(keyValuePair);
Eric Laurenta553c252009-07-17 12:17:14 -07002037 }
2038 if (status == NO_ERROR && reconfig) {
2039 readOutputParameters();
Eric Laurent8fce46a2009-08-04 09:45:33 -07002040 sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
Eric Laurenta553c252009-07-17 12:17:14 -07002041 }
2042 }
Eric Laurent3fdb1262009-11-07 00:01:32 -08002043
2044 mNewParameters.removeAt(0);
2045
Eric Laurenta553c252009-07-17 12:17:14 -07002046 mParamStatus = status;
Eric Laurenta553c252009-07-17 12:17:14 -07002047 mParamCond.signal();
Eric Laurent8fce46a2009-08-04 09:45:33 -07002048 mWaitWorkCV.wait(mLock);
Eric Laurenta553c252009-07-17 12:17:14 -07002049 }
2050 return reconfig;
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -08002051}
2052
Eric Laurent059b4be2009-11-09 23:32:22 -08002053uint32_t AudioFlinger::DirectOutputThread::activeSleepTimeUs()
Eric Laurent62443f52009-10-05 20:29:18 -07002054{
2055 uint32_t time;
2056 if (AudioSystem::isLinearPCM(mFormat)) {
Eric Laurent059b4be2009-11-09 23:32:22 -08002057 time = (uint32_t)(mOutput->latency() * 1000) / 2;
2058 } else {
2059 time = 10000;
2060 }
2061 return time;
2062}
2063
2064uint32_t AudioFlinger::DirectOutputThread::idleSleepTimeUs()
2065{
2066 uint32_t time;
2067 if (AudioSystem::isLinearPCM(mFormat)) {
2068 time = (uint32_t)((mFrameCount * 1000) / mSampleRate) * 1000;
Eric Laurent62443f52009-10-05 20:29:18 -07002069 } else {
2070 time = 10000;
2071 }
2072 return time;
2073}
2074
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002075// ----------------------------------------------------------------------------
2076
Eric Laurent49f02be2009-11-19 09:00:56 -08002077AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger, AudioFlinger::MixerThread* mainThread, int id)
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08002078 : MixerThread(audioFlinger, mainThread->getOutput(), id), mWaitTimeMs(UINT_MAX)
Eric Laurenta553c252009-07-17 12:17:14 -07002079{
2080 mType = PlaybackThread::DUPLICATING;
2081 addOutputTrack(mainThread);
2082}
2083
2084AudioFlinger::DuplicatingThread::~DuplicatingThread()
2085{
Eric Laurent0a080292009-12-07 10:53:10 -08002086 for (size_t i = 0; i < mOutputTracks.size(); i++) {
2087 mOutputTracks[i]->destroy();
2088 }
Eric Laurenta553c252009-07-17 12:17:14 -07002089 mOutputTracks.clear();
2090}
2091
2092bool AudioFlinger::DuplicatingThread::threadLoop()
2093{
Eric Laurenta553c252009-07-17 12:17:14 -07002094 int16_t* curBuf = mMixBuffer;
2095 Vector< sp<Track> > tracksToRemove;
Eric Laurent059b4be2009-11-09 23:32:22 -08002096 uint32_t mixerStatus = MIXER_IDLE;
Eric Laurenta553c252009-07-17 12:17:14 -07002097 nsecs_t standbyTime = systemTime();
2098 size_t mixBufferSize = mFrameCount*mFrameSize;
2099 SortedVector< sp<OutputTrack> > outputTracks;
Eric Laurent62443f52009-10-05 20:29:18 -07002100 uint32_t writeFrames = 0;
Eric Laurent059b4be2009-11-09 23:32:22 -08002101 uint32_t activeSleepTime = activeSleepTimeUs();
2102 uint32_t idleSleepTime = idleSleepTimeUs();
2103 uint32_t sleepTime = idleSleepTime;
Eric Laurenta553c252009-07-17 12:17:14 -07002104
2105 while (!exitPending())
2106 {
2107 processConfigEvents();
2108
Eric Laurent059b4be2009-11-09 23:32:22 -08002109 mixerStatus = MIXER_IDLE;
Eric Laurenta553c252009-07-17 12:17:14 -07002110 { // scope for the mLock
2111
2112 Mutex::Autolock _l(mLock);
2113
2114 if (checkForNewParameters_l()) {
2115 mixBufferSize = mFrameCount*mFrameSize;
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08002116 updateWaitTime();
Eric Laurent059b4be2009-11-09 23:32:22 -08002117 activeSleepTime = activeSleepTimeUs();
2118 idleSleepTime = idleSleepTimeUs();
Eric Laurenta553c252009-07-17 12:17:14 -07002119 }
2120
2121 const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
2122
2123 for (size_t i = 0; i < mOutputTracks.size(); i++) {
2124 outputTracks.add(mOutputTracks[i]);
2125 }
2126
2127 // put audio hardware into standby after short delay
2128 if UNLIKELY((!activeTracks.size() && systemTime() > standbyTime) ||
2129 mSuspended) {
2130 if (!mStandby) {
2131 for (size_t i = 0; i < outputTracks.size(); i++) {
Eric Laurenta553c252009-07-17 12:17:14 -07002132 outputTracks[i]->stop();
Eric Laurenta553c252009-07-17 12:17:14 -07002133 }
2134 mStandby = true;
2135 mBytesWritten = 0;
2136 }
2137
2138 if (!activeTracks.size() && mConfigEvents.isEmpty()) {
2139 // we're about to wait, flush the binder command buffer
2140 IPCThreadState::self()->flushCommands();
2141 outputTracks.clear();
2142
2143 if (exitPending()) break;
2144
2145 LOGV("DuplicatingThread %p TID %d going to sleep\n", this, gettid());
2146 mWaitWorkCV.wait(mLock);
2147 LOGV("DuplicatingThread %p TID %d waking up\n", this, gettid());
2148 if (mMasterMute == false) {
2149 char value[PROPERTY_VALUE_MAX];
2150 property_get("ro.audio.silent", value, "0");
2151 if (atoi(value)) {
2152 LOGD("Silence is golden");
2153 setMasterMute(true);
2154 }
2155 }
2156
2157 standbyTime = systemTime() + kStandbyTimeInNsecs;
Eric Laurent059b4be2009-11-09 23:32:22 -08002158 sleepTime = idleSleepTime;
Eric Laurenta553c252009-07-17 12:17:14 -07002159 continue;
2160 }
2161 }
2162
Eric Laurent059b4be2009-11-09 23:32:22 -08002163 mixerStatus = prepareTracks_l(activeTracks, &tracksToRemove);
Eric Laurentf69a3f82009-09-22 00:35:48 -07002164 }
Eric Laurenta553c252009-07-17 12:17:14 -07002165
Eric Laurent059b4be2009-11-09 23:32:22 -08002166 if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
Eric Laurenta553c252009-07-17 12:17:14 -07002167 // mix buffers...
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08002168 if (outputsReady(outputTracks)) {
2169 mAudioMixer->process(curBuf);
2170 } else {
2171 memset(curBuf, 0, mixBufferSize);
2172 }
Eric Laurentf69a3f82009-09-22 00:35:48 -07002173 sleepTime = 0;
Eric Laurent62443f52009-10-05 20:29:18 -07002174 writeFrames = mFrameCount;
Eric Laurenta553c252009-07-17 12:17:14 -07002175 } else {
Eric Laurent62443f52009-10-05 20:29:18 -07002176 if (sleepTime == 0) {
Eric Laurent059b4be2009-11-09 23:32:22 -08002177 if (mixerStatus == MIXER_TRACKS_ENABLED) {
2178 sleepTime = activeSleepTime;
2179 } else {
2180 sleepTime = idleSleepTime;
2181 }
Eric Laurent62443f52009-10-05 20:29:18 -07002182 } else if (mBytesWritten != 0) {
2183 // flush remaining overflow buffers in output tracks
2184 for (size_t i = 0; i < outputTracks.size(); i++) {
2185 if (outputTracks[i]->isActive()) {
2186 sleepTime = 0;
2187 writeFrames = 0;
2188 break;
2189 }
2190 }
Eric Laurenta553c252009-07-17 12:17:14 -07002191 }
2192 }
Eric Laurentf69a3f82009-09-22 00:35:48 -07002193
2194 if (mSuspended) {
Eric Laurent059b4be2009-11-09 23:32:22 -08002195 sleepTime = idleSleepTime;
Eric Laurentf69a3f82009-09-22 00:35:48 -07002196 }
2197 // sleepTime == 0 means we must write to audio hardware
2198 if (sleepTime == 0) {
Eric Laurent62443f52009-10-05 20:29:18 -07002199 standbyTime = systemTime() + kStandbyTimeInNsecs;
Eric Laurentf69a3f82009-09-22 00:35:48 -07002200 for (size_t i = 0; i < outputTracks.size(); i++) {
Eric Laurent62443f52009-10-05 20:29:18 -07002201 outputTracks[i]->write(curBuf, writeFrames);
Eric Laurenta553c252009-07-17 12:17:14 -07002202 }
Eric Laurentf69a3f82009-09-22 00:35:48 -07002203 mStandby = false;
2204 mBytesWritten += mixBufferSize;
Eric Laurenta553c252009-07-17 12:17:14 -07002205 } else {
Eric Laurentf69a3f82009-09-22 00:35:48 -07002206 usleep(sleepTime);
Eric Laurenta553c252009-07-17 12:17:14 -07002207 }
2208
2209 // finally let go of all our tracks, without the lock held
2210 // since we can't guarantee the destructors won't acquire that
2211 // same lock.
2212 tracksToRemove.clear();
2213 outputTracks.clear();
2214 }
2215
Eric Laurenta553c252009-07-17 12:17:14 -07002216 return false;
2217}
2218
2219void AudioFlinger::DuplicatingThread::addOutputTrack(MixerThread *thread)
2220{
2221 int frameCount = (3 * mFrameCount * mSampleRate) / thread->sampleRate();
2222 OutputTrack *outputTrack = new OutputTrack((ThreadBase *)thread,
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08002223 this,
Eric Laurenta553c252009-07-17 12:17:14 -07002224 mSampleRate,
2225 mFormat,
2226 mChannelCount,
2227 frameCount);
Eric Laurent6c30a712009-08-10 23:22:32 -07002228 if (outputTrack->cblk() != NULL) {
2229 thread->setStreamVolume(AudioSystem::NUM_STREAM_TYPES, 1.0f);
2230 mOutputTracks.add(outputTrack);
2231 LOGV("addOutputTrack() track %p, on thread %p", outputTrack, thread);
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08002232 updateWaitTime();
Eric Laurent6c30a712009-08-10 23:22:32 -07002233 }
Eric Laurenta553c252009-07-17 12:17:14 -07002234}
2235
2236void AudioFlinger::DuplicatingThread::removeOutputTrack(MixerThread *thread)
2237{
2238 Mutex::Autolock _l(mLock);
2239 for (size_t i = 0; i < mOutputTracks.size(); i++) {
2240 if (mOutputTracks[i]->thread() == (ThreadBase *)thread) {
Eric Laurent6c30a712009-08-10 23:22:32 -07002241 mOutputTracks[i]->destroy();
Eric Laurenta553c252009-07-17 12:17:14 -07002242 mOutputTracks.removeAt(i);
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08002243 updateWaitTime();
Eric Laurenta553c252009-07-17 12:17:14 -07002244 return;
2245 }
2246 }
2247 LOGV("removeOutputTrack(): unkonwn thread: %p", thread);
2248}
2249
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08002250void AudioFlinger::DuplicatingThread::updateWaitTime()
2251{
2252 mWaitTimeMs = UINT_MAX;
2253 for (size_t i = 0; i < mOutputTracks.size(); i++) {
2254 sp<ThreadBase> strong = mOutputTracks[i]->thread().promote();
2255 if (strong != NULL) {
2256 uint32_t waitTimeMs = (strong->frameCount() * 2 * 1000) / strong->sampleRate();
2257 if (waitTimeMs < mWaitTimeMs) {
2258 mWaitTimeMs = waitTimeMs;
2259 }
2260 }
2261 }
2262}
2263
2264
2265bool AudioFlinger::DuplicatingThread::outputsReady(SortedVector< sp<OutputTrack> > &outputTracks)
2266{
2267 for (size_t i = 0; i < outputTracks.size(); i++) {
2268 sp <ThreadBase> thread = outputTracks[i]->thread().promote();
2269 if (thread == 0) {
2270 LOGW("DuplicatingThread::outputsReady() could not promote thread on output track %p", outputTracks[i].get());
2271 return false;
2272 }
2273 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
2274 if (playbackThread->standby() && !playbackThread->isSuspended()) {
2275 LOGV("DuplicatingThread output track %p on thread %p Not Ready", outputTracks[i].get(), thread.get());
2276 return false;
2277 }
2278 }
2279 return true;
2280}
2281
2282uint32_t AudioFlinger::DuplicatingThread::activeSleepTimeUs()
2283{
2284 return (mWaitTimeMs * 1000) / 2;
2285}
2286
Eric Laurenta553c252009-07-17 12:17:14 -07002287// ----------------------------------------------------------------------------
2288
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07002289// TrackBase constructor must be called with AudioFlinger::mLock held
Eric Laurenta553c252009-07-17 12:17:14 -07002290AudioFlinger::ThreadBase::TrackBase::TrackBase(
2291 const wp<ThreadBase>& thread,
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002292 const sp<Client>& client,
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002293 uint32_t sampleRate,
2294 int format,
2295 int channelCount,
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002296 int frameCount,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002297 uint32_t flags,
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002298 const sp<IMemory>& sharedBuffer)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002299 : RefBase(),
Eric Laurenta553c252009-07-17 12:17:14 -07002300 mThread(thread),
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002301 mClient(client),
Eric Laurent8a77a992009-09-09 05:16:08 -07002302 mCblk(0),
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002303 mFrameCount(0),
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002304 mState(IDLE),
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002305 mClientTid(-1),
2306 mFormat(format),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002307 mFlags(flags & ~SYSTEM_FLAGS_MASK)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002308{
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002309 LOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size());
2310
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002311 // LOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002312 size_t size = sizeof(audio_track_cblk_t);
2313 size_t bufferSize = frameCount*channelCount*sizeof(int16_t);
2314 if (sharedBuffer == 0) {
2315 size += bufferSize;
2316 }
2317
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002318 if (client != NULL) {
2319 mCblkMemory = client->heap()->allocate(size);
2320 if (mCblkMemory != 0) {
2321 mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer());
2322 if (mCblk) { // construct the shared structure in-place.
2323 new(mCblk) audio_track_cblk_t();
2324 // clear all buffers
2325 mCblk->frameCount = frameCount;
Eric Laurent88e209d2009-07-07 07:10:45 -07002326 mCblk->sampleRate = sampleRate;
2327 mCblk->channels = (uint8_t)channelCount;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002328 if (sharedBuffer == 0) {
2329 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
2330 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
2331 // Force underrun condition to avoid false underrun callback until first data is
2332 // written to buffer
2333 mCblk->flowControlFlag = 1;
2334 } else {
2335 mBuffer = sharedBuffer->pointer();
2336 }
2337 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002338 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002339 } else {
2340 LOGE("not enough memory for AudioTrack size=%u", size);
2341 client->heap()->dump("AudioTrack");
2342 return;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002343 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002344 } else {
2345 mCblk = (audio_track_cblk_t *)(new uint8_t[size]);
2346 if (mCblk) { // construct the shared structure in-place.
2347 new(mCblk) audio_track_cblk_t();
2348 // clear all buffers
2349 mCblk->frameCount = frameCount;
Eric Laurent88e209d2009-07-07 07:10:45 -07002350 mCblk->sampleRate = sampleRate;
2351 mCblk->channels = (uint8_t)channelCount;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002352 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
2353 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
2354 // Force underrun condition to avoid false underrun callback until first data is
2355 // written to buffer
2356 mCblk->flowControlFlag = 1;
2357 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
2358 }
2359 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002360}
2361
Eric Laurent2bb6b2a2009-09-16 06:02:45 -07002362AudioFlinger::ThreadBase::TrackBase::~TrackBase()
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002363{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002364 if (mCblk) {
Eric Laurenta553c252009-07-17 12:17:14 -07002365 mCblk->~audio_track_cblk_t(); // destroy our shared-structure.
2366 if (mClient == NULL) {
2367 delete mCblk;
2368 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002369 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002370 mCblkMemory.clear(); // and free the shared memory
Eric Laurentb9481d82009-09-17 05:12:56 -07002371 if (mClient != NULL) {
2372 Mutex::Autolock _l(mClient->audioFlinger()->mLock);
2373 mClient.clear();
2374 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002375}
2376
Eric Laurent2bb6b2a2009-09-16 06:02:45 -07002377void AudioFlinger::ThreadBase::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002378{
2379 buffer->raw = 0;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002380 mFrameCount = buffer->frameCount;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002381 step();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002382 buffer->frameCount = 0;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002383}
2384
Eric Laurent2bb6b2a2009-09-16 06:02:45 -07002385bool AudioFlinger::ThreadBase::TrackBase::step() {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002386 bool result;
2387 audio_track_cblk_t* cblk = this->cblk();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002388
2389 result = cblk->stepServer(mFrameCount);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002390 if (!result) {
2391 LOGV("stepServer failed acquiring cblk mutex");
2392 mFlags |= STEPSERVER_FAILED;
2393 }
2394 return result;
2395}
2396
Eric Laurent2bb6b2a2009-09-16 06:02:45 -07002397void AudioFlinger::ThreadBase::TrackBase::reset() {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002398 audio_track_cblk_t* cblk = this->cblk();
2399
2400 cblk->user = 0;
2401 cblk->server = 0;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002402 cblk->userBase = 0;
2403 cblk->serverBase = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002404 mFlags &= (uint32_t)(~SYSTEM_FLAGS_MASK);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002405 LOGV("TrackBase::reset");
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002406}
2407
Eric Laurent2bb6b2a2009-09-16 06:02:45 -07002408sp<IMemory> AudioFlinger::ThreadBase::TrackBase::getCblk() const
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002409{
2410 return mCblkMemory;
2411}
2412
Eric Laurent2bb6b2a2009-09-16 06:02:45 -07002413int AudioFlinger::ThreadBase::TrackBase::sampleRate() const {
The Android Open Source Project10592532009-03-18 17:39:46 -07002414 return (int)mCblk->sampleRate;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002415}
2416
Eric Laurent2bb6b2a2009-09-16 06:02:45 -07002417int AudioFlinger::ThreadBase::TrackBase::channelCount() const {
Eric Laurent88e209d2009-07-07 07:10:45 -07002418 return (int)mCblk->channels;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002419}
2420
Eric Laurent2bb6b2a2009-09-16 06:02:45 -07002421void* AudioFlinger::ThreadBase::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002422 audio_track_cblk_t* cblk = this->cblk();
Eric Laurenta553c252009-07-17 12:17:14 -07002423 int8_t *bufferStart = (int8_t *)mBuffer + (offset-cblk->serverBase)*cblk->frameSize;
2424 int8_t *bufferEnd = bufferStart + frames * cblk->frameSize;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002425
2426 // Check validity of returned pointer in case the track control block would have been corrupted.
Eric Laurenta553c252009-07-17 12:17:14 -07002427 if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd ||
2428 ((unsigned long)bufferStart & (unsigned long)(cblk->frameSize - 1))) {
The Android Open Source Project10592532009-03-18 17:39:46 -07002429 LOGE("TrackBase::getBuffer buffer out of range:\n start: %p, end %p , mBuffer %p mBufferEnd %p\n \
2430 server %d, serverBase %d, user %d, userBase %d, channels %d",
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002431 bufferStart, bufferEnd, mBuffer, mBufferEnd,
The Android Open Source Project10592532009-03-18 17:39:46 -07002432 cblk->server, cblk->serverBase, cblk->user, cblk->userBase, cblk->channels);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002433 return 0;
2434 }
2435
2436 return bufferStart;
2437}
2438
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002439// ----------------------------------------------------------------------------
2440
Eric Laurenta553c252009-07-17 12:17:14 -07002441// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
2442AudioFlinger::PlaybackThread::Track::Track(
2443 const wp<ThreadBase>& thread,
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002444 const sp<Client>& client,
2445 int streamType,
2446 uint32_t sampleRate,
2447 int format,
2448 int channelCount,
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002449 int frameCount,
2450 const sp<IMemory>& sharedBuffer)
Eric Laurenta553c252009-07-17 12:17:14 -07002451 : TrackBase(thread, client, sampleRate, format, channelCount, frameCount, 0, sharedBuffer),
2452 mMute(false), mSharedBuffer(sharedBuffer), mName(-1)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002453{
Eric Laurent8a77a992009-09-09 05:16:08 -07002454 if (mCblk != NULL) {
2455 sp<ThreadBase> baseThread = thread.promote();
2456 if (baseThread != 0) {
2457 PlaybackThread *playbackThread = (PlaybackThread *)baseThread.get();
2458 mName = playbackThread->getTrackName_l();
2459 }
2460 LOGV("Track constructor name %d, calling thread %d", mName, IPCThreadState::self()->getCallingPid());
2461 if (mName < 0) {
2462 LOGE("no more track names available");
2463 }
2464 mVolume[0] = 1.0f;
2465 mVolume[1] = 1.0f;
2466 mStreamType = streamType;
2467 // NOTE: audio_track_cblk_t::frameSize for 8 bit PCM data is based on a sample size of
2468 // 16 bit because data is converted to 16 bit before being stored in buffer by AudioTrack
2469 mCblk->frameSize = AudioSystem::isLinearPCM(format) ? channelCount * sizeof(int16_t) : sizeof(int8_t);
Eric Laurenta553c252009-07-17 12:17:14 -07002470 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002471}
2472
Eric Laurenta553c252009-07-17 12:17:14 -07002473AudioFlinger::PlaybackThread::Track::~Track()
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002474{
Eric Laurenta553c252009-07-17 12:17:14 -07002475 LOGV("PlaybackThread::Track destructor");
2476 sp<ThreadBase> thread = mThread.promote();
2477 if (thread != 0) {
Eric Laurentac196e12009-12-01 02:17:41 -08002478 Mutex::Autolock _l(thread->mLock);
Eric Laurenta553c252009-07-17 12:17:14 -07002479 mState = TERMINATED;
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07002480 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002481}
2482
Eric Laurenta553c252009-07-17 12:17:14 -07002483void AudioFlinger::PlaybackThread::Track::destroy()
2484{
2485 // NOTE: destroyTrack_l() can remove a strong reference to this Track
2486 // by removing it from mTracks vector, so there is a risk that this Tracks's
2487 // desctructor is called. As the destructor needs to lock mLock,
2488 // we must acquire a strong reference on this Track before locking mLock
2489 // here so that the destructor is called only when exiting this function.
2490 // On the other hand, as long as Track::destroy() is only called by
2491 // TrackHandle destructor, the TrackHandle still holds a strong ref on
2492 // this Track with its member mTrack.
2493 sp<Track> keep(this);
2494 { // scope for mLock
2495 sp<ThreadBase> thread = mThread.promote();
2496 if (thread != 0) {
Eric Laurentac196e12009-12-01 02:17:41 -08002497 if (!isOutputTrack()) {
2498 if (mState == ACTIVE || mState == RESUMING) {
2499 AudioSystem::stopOutput(thread->id(), (AudioSystem::stream_type)mStreamType);
2500 }
2501 AudioSystem::releaseOutput(thread->id());
Eric Laurent49f02be2009-11-19 09:00:56 -08002502 }
Eric Laurenta553c252009-07-17 12:17:14 -07002503 Mutex::Autolock _l(thread->mLock);
2504 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
2505 playbackThread->destroyTrack_l(this);
2506 }
2507 }
2508}
2509
2510void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002511{
Eric Laurent3fdb1262009-11-07 00:01:32 -08002512 snprintf(buffer, size, " %5d %5d %3u %3u %3u %04u %1d %1d %1d %5u %5u %5u %08x %08x\n",
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002513 mName - AudioMixer::TRACK0,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002514 (mClient == NULL) ? getpid() : mClient->pid(),
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002515 mStreamType,
2516 mFormat,
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002517 mCblk->channels,
2518 mFrameCount,
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002519 mState,
2520 mMute,
2521 mFillingUpStatus,
2522 mCblk->sampleRate,
2523 mCblk->volume[0],
2524 mCblk->volume[1],
2525 mCblk->server,
2526 mCblk->user);
2527}
2528
Eric Laurenta553c252009-07-17 12:17:14 -07002529status_t AudioFlinger::PlaybackThread::Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002530{
2531 audio_track_cblk_t* cblk = this->cblk();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002532 uint32_t framesReady;
2533 uint32_t framesReq = buffer->frameCount;
2534
2535 // Check if last stepServer failed, try to step now
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002536 if (mFlags & TrackBase::STEPSERVER_FAILED) {
2537 if (!step()) goto getNextBuffer_exit;
2538 LOGV("stepServer recovered");
2539 mFlags &= ~TrackBase::STEPSERVER_FAILED;
2540 }
2541
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002542 framesReady = cblk->framesReady();
2543
2544 if (LIKELY(framesReady)) {
2545 uint32_t s = cblk->server;
2546 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
2547
2548 bufferEnd = (cblk->loopEnd < bufferEnd) ? cblk->loopEnd : bufferEnd;
2549 if (framesReq > framesReady) {
2550 framesReq = framesReady;
2551 }
2552 if (s + framesReq > bufferEnd) {
2553 framesReq = bufferEnd - s;
2554 }
2555
2556 buffer->raw = getBuffer(s, framesReq);
2557 if (buffer->raw == 0) goto getNextBuffer_exit;
2558
2559 buffer->frameCount = framesReq;
2560 return NO_ERROR;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002561 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002562
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002563getNextBuffer_exit:
2564 buffer->raw = 0;
2565 buffer->frameCount = 0;
Eric Laurent62443f52009-10-05 20:29:18 -07002566 LOGV("getNextBuffer() no more data for track %d on thread %p", mName, mThread.unsafe_get());
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002567 return NOT_ENOUGH_DATA;
2568}
2569
Eric Laurenta553c252009-07-17 12:17:14 -07002570bool AudioFlinger::PlaybackThread::Track::isReady() const {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002571 if (mFillingUpStatus != FS_FILLING) return true;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002572
2573 if (mCblk->framesReady() >= mCblk->frameCount ||
2574 mCblk->forceReady) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002575 mFillingUpStatus = FS_FILLED;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002576 mCblk->forceReady = 0;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002577 return true;
2578 }
2579 return false;
2580}
2581
Eric Laurenta553c252009-07-17 12:17:14 -07002582status_t AudioFlinger::PlaybackThread::Track::start()
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002583{
Eric Laurent49f02be2009-11-19 09:00:56 -08002584 status_t status = NO_ERROR;
Eric Laurenta553c252009-07-17 12:17:14 -07002585 LOGV("start(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
2586 sp<ThreadBase> thread = mThread.promote();
2587 if (thread != 0) {
2588 Mutex::Autolock _l(thread->mLock);
Eric Laurent49f02be2009-11-19 09:00:56 -08002589 int state = mState;
2590 // here the track could be either new, or restarted
2591 // in both cases "unstop" the track
2592 if (mState == PAUSED) {
2593 mState = TrackBase::RESUMING;
2594 LOGV("PAUSED => RESUMING (%d) on thread %p", mName, this);
2595 } else {
2596 mState = TrackBase::ACTIVE;
2597 LOGV("? => ACTIVE (%d) on thread %p", mName, this);
2598 }
2599
2600 if (!isOutputTrack() && state != ACTIVE && state != RESUMING) {
2601 thread->mLock.unlock();
2602 status = AudioSystem::startOutput(thread->id(), (AudioSystem::stream_type)mStreamType);
2603 thread->mLock.lock();
2604 }
2605 if (status == NO_ERROR) {
2606 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
2607 playbackThread->addTrack_l(this);
2608 } else {
2609 mState = state;
2610 }
2611 } else {
2612 status = BAD_VALUE;
Eric Laurenta553c252009-07-17 12:17:14 -07002613 }
Eric Laurent49f02be2009-11-19 09:00:56 -08002614 return status;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002615}
2616
Eric Laurenta553c252009-07-17 12:17:14 -07002617void AudioFlinger::PlaybackThread::Track::stop()
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002618{
Eric Laurenta553c252009-07-17 12:17:14 -07002619 LOGV("stop(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
2620 sp<ThreadBase> thread = mThread.promote();
2621 if (thread != 0) {
2622 Mutex::Autolock _l(thread->mLock);
Eric Laurent49f02be2009-11-19 09:00:56 -08002623 int state = mState;
Eric Laurenta553c252009-07-17 12:17:14 -07002624 if (mState > STOPPED) {
2625 mState = STOPPED;
2626 // If the track is not active (PAUSED and buffers full), flush buffers
2627 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
2628 if (playbackThread->mActiveTracks.indexOf(this) < 0) {
2629 reset();
2630 }
Eric Laurent62443f52009-10-05 20:29:18 -07002631 LOGV("(> STOPPED) => STOPPED (%d) on thread %p", mName, playbackThread);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002632 }
Eric Laurent49f02be2009-11-19 09:00:56 -08002633 if (!isOutputTrack() && (state == ACTIVE || state == RESUMING)) {
2634 thread->mLock.unlock();
2635 AudioSystem::stopOutput(thread->id(), (AudioSystem::stream_type)mStreamType);
2636 thread->mLock.lock();
2637 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002638 }
2639}
2640
Eric Laurenta553c252009-07-17 12:17:14 -07002641void AudioFlinger::PlaybackThread::Track::pause()
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002642{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002643 LOGV("pause(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
Eric Laurenta553c252009-07-17 12:17:14 -07002644 sp<ThreadBase> thread = mThread.promote();
2645 if (thread != 0) {
2646 Mutex::Autolock _l(thread->mLock);
2647 if (mState == ACTIVE || mState == RESUMING) {
2648 mState = PAUSING;
Eric Laurent62443f52009-10-05 20:29:18 -07002649 LOGV("ACTIVE/RESUMING => PAUSING (%d) on thread %p", mName, thread.get());
Eric Laurent49f02be2009-11-19 09:00:56 -08002650 if (!isOutputTrack()) {
2651 thread->mLock.unlock();
2652 AudioSystem::stopOutput(thread->id(), (AudioSystem::stream_type)mStreamType);
2653 thread->mLock.lock();
2654 }
Eric Laurenta553c252009-07-17 12:17:14 -07002655 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002656 }
2657}
2658
Eric Laurenta553c252009-07-17 12:17:14 -07002659void AudioFlinger::PlaybackThread::Track::flush()
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002660{
2661 LOGV("flush(%d)", mName);
Eric Laurenta553c252009-07-17 12:17:14 -07002662 sp<ThreadBase> thread = mThread.promote();
2663 if (thread != 0) {
2664 Mutex::Autolock _l(thread->mLock);
2665 if (mState != STOPPED && mState != PAUSED && mState != PAUSING) {
2666 return;
2667 }
2668 // No point remaining in PAUSED state after a flush => go to
2669 // STOPPED state
2670 mState = STOPPED;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002671
Eric Laurenta553c252009-07-17 12:17:14 -07002672 mCblk->lock.lock();
2673 // NOTE: reset() will reset cblk->user and cblk->server with
2674 // the risk that at the same time, the AudioMixer is trying to read
2675 // data. In this case, getNextBuffer() would return a NULL pointer
2676 // as audio buffer => the AudioMixer code MUST always test that pointer
2677 // returned by getNextBuffer() is not NULL!
2678 reset();
2679 mCblk->lock.unlock();
2680 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002681}
2682
Eric Laurenta553c252009-07-17 12:17:14 -07002683void AudioFlinger::PlaybackThread::Track::reset()
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002684{
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002685 // Do not reset twice to avoid discarding data written just after a flush and before
2686 // the audioflinger thread detects the track is stopped.
2687 if (!mResetDone) {
2688 TrackBase::reset();
2689 // Force underrun condition to avoid false underrun callback until first data is
2690 // written to buffer
2691 mCblk->flowControlFlag = 1;
2692 mCblk->forceReady = 0;
Eric Laurenta553c252009-07-17 12:17:14 -07002693 mFillingUpStatus = FS_FILLING;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002694 mResetDone = true;
2695 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002696}
2697
Eric Laurenta553c252009-07-17 12:17:14 -07002698void AudioFlinger::PlaybackThread::Track::mute(bool muted)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002699{
2700 mMute = muted;
2701}
2702
Eric Laurenta553c252009-07-17 12:17:14 -07002703void AudioFlinger::PlaybackThread::Track::setVolume(float left, float right)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002704{
2705 mVolume[0] = left;
2706 mVolume[1] = right;
2707}
2708
2709// ----------------------------------------------------------------------------
2710
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07002711// RecordTrack constructor must be called with AudioFlinger::mLock held
Eric Laurenta553c252009-07-17 12:17:14 -07002712AudioFlinger::RecordThread::RecordTrack::RecordTrack(
2713 const wp<ThreadBase>& thread,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002714 const sp<Client>& client,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002715 uint32_t sampleRate,
2716 int format,
2717 int channelCount,
2718 int frameCount,
2719 uint32_t flags)
Eric Laurenta553c252009-07-17 12:17:14 -07002720 : TrackBase(thread, client, sampleRate, format,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002721 channelCount, frameCount, flags, 0),
Eric Laurenta553c252009-07-17 12:17:14 -07002722 mOverflow(false)
2723{
Eric Laurent8a77a992009-09-09 05:16:08 -07002724 if (mCblk != NULL) {
2725 LOGV("RecordTrack constructor, size %d", (int)mBufferEnd - (int)mBuffer);
2726 if (format == AudioSystem::PCM_16_BIT) {
2727 mCblk->frameSize = channelCount * sizeof(int16_t);
2728 } else if (format == AudioSystem::PCM_8_BIT) {
2729 mCblk->frameSize = channelCount * sizeof(int8_t);
2730 } else {
2731 mCblk->frameSize = sizeof(int8_t);
2732 }
2733 }
Eric Laurenta553c252009-07-17 12:17:14 -07002734}
2735
2736AudioFlinger::RecordThread::RecordTrack::~RecordTrack()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002737{
Eric Laurent49f02be2009-11-19 09:00:56 -08002738 sp<ThreadBase> thread = mThread.promote();
2739 if (thread != 0) {
2740 AudioSystem::releaseInput(thread->id());
2741 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002742}
2743
Eric Laurenta553c252009-07-17 12:17:14 -07002744status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002745{
2746 audio_track_cblk_t* cblk = this->cblk();
2747 uint32_t framesAvail;
2748 uint32_t framesReq = buffer->frameCount;
2749
2750 // Check if last stepServer failed, try to step now
2751 if (mFlags & TrackBase::STEPSERVER_FAILED) {
2752 if (!step()) goto getNextBuffer_exit;
2753 LOGV("stepServer recovered");
2754 mFlags &= ~TrackBase::STEPSERVER_FAILED;
2755 }
2756
2757 framesAvail = cblk->framesAvailable_l();
2758
2759 if (LIKELY(framesAvail)) {
2760 uint32_t s = cblk->server;
2761 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
2762
2763 if (framesReq > framesAvail) {
2764 framesReq = framesAvail;
2765 }
2766 if (s + framesReq > bufferEnd) {
2767 framesReq = bufferEnd - s;
2768 }
2769
2770 buffer->raw = getBuffer(s, framesReq);
2771 if (buffer->raw == 0) goto getNextBuffer_exit;
2772
2773 buffer->frameCount = framesReq;
2774 return NO_ERROR;
2775 }
2776
2777getNextBuffer_exit:
2778 buffer->raw = 0;
2779 buffer->frameCount = 0;
2780 return NOT_ENOUGH_DATA;
2781}
2782
Eric Laurenta553c252009-07-17 12:17:14 -07002783status_t AudioFlinger::RecordThread::RecordTrack::start()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002784{
Eric Laurenta553c252009-07-17 12:17:14 -07002785 sp<ThreadBase> thread = mThread.promote();
2786 if (thread != 0) {
2787 RecordThread *recordThread = (RecordThread *)thread.get();
2788 return recordThread->start(this);
Eric Laurent49f02be2009-11-19 09:00:56 -08002789 } else {
2790 return BAD_VALUE;
Eric Laurenta553c252009-07-17 12:17:14 -07002791 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002792}
2793
Eric Laurenta553c252009-07-17 12:17:14 -07002794void AudioFlinger::RecordThread::RecordTrack::stop()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002795{
Eric Laurenta553c252009-07-17 12:17:14 -07002796 sp<ThreadBase> thread = mThread.promote();
2797 if (thread != 0) {
2798 RecordThread *recordThread = (RecordThread *)thread.get();
2799 recordThread->stop(this);
2800 TrackBase::reset();
2801 // Force overerrun condition to avoid false overrun callback until first data is
2802 // read from buffer
2803 mCblk->flowControlFlag = 1;
2804 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002805}
2806
Eric Laurent3fdb1262009-11-07 00:01:32 -08002807void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size)
2808{
2809 snprintf(buffer, size, " %05d %03u %03u %04u %01d %05u %08x %08x\n",
2810 (mClient == NULL) ? getpid() : mClient->pid(),
2811 mFormat,
2812 mCblk->channels,
2813 mFrameCount,
2814 mState,
2815 mCblk->sampleRate,
2816 mCblk->server,
2817 mCblk->user);
2818}
2819
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002820
2821// ----------------------------------------------------------------------------
2822
Eric Laurenta553c252009-07-17 12:17:14 -07002823AudioFlinger::PlaybackThread::OutputTrack::OutputTrack(
2824 const wp<ThreadBase>& thread,
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08002825 DuplicatingThread *sourceThread,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002826 uint32_t sampleRate,
2827 int format,
2828 int channelCount,
2829 int frameCount)
Eric Laurenta553c252009-07-17 12:17:14 -07002830 : Track(thread, NULL, AudioSystem::NUM_STREAM_TYPES, sampleRate, format, channelCount, frameCount, NULL),
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08002831 mActive(false), mSourceThread(sourceThread)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002832{
Eric Laurenta553c252009-07-17 12:17:14 -07002833
2834 PlaybackThread *playbackThread = (PlaybackThread *)thread.unsafe_get();
Eric Laurent6c30a712009-08-10 23:22:32 -07002835 if (mCblk != NULL) {
2836 mCblk->out = 1;
2837 mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
2838 mCblk->volume[0] = mCblk->volume[1] = 0x1000;
2839 mOutBuffer.frameCount = 0;
Eric Laurent6c30a712009-08-10 23:22:32 -07002840 playbackThread->mTracks.add(this);
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08002841 LOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, mCblk->frameCount %d, mCblk->sampleRate %d, mCblk->channels %d mBufferEnd %p",
2842 mCblk, mBuffer, mCblk->buffers, mCblk->frameCount, mCblk->sampleRate, mCblk->channels, mBufferEnd);
Eric Laurent6c30a712009-08-10 23:22:32 -07002843 } else {
2844 LOGW("Error creating output track on thread %p", playbackThread);
2845 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002846}
2847
Eric Laurenta553c252009-07-17 12:17:14 -07002848AudioFlinger::PlaybackThread::OutputTrack::~OutputTrack()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002849{
Eric Laurent6c30a712009-08-10 23:22:32 -07002850 clearBufferQueue();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002851}
2852
Eric Laurenta553c252009-07-17 12:17:14 -07002853status_t AudioFlinger::PlaybackThread::OutputTrack::start()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002854{
2855 status_t status = Track::start();
Eric Laurenta553c252009-07-17 12:17:14 -07002856 if (status != NO_ERROR) {
2857 return status;
2858 }
2859
2860 mActive = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002861 mRetryCount = 127;
2862 return status;
2863}
2864
Eric Laurenta553c252009-07-17 12:17:14 -07002865void AudioFlinger::PlaybackThread::OutputTrack::stop()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002866{
2867 Track::stop();
2868 clearBufferQueue();
2869 mOutBuffer.frameCount = 0;
Eric Laurenta553c252009-07-17 12:17:14 -07002870 mActive = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002871}
2872
Eric Laurenta553c252009-07-17 12:17:14 -07002873bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t frames)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002874{
2875 Buffer *pInBuffer;
2876 Buffer inBuffer;
2877 uint32_t channels = mCblk->channels;
Eric Laurenta553c252009-07-17 12:17:14 -07002878 bool outputBufferFull = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002879 inBuffer.frameCount = frames;
2880 inBuffer.i16 = data;
Eric Laurenta553c252009-07-17 12:17:14 -07002881
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08002882 uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
Eric Laurenta553c252009-07-17 12:17:14 -07002883
Eric Laurent62443f52009-10-05 20:29:18 -07002884 if (!mActive && frames != 0) {
Eric Laurenta553c252009-07-17 12:17:14 -07002885 start();
2886 sp<ThreadBase> thread = mThread.promote();
2887 if (thread != 0) {
2888 MixerThread *mixerThread = (MixerThread *)thread.get();
2889 if (mCblk->frameCount > frames){
2890 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
2891 uint32_t startFrames = (mCblk->frameCount - frames);
2892 pInBuffer = new Buffer;
2893 pInBuffer->mBuffer = new int16_t[startFrames * channels];
2894 pInBuffer->frameCount = startFrames;
2895 pInBuffer->i16 = pInBuffer->mBuffer;
2896 memset(pInBuffer->raw, 0, startFrames * channels * sizeof(int16_t));
2897 mBufferQueue.add(pInBuffer);
2898 } else {
2899 LOGW ("OutputTrack::write() %p no more buffers in queue", this);
2900 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002901 }
Eric Laurenta553c252009-07-17 12:17:14 -07002902 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002903 }
2904
Eric Laurenta553c252009-07-17 12:17:14 -07002905 while (waitTimeLeftMs) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002906 // First write pending buffers, then new data
2907 if (mBufferQueue.size()) {
2908 pInBuffer = mBufferQueue.itemAt(0);
2909 } else {
2910 pInBuffer = &inBuffer;
2911 }
Eric Laurenta553c252009-07-17 12:17:14 -07002912
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002913 if (pInBuffer->frameCount == 0) {
2914 break;
2915 }
Eric Laurenta553c252009-07-17 12:17:14 -07002916
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002917 if (mOutBuffer.frameCount == 0) {
2918 mOutBuffer.frameCount = pInBuffer->frameCount;
Eric Laurenta553c252009-07-17 12:17:14 -07002919 nsecs_t startTime = systemTime();
2920 if (obtainBuffer(&mOutBuffer, waitTimeLeftMs) == (status_t)AudioTrack::NO_MORE_BUFFERS) {
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08002921 LOGV ("OutputTrack::write() %p thread %p no more output buffers", this, mThread.unsafe_get());
Eric Laurenta553c252009-07-17 12:17:14 -07002922 outputBufferFull = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002923 break;
2924 }
Eric Laurenta553c252009-07-17 12:17:14 -07002925 uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
Eric Laurenta553c252009-07-17 12:17:14 -07002926 if (waitTimeLeftMs >= waitTimeMs) {
2927 waitTimeLeftMs -= waitTimeMs;
2928 } else {
2929 waitTimeLeftMs = 0;
2930 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002931 }
Eric Laurenta553c252009-07-17 12:17:14 -07002932
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002933 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount : pInBuffer->frameCount;
2934 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * channels * sizeof(int16_t));
2935 mCblk->stepUser(outFrames);
2936 pInBuffer->frameCount -= outFrames;
2937 pInBuffer->i16 += outFrames * channels;
2938 mOutBuffer.frameCount -= outFrames;
Eric Laurenta553c252009-07-17 12:17:14 -07002939 mOutBuffer.i16 += outFrames * channels;
2940
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002941 if (pInBuffer->frameCount == 0) {
2942 if (mBufferQueue.size()) {
2943 mBufferQueue.removeAt(0);
2944 delete [] pInBuffer->mBuffer;
2945 delete pInBuffer;
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08002946 LOGV("OutputTrack::write() %p thread %p released overflow buffer %d", this, mThread.unsafe_get(), mBufferQueue.size());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002947 } else {
2948 break;
2949 }
2950 }
2951 }
Eric Laurenta553c252009-07-17 12:17:14 -07002952
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002953 // If we could not write all frames, allocate a buffer and queue it for next time.
2954 if (inBuffer.frameCount) {
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08002955 sp<ThreadBase> thread = mThread.promote();
2956 if (thread != 0 && !thread->standby()) {
2957 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
2958 pInBuffer = new Buffer;
2959 pInBuffer->mBuffer = new int16_t[inBuffer.frameCount * channels];
2960 pInBuffer->frameCount = inBuffer.frameCount;
2961 pInBuffer->i16 = pInBuffer->mBuffer;
2962 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * channels * sizeof(int16_t));
2963 mBufferQueue.add(pInBuffer);
2964 LOGV("OutputTrack::write() %p thread %p adding overflow buffer %d", this, mThread.unsafe_get(), mBufferQueue.size());
2965 } else {
2966 LOGW("OutputTrack::write() %p thread %p no more overflow buffers", mThread.unsafe_get(), this);
2967 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002968 }
2969 }
Eric Laurenta553c252009-07-17 12:17:14 -07002970
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002971 // Calling write() with a 0 length buffer, means that no more data will be written:
Eric Laurenta553c252009-07-17 12:17:14 -07002972 // If no more buffers are pending, fill output track buffer to make sure it is started
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002973 // by output mixer.
Eric Laurenta553c252009-07-17 12:17:14 -07002974 if (frames == 0 && mBufferQueue.size() == 0) {
2975 if (mCblk->user < mCblk->frameCount) {
2976 frames = mCblk->frameCount - mCblk->user;
2977 pInBuffer = new Buffer;
2978 pInBuffer->mBuffer = new int16_t[frames * channels];
2979 pInBuffer->frameCount = frames;
2980 pInBuffer->i16 = pInBuffer->mBuffer;
2981 memset(pInBuffer->raw, 0, frames * channels * sizeof(int16_t));
2982 mBufferQueue.add(pInBuffer);
Eric Laurent62443f52009-10-05 20:29:18 -07002983 } else if (mActive) {
Eric Laurenta553c252009-07-17 12:17:14 -07002984 stop();
2985 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002986 }
2987
Eric Laurenta553c252009-07-17 12:17:14 -07002988 return outputBufferFull;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002989}
2990
Eric Laurenta553c252009-07-17 12:17:14 -07002991status_t AudioFlinger::PlaybackThread::OutputTrack::obtainBuffer(AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002992{
2993 int active;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002994 status_t result;
2995 audio_track_cblk_t* cblk = mCblk;
2996 uint32_t framesReq = buffer->frameCount;
2997
Eric Laurenta553c252009-07-17 12:17:14 -07002998// LOGV("OutputTrack::obtainBuffer user %d, server %d", cblk->user, cblk->server);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002999 buffer->frameCount = 0;
Eric Laurenta553c252009-07-17 12:17:14 -07003000
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003001 uint32_t framesAvail = cblk->framesAvailable();
3002
Eric Laurenta553c252009-07-17 12:17:14 -07003003
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003004 if (framesAvail == 0) {
Eric Laurenta553c252009-07-17 12:17:14 -07003005 Mutex::Autolock _l(cblk->lock);
3006 goto start_loop_here;
3007 while (framesAvail == 0) {
3008 active = mActive;
3009 if (UNLIKELY(!active)) {
3010 LOGV("Not active and NO_MORE_BUFFERS");
3011 return AudioTrack::NO_MORE_BUFFERS;
3012 }
3013 result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
3014 if (result != NO_ERROR) {
3015 return AudioTrack::NO_MORE_BUFFERS;
3016 }
3017 // read the server count again
3018 start_loop_here:
3019 framesAvail = cblk->framesAvailable_l();
3020 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003021 }
3022
Eric Laurenta553c252009-07-17 12:17:14 -07003023// if (framesAvail < framesReq) {
3024// return AudioTrack::NO_MORE_BUFFERS;
3025// }
3026
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003027 if (framesReq > framesAvail) {
3028 framesReq = framesAvail;
3029 }
3030
3031 uint32_t u = cblk->user;
3032 uint32_t bufferEnd = cblk->userBase + cblk->frameCount;
3033
3034 if (u + framesReq > bufferEnd) {
3035 framesReq = bufferEnd - u;
3036 }
3037
3038 buffer->frameCount = framesReq;
3039 buffer->raw = (void *)cblk->buffer(u);
3040 return NO_ERROR;
3041}
3042
3043
Eric Laurenta553c252009-07-17 12:17:14 -07003044void AudioFlinger::PlaybackThread::OutputTrack::clearBufferQueue()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003045{
3046 size_t size = mBufferQueue.size();
3047 Buffer *pBuffer;
Eric Laurenta553c252009-07-17 12:17:14 -07003048
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003049 for (size_t i = 0; i < size; i++) {
3050 pBuffer = mBufferQueue.itemAt(i);
3051 delete [] pBuffer->mBuffer;
3052 delete pBuffer;
3053 }
3054 mBufferQueue.clear();
3055}
3056
3057// ----------------------------------------------------------------------------
3058
3059AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
3060 : RefBase(),
3061 mAudioFlinger(audioFlinger),
Mathias Agopian6faf7892010-01-25 19:00:00 -08003062 mMemoryDealer(new MemoryDealer(1024*1024, "AudioFlinger::Client")),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003063 mPid(pid)
3064{
3065 // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
3066}
3067
Eric Laurentb9481d82009-09-17 05:12:56 -07003068// Client destructor must be called with AudioFlinger::mLock held
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003069AudioFlinger::Client::~Client()
3070{
Eric Laurentb9481d82009-09-17 05:12:56 -07003071 mAudioFlinger->removeClient_l(mPid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003072}
3073
3074const sp<MemoryDealer>& AudioFlinger::Client::heap() const
3075{
3076 return mMemoryDealer;
3077}
3078
3079// ----------------------------------------------------------------------------
3080
Eric Laurenta553c252009-07-17 12:17:14 -07003081AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::PlaybackThread::Track>& track)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003082 : BnAudioTrack(),
3083 mTrack(track)
3084{
3085}
3086
3087AudioFlinger::TrackHandle::~TrackHandle() {
3088 // just stop the track on deletion, associated resources
3089 // will be freed from the main thread once all pending buffers have
3090 // been played. Unless it's not in the active track list, in which
3091 // case we free everything now...
3092 mTrack->destroy();
3093}
3094
3095status_t AudioFlinger::TrackHandle::start() {
3096 return mTrack->start();
3097}
3098
3099void AudioFlinger::TrackHandle::stop() {
3100 mTrack->stop();
3101}
3102
3103void AudioFlinger::TrackHandle::flush() {
3104 mTrack->flush();
3105}
3106
3107void AudioFlinger::TrackHandle::mute(bool e) {
3108 mTrack->mute(e);
3109}
3110
3111void AudioFlinger::TrackHandle::pause() {
3112 mTrack->pause();
3113}
3114
3115void AudioFlinger::TrackHandle::setVolume(float left, float right) {
3116 mTrack->setVolume(left, right);
3117}
3118
3119sp<IMemory> AudioFlinger::TrackHandle::getCblk() const {
3120 return mTrack->getCblk();
3121}
3122
3123status_t AudioFlinger::TrackHandle::onTransact(
3124 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
3125{
3126 return BnAudioTrack::onTransact(code, data, reply, flags);
3127}
3128
3129// ----------------------------------------------------------------------------
3130
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003131sp<IAudioRecord> AudioFlinger::openRecord(
3132 pid_t pid,
Eric Laurentddb78e72009-07-28 08:44:33 -07003133 int input,
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003134 uint32_t sampleRate,
3135 int format,
3136 int channelCount,
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003137 int frameCount,
3138 uint32_t flags,
3139 status_t *status)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003140{
Eric Laurenta553c252009-07-17 12:17:14 -07003141 sp<RecordThread::RecordTrack> recordTrack;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003142 sp<RecordHandle> recordHandle;
3143 sp<Client> client;
3144 wp<Client> wclient;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003145 status_t lStatus;
Eric Laurenta553c252009-07-17 12:17:14 -07003146 RecordThread *thread;
3147 size_t inFrameCount;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003148
3149 // check calling permissions
3150 if (!recordingAllowed()) {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003151 lStatus = PERMISSION_DENIED;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003152 goto Exit;
3153 }
3154
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003155 // add client to list
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07003156 { // scope for mLock
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003157 Mutex::Autolock _l(mLock);
Eric Laurenta553c252009-07-17 12:17:14 -07003158 thread = checkRecordThread_l(input);
3159 if (thread == NULL) {
3160 lStatus = BAD_VALUE;
3161 goto Exit;
3162 }
3163
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003164 wclient = mClients.valueFor(pid);
3165 if (wclient != NULL) {
3166 client = wclient.promote();
3167 } else {
3168 client = new Client(this, pid);
3169 mClients.add(pid, client);
3170 }
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07003171
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07003172 // create new record track. The record track uses one track in mHardwareMixerThread by convention.
Eric Laurenta553c252009-07-17 12:17:14 -07003173 recordTrack = new RecordThread::RecordTrack(thread, client, sampleRate,
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07003174 format, channelCount, frameCount, flags);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003175 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003176 if (recordTrack->getCblk() == NULL) {
Eric Laurentb9481d82009-09-17 05:12:56 -07003177 // remove local strong reference to Client before deleting the RecordTrack so that the Client
3178 // destructor is called by the TrackBase destructor with mLock held
3179 client.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003180 recordTrack.clear();
3181 lStatus = NO_MEMORY;
3182 goto Exit;
3183 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003184
3185 // return to handle to client
3186 recordHandle = new RecordHandle(recordTrack);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003187 lStatus = NO_ERROR;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003188
3189Exit:
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003190 if (status) {
3191 *status = lStatus;
3192 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003193 return recordHandle;
3194}
3195
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003196// ----------------------------------------------------------------------------
3197
Eric Laurenta553c252009-07-17 12:17:14 -07003198AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::RecordThread::RecordTrack>& recordTrack)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003199 : BnAudioRecord(),
3200 mRecordTrack(recordTrack)
3201{
3202}
3203
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003204AudioFlinger::RecordHandle::~RecordHandle() {
3205 stop();
3206}
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003207
3208status_t AudioFlinger::RecordHandle::start() {
3209 LOGV("RecordHandle::start()");
3210 return mRecordTrack->start();
3211}
3212
3213void AudioFlinger::RecordHandle::stop() {
3214 LOGV("RecordHandle::stop()");
3215 mRecordTrack->stop();
3216}
3217
3218sp<IMemory> AudioFlinger::RecordHandle::getCblk() const {
3219 return mRecordTrack->getCblk();
3220}
3221
3222status_t AudioFlinger::RecordHandle::onTransact(
3223 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
3224{
3225 return BnAudioRecord::onTransact(code, data, reply, flags);
3226}
3227
3228// ----------------------------------------------------------------------------
3229
Eric Laurent49f02be2009-11-19 09:00:56 -08003230AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, AudioStreamIn *input, uint32_t sampleRate, uint32_t channels, int id) :
3231 ThreadBase(audioFlinger, id),
Eric Laurenta553c252009-07-17 12:17:14 -07003232 mInput(input), mResampler(0), mRsmpOutBuffer(0), mRsmpInBuffer(0)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003233{
Eric Laurenta553c252009-07-17 12:17:14 -07003234 mReqChannelCount = AudioSystem::popCount(channels);
3235 mReqSampleRate = sampleRate;
3236 readInputParameters();
3237 sendConfigEvent(AudioSystem::INPUT_OPENED);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003238}
3239
Eric Laurenta553c252009-07-17 12:17:14 -07003240
3241AudioFlinger::RecordThread::~RecordThread()
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003242{
Eric Laurenta553c252009-07-17 12:17:14 -07003243 delete[] mRsmpInBuffer;
3244 if (mResampler != 0) {
3245 delete mResampler;
3246 delete[] mRsmpOutBuffer;
3247 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003248}
3249
Eric Laurenta553c252009-07-17 12:17:14 -07003250void AudioFlinger::RecordThread::onFirstRef()
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003251{
Eric Laurenta553c252009-07-17 12:17:14 -07003252 const size_t SIZE = 256;
3253 char buffer[SIZE];
3254
3255 snprintf(buffer, SIZE, "Record Thread %p", this);
3256
3257 run(buffer, PRIORITY_URGENT_AUDIO);
3258}
Eric Laurent49f02be2009-11-19 09:00:56 -08003259
Eric Laurenta553c252009-07-17 12:17:14 -07003260bool AudioFlinger::RecordThread::threadLoop()
3261{
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003262 AudioBufferProvider::Buffer buffer;
Eric Laurenta553c252009-07-17 12:17:14 -07003263 sp<RecordTrack> activeTrack;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003264
3265 // start recording
3266 while (!exitPending()) {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003267
Eric Laurenta553c252009-07-17 12:17:14 -07003268 processConfigEvents();
3269
3270 { // scope for mLock
3271 Mutex::Autolock _l(mLock);
3272 checkForNewParameters_l();
3273 if (mActiveTrack == 0 && mConfigEvents.isEmpty()) {
3274 if (!mStandby) {
3275 mInput->standby();
3276 mStandby = true;
3277 }
3278
3279 if (exitPending()) break;
3280
3281 LOGV("RecordThread: loop stopping");
3282 // go to sleep
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003283 mWaitWorkCV.wait(mLock);
Eric Laurenta553c252009-07-17 12:17:14 -07003284 LOGV("RecordThread: loop starting");
3285 continue;
3286 }
3287 if (mActiveTrack != 0) {
3288 if (mActiveTrack->mState == TrackBase::PAUSING) {
Eric Laurent9cc489a22009-12-05 05:20:01 -08003289 if (!mStandby) {
3290 mInput->standby();
3291 mStandby = true;
3292 }
Eric Laurenta553c252009-07-17 12:17:14 -07003293 mActiveTrack.clear();
3294 mStartStopCond.broadcast();
3295 } else if (mActiveTrack->mState == TrackBase::RESUMING) {
Eric Laurenta553c252009-07-17 12:17:14 -07003296 if (mReqChannelCount != mActiveTrack->channelCount()) {
3297 mActiveTrack.clear();
Eric Laurent9cc489a22009-12-05 05:20:01 -08003298 mStartStopCond.broadcast();
3299 } else if (mBytesRead != 0) {
3300 // record start succeeds only if first read from audio input
3301 // succeeds
3302 if (mBytesRead > 0) {
3303 mActiveTrack->mState = TrackBase::ACTIVE;
3304 } else {
3305 mActiveTrack.clear();
3306 }
3307 mStartStopCond.broadcast();
Eric Laurenta553c252009-07-17 12:17:14 -07003308 }
Eric Laurent9cc489a22009-12-05 05:20:01 -08003309 mStandby = false;
Eric Laurenta553c252009-07-17 12:17:14 -07003310 }
Eric Laurenta553c252009-07-17 12:17:14 -07003311 }
3312 }
3313
3314 if (mActiveTrack != 0) {
Eric Laurent9cc489a22009-12-05 05:20:01 -08003315 if (mActiveTrack->mState != TrackBase::ACTIVE &&
3316 mActiveTrack->mState != TrackBase::RESUMING) {
Eric Laurent49f02be2009-11-19 09:00:56 -08003317 usleep(5000);
3318 continue;
3319 }
Eric Laurenta553c252009-07-17 12:17:14 -07003320 buffer.frameCount = mFrameCount;
3321 if (LIKELY(mActiveTrack->getNextBuffer(&buffer) == NO_ERROR)) {
3322 size_t framesOut = buffer.frameCount;
3323 if (mResampler == 0) {
3324 // no resampling
3325 while (framesOut) {
3326 size_t framesIn = mFrameCount - mRsmpInIndex;
3327 if (framesIn) {
3328 int8_t *src = (int8_t *)mRsmpInBuffer + mRsmpInIndex * mFrameSize;
3329 int8_t *dst = buffer.i8 + (buffer.frameCount - framesOut) * mActiveTrack->mCblk->frameSize;
3330 if (framesIn > framesOut)
3331 framesIn = framesOut;
3332 mRsmpInIndex += framesIn;
3333 framesOut -= framesIn;
3334 if (mChannelCount == mReqChannelCount ||
3335 mFormat != AudioSystem::PCM_16_BIT) {
3336 memcpy(dst, src, framesIn * mFrameSize);
3337 } else {
3338 int16_t *src16 = (int16_t *)src;
3339 int16_t *dst16 = (int16_t *)dst;
3340 if (mChannelCount == 1) {
3341 while (framesIn--) {
3342 *dst16++ = *src16;
3343 *dst16++ = *src16++;
3344 }
3345 } else {
3346 while (framesIn--) {
3347 *dst16++ = (int16_t)(((int32_t)*src16 + (int32_t)*(src16 + 1)) >> 1);
3348 src16 += 2;
3349 }
3350 }
3351 }
3352 }
3353 if (framesOut && mFrameCount == mRsmpInIndex) {
Eric Laurenta553c252009-07-17 12:17:14 -07003354 if (framesOut == mFrameCount &&
3355 (mChannelCount == mReqChannelCount || mFormat != AudioSystem::PCM_16_BIT)) {
Eric Laurent9cc489a22009-12-05 05:20:01 -08003356 mBytesRead = mInput->read(buffer.raw, mInputBytes);
Eric Laurenta553c252009-07-17 12:17:14 -07003357 framesOut = 0;
3358 } else {
Eric Laurent9cc489a22009-12-05 05:20:01 -08003359 mBytesRead = mInput->read(mRsmpInBuffer, mInputBytes);
Eric Laurenta553c252009-07-17 12:17:14 -07003360 mRsmpInIndex = 0;
3361 }
Eric Laurent9cc489a22009-12-05 05:20:01 -08003362 if (mBytesRead < 0) {
Eric Laurenta553c252009-07-17 12:17:14 -07003363 LOGE("Error reading audio input");
Eric Laurent9cc489a22009-12-05 05:20:01 -08003364 if (mActiveTrack->mState == TrackBase::ACTIVE) {
Eric Laurentba8811f2010-03-02 18:38:06 -08003365 // Force input into standby so that it tries to
3366 // recover at next read attempt
3367 mInput->standby();
3368 usleep(5000);
Eric Laurent9cc489a22009-12-05 05:20:01 -08003369 }
Eric Laurenta553c252009-07-17 12:17:14 -07003370 mRsmpInIndex = mFrameCount;
3371 framesOut = 0;
3372 buffer.frameCount = 0;
3373 }
3374 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003375 }
3376 } else {
Eric Laurenta553c252009-07-17 12:17:14 -07003377 // resampling
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003378
Eric Laurenta553c252009-07-17 12:17:14 -07003379 memset(mRsmpOutBuffer, 0, framesOut * 2 * sizeof(int32_t));
3380 // alter output frame count as if we were expecting stereo samples
3381 if (mChannelCount == 1 && mReqChannelCount == 1) {
3382 framesOut >>= 1;
3383 }
3384 mResampler->resample(mRsmpOutBuffer, framesOut, this);
3385 // ditherAndClamp() works as long as all buffers returned by mActiveTrack->getNextBuffer()
3386 // are 32 bit aligned which should be always true.
3387 if (mChannelCount == 2 && mReqChannelCount == 1) {
3388 AudioMixer::ditherAndClamp(mRsmpOutBuffer, mRsmpOutBuffer, framesOut);
3389 // the resampler always outputs stereo samples: do post stereo to mono conversion
3390 int16_t *src = (int16_t *)mRsmpOutBuffer;
3391 int16_t *dst = buffer.i16;
3392 while (framesOut--) {
3393 *dst++ = (int16_t)(((int32_t)*src + (int32_t)*(src + 1)) >> 1);
3394 src += 2;
3395 }
3396 } else {
3397 AudioMixer::ditherAndClamp((int32_t *)buffer.raw, mRsmpOutBuffer, framesOut);
3398 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003399
Eric Laurenta553c252009-07-17 12:17:14 -07003400 }
3401 mActiveTrack->releaseBuffer(&buffer);
3402 mActiveTrack->overflow();
3403 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003404 // client isn't retrieving buffers fast enough
3405 else {
Eric Laurenta553c252009-07-17 12:17:14 -07003406 if (!mActiveTrack->setOverflow())
3407 LOGW("RecordThread: buffer overflow");
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003408 // Release the processor for a while before asking for a new buffer.
3409 // This will give the application more chance to read from the buffer and
3410 // clear the overflow.
3411 usleep(5000);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003412 }
3413 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003414 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003415
Eric Laurenta553c252009-07-17 12:17:14 -07003416 if (!mStandby) {
3417 mInput->standby();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003418 }
Eric Laurenta553c252009-07-17 12:17:14 -07003419 mActiveTrack.clear();
3420
Eric Laurent49f02be2009-11-19 09:00:56 -08003421 mStartStopCond.broadcast();
3422
Eric Laurenta553c252009-07-17 12:17:14 -07003423 LOGV("RecordThread %p exiting", this);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003424 return false;
3425}
3426
Eric Laurenta553c252009-07-17 12:17:14 -07003427status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003428{
Eric Laurenta553c252009-07-17 12:17:14 -07003429 LOGV("RecordThread::start");
Eric Laurent49f02be2009-11-19 09:00:56 -08003430 sp <ThreadBase> strongMe = this;
3431 status_t status = NO_ERROR;
3432 {
3433 AutoMutex lock(&mLock);
3434 if (mActiveTrack != 0) {
3435 if (recordTrack != mActiveTrack.get()) {
3436 status = -EBUSY;
3437 } else if (mActiveTrack->mState == TrackBase::PAUSING) {
Eric Laurent9cc489a22009-12-05 05:20:01 -08003438 mActiveTrack->mState = TrackBase::ACTIVE;
Eric Laurent49f02be2009-11-19 09:00:56 -08003439 }
3440 return status;
3441 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003442
Eric Laurent49f02be2009-11-19 09:00:56 -08003443 recordTrack->mState = TrackBase::IDLE;
3444 mActiveTrack = recordTrack;
3445 mLock.unlock();
3446 status_t status = AudioSystem::startInput(mId);
3447 mLock.lock();
3448 if (status != NO_ERROR) {
3449 mActiveTrack.clear();
3450 return status;
3451 }
3452 mActiveTrack->mState = TrackBase::RESUMING;
Eric Laurent9cc489a22009-12-05 05:20:01 -08003453 mRsmpInIndex = mFrameCount;
3454 mBytesRead = 0;
Eric Laurent49f02be2009-11-19 09:00:56 -08003455 // signal thread to start
3456 LOGV("Signal record thread");
3457 mWaitWorkCV.signal();
3458 // do not wait for mStartStopCond if exiting
3459 if (mExiting) {
3460 mActiveTrack.clear();
3461 status = INVALID_OPERATION;
3462 goto startError;
3463 }
3464 mStartStopCond.wait(mLock);
3465 if (mActiveTrack == 0) {
3466 LOGV("Record failed to start");
3467 status = BAD_VALUE;
3468 goto startError;
3469 }
Eric Laurenta553c252009-07-17 12:17:14 -07003470 LOGV("Record started OK");
Eric Laurent49f02be2009-11-19 09:00:56 -08003471 return status;
Eric Laurenta553c252009-07-17 12:17:14 -07003472 }
Eric Laurent49f02be2009-11-19 09:00:56 -08003473startError:
3474 AudioSystem::stopInput(mId);
3475 return status;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003476}
3477
Eric Laurenta553c252009-07-17 12:17:14 -07003478void AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) {
3479 LOGV("RecordThread::stop");
Eric Laurent49f02be2009-11-19 09:00:56 -08003480 sp <ThreadBase> strongMe = this;
3481 {
3482 AutoMutex lock(&mLock);
3483 if (mActiveTrack != 0 && recordTrack == mActiveTrack.get()) {
3484 mActiveTrack->mState = TrackBase::PAUSING;
3485 // do not wait for mStartStopCond if exiting
3486 if (mExiting) {
3487 return;
3488 }
3489 mStartStopCond.wait(mLock);
3490 // if we have been restarted, recordTrack == mActiveTrack.get() here
3491 if (mActiveTrack == 0 || recordTrack != mActiveTrack.get()) {
3492 mLock.unlock();
3493 AudioSystem::stopInput(mId);
3494 mLock.lock();
Eric Laurent9cc489a22009-12-05 05:20:01 -08003495 LOGV("Record stopped OK");
Eric Laurent49f02be2009-11-19 09:00:56 -08003496 }
3497 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003498 }
3499}
3500
Eric Laurenta553c252009-07-17 12:17:14 -07003501status_t AudioFlinger::RecordThread::dump(int fd, const Vector<String16>& args)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003502{
3503 const size_t SIZE = 256;
3504 char buffer[SIZE];
3505 String8 result;
3506 pid_t pid = 0;
3507
Eric Laurent3fdb1262009-11-07 00:01:32 -08003508 snprintf(buffer, SIZE, "\nInput thread %p internals\n", this);
3509 result.append(buffer);
3510
3511 if (mActiveTrack != 0) {
3512 result.append("Active Track:\n");
3513 result.append(" Clien Fmt Chn Buf S SRate Serv User\n");
3514 mActiveTrack->dump(buffer, SIZE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003515 result.append(buffer);
Eric Laurent3fdb1262009-11-07 00:01:32 -08003516
3517 snprintf(buffer, SIZE, "In index: %d\n", mRsmpInIndex);
3518 result.append(buffer);
3519 snprintf(buffer, SIZE, "In size: %d\n", mInputBytes);
3520 result.append(buffer);
3521 snprintf(buffer, SIZE, "Resampling: %d\n", (mResampler != 0));
3522 result.append(buffer);
3523 snprintf(buffer, SIZE, "Out channel count: %d\n", mReqChannelCount);
3524 result.append(buffer);
3525 snprintf(buffer, SIZE, "Out sample rate: %d\n", mReqSampleRate);
3526 result.append(buffer);
3527
3528
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003529 } else {
3530 result.append("No record client\n");
3531 }
3532 write(fd, result.string(), result.size());
Eric Laurent3fdb1262009-11-07 00:01:32 -08003533
3534 dumpBase(fd, args);
3535
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003536 return NO_ERROR;
3537}
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003538
Eric Laurenta553c252009-07-17 12:17:14 -07003539status_t AudioFlinger::RecordThread::getNextBuffer(AudioBufferProvider::Buffer* buffer)
3540{
3541 size_t framesReq = buffer->frameCount;
3542 size_t framesReady = mFrameCount - mRsmpInIndex;
3543 int channelCount;
3544
3545 if (framesReady == 0) {
Eric Laurent9cc489a22009-12-05 05:20:01 -08003546 mBytesRead = mInput->read(mRsmpInBuffer, mInputBytes);
3547 if (mBytesRead < 0) {
Eric Laurenta553c252009-07-17 12:17:14 -07003548 LOGE("RecordThread::getNextBuffer() Error reading audio input");
Eric Laurent9cc489a22009-12-05 05:20:01 -08003549 if (mActiveTrack->mState == TrackBase::ACTIVE) {
Eric Laurentba8811f2010-03-02 18:38:06 -08003550 // Force input into standby so that it tries to
3551 // recover at next read attempt
3552 mInput->standby();
3553 usleep(5000);
Eric Laurent9cc489a22009-12-05 05:20:01 -08003554 }
Eric Laurenta553c252009-07-17 12:17:14 -07003555 buffer->raw = 0;
3556 buffer->frameCount = 0;
3557 return NOT_ENOUGH_DATA;
3558 }
3559 mRsmpInIndex = 0;
3560 framesReady = mFrameCount;
3561 }
3562
3563 if (framesReq > framesReady) {
3564 framesReq = framesReady;
3565 }
3566
3567 if (mChannelCount == 1 && mReqChannelCount == 2) {
3568 channelCount = 1;
3569 } else {
3570 channelCount = 2;
3571 }
3572 buffer->raw = mRsmpInBuffer + mRsmpInIndex * channelCount;
3573 buffer->frameCount = framesReq;
3574 return NO_ERROR;
3575}
3576
3577void AudioFlinger::RecordThread::releaseBuffer(AudioBufferProvider::Buffer* buffer)
3578{
3579 mRsmpInIndex += buffer->frameCount;
3580 buffer->frameCount = 0;
3581}
3582
3583bool AudioFlinger::RecordThread::checkForNewParameters_l()
3584{
3585 bool reconfig = false;
3586
Eric Laurent8fce46a2009-08-04 09:45:33 -07003587 while (!mNewParameters.isEmpty()) {
Eric Laurenta553c252009-07-17 12:17:14 -07003588 status_t status = NO_ERROR;
Eric Laurent8fce46a2009-08-04 09:45:33 -07003589 String8 keyValuePair = mNewParameters[0];
3590 AudioParameter param = AudioParameter(keyValuePair);
Eric Laurenta553c252009-07-17 12:17:14 -07003591 int value;
3592 int reqFormat = mFormat;
3593 int reqSamplingRate = mReqSampleRate;
3594 int reqChannelCount = mReqChannelCount;
Eric Laurent8fce46a2009-08-04 09:45:33 -07003595
Eric Laurenta553c252009-07-17 12:17:14 -07003596 if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
3597 reqSamplingRate = value;
3598 reconfig = true;
3599 }
3600 if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
3601 reqFormat = value;
3602 reconfig = true;
3603 }
3604 if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
3605 reqChannelCount = AudioSystem::popCount(value);
3606 reconfig = true;
3607 }
3608 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
3609 // do not accept frame count changes if tracks are open as the track buffer
3610 // size depends on frame count and correct behavior would not be garantied
3611 // if frame count is changed after track creation
3612 if (mActiveTrack != 0) {
3613 status = INVALID_OPERATION;
3614 } else {
3615 reconfig = true;
3616 }
3617 }
3618 if (status == NO_ERROR) {
Eric Laurent8fce46a2009-08-04 09:45:33 -07003619 status = mInput->setParameters(keyValuePair);
Eric Laurenta553c252009-07-17 12:17:14 -07003620 if (status == INVALID_OPERATION) {
3621 mInput->standby();
Eric Laurent8fce46a2009-08-04 09:45:33 -07003622 status = mInput->setParameters(keyValuePair);
Eric Laurenta553c252009-07-17 12:17:14 -07003623 }
3624 if (reconfig) {
3625 if (status == BAD_VALUE &&
3626 reqFormat == mInput->format() && reqFormat == AudioSystem::PCM_16_BIT &&
3627 ((int)mInput->sampleRate() <= 2 * reqSamplingRate) &&
3628 (AudioSystem::popCount(mInput->channels()) < 3) && (reqChannelCount < 3)) {
3629 status = NO_ERROR;
3630 }
3631 if (status == NO_ERROR) {
3632 readInputParameters();
Eric Laurent8fce46a2009-08-04 09:45:33 -07003633 sendConfigEvent_l(AudioSystem::INPUT_CONFIG_CHANGED);
Eric Laurenta553c252009-07-17 12:17:14 -07003634 }
3635 }
3636 }
Eric Laurent3fdb1262009-11-07 00:01:32 -08003637
3638 mNewParameters.removeAt(0);
3639
Eric Laurenta553c252009-07-17 12:17:14 -07003640 mParamStatus = status;
3641 mParamCond.signal();
Eric Laurent8fce46a2009-08-04 09:45:33 -07003642 mWaitWorkCV.wait(mLock);
Eric Laurenta553c252009-07-17 12:17:14 -07003643 }
3644 return reconfig;
3645}
3646
3647String8 AudioFlinger::RecordThread::getParameters(const String8& keys)
3648{
3649 return mInput->getParameters(keys);
3650}
3651
3652void AudioFlinger::RecordThread::audioConfigChanged(int event, int param) {
3653 AudioSystem::OutputDescriptor desc;
3654 void *param2 = 0;
3655
3656 switch (event) {
3657 case AudioSystem::INPUT_OPENED:
3658 case AudioSystem::INPUT_CONFIG_CHANGED:
3659 desc.channels = mChannelCount;
3660 desc.samplingRate = mSampleRate;
3661 desc.format = mFormat;
3662 desc.frameCount = mFrameCount;
3663 desc.latency = 0;
3664 param2 = &desc;
3665 break;
3666
3667 case AudioSystem::INPUT_CLOSED:
3668 default:
3669 break;
3670 }
Eric Laurent296a0ec2009-09-15 07:10:12 -07003671 Mutex::Autolock _l(mAudioFlinger->mLock);
Eric Laurent49f02be2009-11-19 09:00:56 -08003672 mAudioFlinger->audioConfigChanged_l(event, mId, param2);
Eric Laurenta553c252009-07-17 12:17:14 -07003673}
3674
3675void AudioFlinger::RecordThread::readInputParameters()
3676{
3677 if (mRsmpInBuffer) delete mRsmpInBuffer;
3678 if (mRsmpOutBuffer) delete mRsmpOutBuffer;
3679 if (mResampler) delete mResampler;
3680 mResampler = 0;
3681
3682 mSampleRate = mInput->sampleRate();
3683 mChannelCount = AudioSystem::popCount(mInput->channels());
3684 mFormat = mInput->format();
3685 mFrameSize = mInput->frameSize();
3686 mInputBytes = mInput->bufferSize();
3687 mFrameCount = mInputBytes / mFrameSize;
3688 mRsmpInBuffer = new int16_t[mFrameCount * mChannelCount];
3689
3690 if (mSampleRate != mReqSampleRate && mChannelCount < 3 && mReqChannelCount < 3)
3691 {
3692 int channelCount;
3693 // optmization: if mono to mono, use the resampler in stereo to stereo mode to avoid
3694 // stereo to mono post process as the resampler always outputs stereo.
3695 if (mChannelCount == 1 && mReqChannelCount == 2) {
3696 channelCount = 1;
3697 } else {
3698 channelCount = 2;
3699 }
3700 mResampler = AudioResampler::create(16, channelCount, mReqSampleRate);
3701 mResampler->setSampleRate(mSampleRate);
3702 mResampler->setVolume(AudioMixer::UNITY_GAIN, AudioMixer::UNITY_GAIN);
3703 mRsmpOutBuffer = new int32_t[mFrameCount * 2];
3704
3705 // optmization: if mono to mono, alter input frame count as if we were inputing stereo samples
3706 if (mChannelCount == 1 && mReqChannelCount == 1) {
3707 mFrameCount >>= 1;
3708 }
3709
3710 }
3711 mRsmpInIndex = mFrameCount;
3712}
3713
Eric Laurent47d0a922010-02-26 02:47:27 -08003714unsigned int AudioFlinger::RecordThread::getInputFramesLost()
3715{
3716 return mInput->getInputFramesLost();
3717}
3718
Eric Laurenta553c252009-07-17 12:17:14 -07003719// ----------------------------------------------------------------------------
3720
Eric Laurentddb78e72009-07-28 08:44:33 -07003721int AudioFlinger::openOutput(uint32_t *pDevices,
Eric Laurenta553c252009-07-17 12:17:14 -07003722 uint32_t *pSamplingRate,
3723 uint32_t *pFormat,
3724 uint32_t *pChannels,
3725 uint32_t *pLatencyMs,
3726 uint32_t flags)
3727{
3728 status_t status;
3729 PlaybackThread *thread = NULL;
3730 mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
3731 uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
3732 uint32_t format = pFormat ? *pFormat : 0;
3733 uint32_t channels = pChannels ? *pChannels : 0;
3734 uint32_t latency = pLatencyMs ? *pLatencyMs : 0;
3735
3736 LOGV("openOutput(), Device %x, SamplingRate %d, Format %d, Channels %x, flags %x",
3737 pDevices ? *pDevices : 0,
3738 samplingRate,
3739 format,
3740 channels,
3741 flags);
3742
3743 if (pDevices == NULL || *pDevices == 0) {
Eric Laurentddb78e72009-07-28 08:44:33 -07003744 return 0;
Eric Laurenta553c252009-07-17 12:17:14 -07003745 }
3746 Mutex::Autolock _l(mLock);
3747
3748 AudioStreamOut *output = mAudioHardware->openOutputStream(*pDevices,
3749 (int *)&format,
3750 &channels,
3751 &samplingRate,
3752 &status);
3753 LOGV("openOutput() openOutputStream returned output %p, SamplingRate %d, Format %d, Channels %x, status %d",
3754 output,
3755 samplingRate,
3756 format,
3757 channels,
3758 status);
3759
3760 mHardwareStatus = AUDIO_HW_IDLE;
3761 if (output != 0) {
3762 if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) ||
3763 (format != AudioSystem::PCM_16_BIT) ||
3764 (channels != AudioSystem::CHANNEL_OUT_STEREO)) {
Eric Laurent49f02be2009-11-19 09:00:56 -08003765 thread = new DirectOutputThread(this, output, ++mNextThreadId);
3766 LOGV("openOutput() created direct output: ID %d thread %p", mNextThreadId, thread);
Eric Laurenta553c252009-07-17 12:17:14 -07003767 } else {
Eric Laurent49f02be2009-11-19 09:00:56 -08003768 thread = new MixerThread(this, output, ++mNextThreadId);
3769 LOGV("openOutput() created mixer output: ID %d thread %p", mNextThreadId, thread);
Glenn Kasten871c16c2010-03-05 12:18:01 -08003770
3771#ifdef LVMX
3772 unsigned bitsPerSample =
3773 (format == AudioSystem::PCM_16_BIT) ? 16 :
3774 ((format == AudioSystem::PCM_8_BIT) ? 8 : 0);
3775 unsigned channelCount = (channels == AudioSystem::CHANNEL_OUT_STEREO) ? 2 : 1;
3776 int audioOutputType = LifeVibes::threadIdToAudioOutputType(thread->id());
3777
3778 LifeVibes::init_aot(audioOutputType, samplingRate, bitsPerSample, channelCount);
3779 LifeVibes::setDevice(audioOutputType, *pDevices);
3780#endif
3781
Eric Laurenta553c252009-07-17 12:17:14 -07003782 }
Eric Laurent49f02be2009-11-19 09:00:56 -08003783 mPlaybackThreads.add(mNextThreadId, thread);
Eric Laurenta553c252009-07-17 12:17:14 -07003784
3785 if (pSamplingRate) *pSamplingRate = samplingRate;
3786 if (pFormat) *pFormat = format;
3787 if (pChannels) *pChannels = channels;
3788 if (pLatencyMs) *pLatencyMs = thread->latency();
Eric Laurent9cc489a22009-12-05 05:20:01 -08003789
3790 return mNextThreadId;
Eric Laurenta553c252009-07-17 12:17:14 -07003791 }
3792
Eric Laurent9cc489a22009-12-05 05:20:01 -08003793 return 0;
Eric Laurenta553c252009-07-17 12:17:14 -07003794}
3795
Eric Laurentddb78e72009-07-28 08:44:33 -07003796int AudioFlinger::openDuplicateOutput(int output1, int output2)
Eric Laurenta553c252009-07-17 12:17:14 -07003797{
3798 Mutex::Autolock _l(mLock);
Eric Laurentddb78e72009-07-28 08:44:33 -07003799 MixerThread *thread1 = checkMixerThread_l(output1);
3800 MixerThread *thread2 = checkMixerThread_l(output2);
Eric Laurenta553c252009-07-17 12:17:14 -07003801
Eric Laurentddb78e72009-07-28 08:44:33 -07003802 if (thread1 == NULL || thread2 == NULL) {
3803 LOGW("openDuplicateOutput() wrong output mixer type for output %d or %d", output1, output2);
3804 return 0;
Eric Laurenta553c252009-07-17 12:17:14 -07003805 }
3806
Eric Laurentddb78e72009-07-28 08:44:33 -07003807
Eric Laurent49f02be2009-11-19 09:00:56 -08003808 DuplicatingThread *thread = new DuplicatingThread(this, thread1, ++mNextThreadId);
Eric Laurentddb78e72009-07-28 08:44:33 -07003809 thread->addOutputTrack(thread2);
Eric Laurent49f02be2009-11-19 09:00:56 -08003810 mPlaybackThreads.add(mNextThreadId, thread);
Eric Laurentddb78e72009-07-28 08:44:33 -07003811 return mNextThreadId;
Eric Laurenta553c252009-07-17 12:17:14 -07003812}
3813
Eric Laurentddb78e72009-07-28 08:44:33 -07003814status_t AudioFlinger::closeOutput(int output)
Eric Laurenta553c252009-07-17 12:17:14 -07003815{
Eric Laurent49018a52009-08-04 08:37:05 -07003816 // keep strong reference on the playback thread so that
3817 // it is not destroyed while exit() is executed
3818 sp <PlaybackThread> thread;
Eric Laurenta553c252009-07-17 12:17:14 -07003819 {
3820 Mutex::Autolock _l(mLock);
3821 thread = checkPlaybackThread_l(output);
3822 if (thread == NULL) {
3823 return BAD_VALUE;
3824 }
3825
Eric Laurentddb78e72009-07-28 08:44:33 -07003826 LOGV("closeOutput() %d", output);
Eric Laurenta553c252009-07-17 12:17:14 -07003827
3828 if (thread->type() == PlaybackThread::MIXER) {
3829 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurentddb78e72009-07-28 08:44:33 -07003830 if (mPlaybackThreads.valueAt(i)->type() == PlaybackThread::DUPLICATING) {
3831 DuplicatingThread *dupThread = (DuplicatingThread *)mPlaybackThreads.valueAt(i).get();
Eric Laurent49018a52009-08-04 08:37:05 -07003832 dupThread->removeOutputTrack((MixerThread *)thread.get());
Eric Laurenta553c252009-07-17 12:17:14 -07003833 }
3834 }
3835 }
Eric Laurent296a0ec2009-09-15 07:10:12 -07003836 void *param2 = 0;
Eric Laurent49f02be2009-11-19 09:00:56 -08003837 audioConfigChanged_l(AudioSystem::OUTPUT_CLOSED, output, param2);
Eric Laurentddb78e72009-07-28 08:44:33 -07003838 mPlaybackThreads.removeItem(output);
Eric Laurenta553c252009-07-17 12:17:14 -07003839 }
3840 thread->exit();
3841
Eric Laurent49018a52009-08-04 08:37:05 -07003842 if (thread->type() != PlaybackThread::DUPLICATING) {
3843 mAudioHardware->closeOutputStream(thread->getOutput());
3844 }
Eric Laurenta553c252009-07-17 12:17:14 -07003845 return NO_ERROR;
3846}
3847
Eric Laurentddb78e72009-07-28 08:44:33 -07003848status_t AudioFlinger::suspendOutput(int output)
Eric Laurenta553c252009-07-17 12:17:14 -07003849{
3850 Mutex::Autolock _l(mLock);
3851 PlaybackThread *thread = checkPlaybackThread_l(output);
3852
3853 if (thread == NULL) {
3854 return BAD_VALUE;
3855 }
3856
Eric Laurentddb78e72009-07-28 08:44:33 -07003857 LOGV("suspendOutput() %d", output);
Eric Laurenta553c252009-07-17 12:17:14 -07003858 thread->suspend();
3859
3860 return NO_ERROR;
3861}
3862
Eric Laurentddb78e72009-07-28 08:44:33 -07003863status_t AudioFlinger::restoreOutput(int output)
Eric Laurenta553c252009-07-17 12:17:14 -07003864{
3865 Mutex::Autolock _l(mLock);
3866 PlaybackThread *thread = checkPlaybackThread_l(output);
3867
3868 if (thread == NULL) {
3869 return BAD_VALUE;
3870 }
3871
Eric Laurentddb78e72009-07-28 08:44:33 -07003872 LOGV("restoreOutput() %d", output);
Eric Laurenta553c252009-07-17 12:17:14 -07003873
3874 thread->restore();
3875
3876 return NO_ERROR;
3877}
3878
Eric Laurentddb78e72009-07-28 08:44:33 -07003879int AudioFlinger::openInput(uint32_t *pDevices,
Eric Laurenta553c252009-07-17 12:17:14 -07003880 uint32_t *pSamplingRate,
3881 uint32_t *pFormat,
3882 uint32_t *pChannels,
3883 uint32_t acoustics)
3884{
3885 status_t status;
3886 RecordThread *thread = NULL;
3887 uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
3888 uint32_t format = pFormat ? *pFormat : 0;
3889 uint32_t channels = pChannels ? *pChannels : 0;
3890 uint32_t reqSamplingRate = samplingRate;
3891 uint32_t reqFormat = format;
3892 uint32_t reqChannels = channels;
3893
3894 if (pDevices == NULL || *pDevices == 0) {
Eric Laurentddb78e72009-07-28 08:44:33 -07003895 return 0;
Eric Laurenta553c252009-07-17 12:17:14 -07003896 }
3897 Mutex::Autolock _l(mLock);
3898
3899 AudioStreamIn *input = mAudioHardware->openInputStream(*pDevices,
3900 (int *)&format,
3901 &channels,
3902 &samplingRate,
3903 &status,
3904 (AudioSystem::audio_in_acoustics)acoustics);
3905 LOGV("openInput() openInputStream returned input %p, SamplingRate %d, Format %d, Channels %x, acoustics %x, status %d",
3906 input,
3907 samplingRate,
3908 format,
3909 channels,
3910 acoustics,
3911 status);
3912
3913 // If the input could not be opened with the requested parameters and we can handle the conversion internally,
3914 // try to open again with the proposed parameters. The AudioFlinger can resample the input and do mono to stereo
3915 // or stereo to mono conversions on 16 bit PCM inputs.
3916 if (input == 0 && status == BAD_VALUE &&
3917 reqFormat == format && format == AudioSystem::PCM_16_BIT &&
3918 (samplingRate <= 2 * reqSamplingRate) &&
3919 (AudioSystem::popCount(channels) < 3) && (AudioSystem::popCount(reqChannels) < 3)) {
3920 LOGV("openInput() reopening with proposed sampling rate and channels");
3921 input = mAudioHardware->openInputStream(*pDevices,
3922 (int *)&format,
3923 &channels,
3924 &samplingRate,
3925 &status,
3926 (AudioSystem::audio_in_acoustics)acoustics);
3927 }
3928
3929 if (input != 0) {
3930 // Start record thread
Eric Laurent49f02be2009-11-19 09:00:56 -08003931 thread = new RecordThread(this, input, reqSamplingRate, reqChannels, ++mNextThreadId);
3932 mRecordThreads.add(mNextThreadId, thread);
Eric Laurentddb78e72009-07-28 08:44:33 -07003933 LOGV("openInput() created record thread: ID %d thread %p", mNextThreadId, thread);
Eric Laurenta553c252009-07-17 12:17:14 -07003934 if (pSamplingRate) *pSamplingRate = reqSamplingRate;
3935 if (pFormat) *pFormat = format;
3936 if (pChannels) *pChannels = reqChannels;
3937
3938 input->standby();
Eric Laurent9cc489a22009-12-05 05:20:01 -08003939
3940 return mNextThreadId;
Eric Laurenta553c252009-07-17 12:17:14 -07003941 }
3942
Eric Laurent9cc489a22009-12-05 05:20:01 -08003943 return 0;
Eric Laurenta553c252009-07-17 12:17:14 -07003944}
3945
Eric Laurentddb78e72009-07-28 08:44:33 -07003946status_t AudioFlinger::closeInput(int input)
Eric Laurenta553c252009-07-17 12:17:14 -07003947{
Eric Laurent49018a52009-08-04 08:37:05 -07003948 // keep strong reference on the record thread so that
3949 // it is not destroyed while exit() is executed
3950 sp <RecordThread> thread;
Eric Laurenta553c252009-07-17 12:17:14 -07003951 {
3952 Mutex::Autolock _l(mLock);
3953 thread = checkRecordThread_l(input);
3954 if (thread == NULL) {
3955 return BAD_VALUE;
3956 }
3957
Eric Laurentddb78e72009-07-28 08:44:33 -07003958 LOGV("closeInput() %d", input);
Eric Laurent296a0ec2009-09-15 07:10:12 -07003959 void *param2 = 0;
Eric Laurent49f02be2009-11-19 09:00:56 -08003960 audioConfigChanged_l(AudioSystem::INPUT_CLOSED, input, param2);
Eric Laurentddb78e72009-07-28 08:44:33 -07003961 mRecordThreads.removeItem(input);
Eric Laurenta553c252009-07-17 12:17:14 -07003962 }
3963 thread->exit();
3964
Eric Laurent49018a52009-08-04 08:37:05 -07003965 mAudioHardware->closeInputStream(thread->getInput());
3966
Eric Laurenta553c252009-07-17 12:17:14 -07003967 return NO_ERROR;
3968}
3969
Eric Laurentddb78e72009-07-28 08:44:33 -07003970status_t AudioFlinger::setStreamOutput(uint32_t stream, int output)
Eric Laurenta553c252009-07-17 12:17:14 -07003971{
3972 Mutex::Autolock _l(mLock);
3973 MixerThread *dstThread = checkMixerThread_l(output);
3974 if (dstThread == NULL) {
Eric Laurentddb78e72009-07-28 08:44:33 -07003975 LOGW("setStreamOutput() bad output id %d", output);
Eric Laurenta553c252009-07-17 12:17:14 -07003976 return BAD_VALUE;
3977 }
3978
Eric Laurentddb78e72009-07-28 08:44:33 -07003979 LOGV("setStreamOutput() stream %d to output %d", stream, output);
Eric Laurenta553c252009-07-17 12:17:14 -07003980
3981 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurentddb78e72009-07-28 08:44:33 -07003982 PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
Eric Laurenta553c252009-07-17 12:17:14 -07003983 if (thread != dstThread &&
3984 thread->type() != PlaybackThread::DIRECT) {
3985 MixerThread *srcThread = (MixerThread *)thread;
3986 SortedVector < sp<MixerThread::Track> > tracks;
3987 SortedVector < wp<MixerThread::Track> > activeTracks;
3988 srcThread->getTracks(tracks, activeTracks, stream);
3989 if (tracks.size()) {
3990 dstThread->putTracks(tracks, activeTracks);
Eric Laurenta553c252009-07-17 12:17:14 -07003991 }
3992 }
3993 }
3994
Eric Laurentd069f322009-09-01 05:56:26 -07003995 dstThread->sendConfigEvent(AudioSystem::STREAM_CONFIG_CHANGED, stream);
3996
Eric Laurenta553c252009-07-17 12:17:14 -07003997 return NO_ERROR;
3998}
3999
4000// checkPlaybackThread_l() must be called with AudioFlinger::mLock held
Eric Laurentddb78e72009-07-28 08:44:33 -07004001AudioFlinger::PlaybackThread *AudioFlinger::checkPlaybackThread_l(int output) const
Eric Laurenta553c252009-07-17 12:17:14 -07004002{
4003 PlaybackThread *thread = NULL;
Eric Laurentddb78e72009-07-28 08:44:33 -07004004 if (mPlaybackThreads.indexOfKey(output) >= 0) {
4005 thread = (PlaybackThread *)mPlaybackThreads.valueFor(output).get();
Eric Laurenta553c252009-07-17 12:17:14 -07004006 }
Eric Laurenta553c252009-07-17 12:17:14 -07004007 return thread;
4008}
4009
4010// checkMixerThread_l() must be called with AudioFlinger::mLock held
Eric Laurentddb78e72009-07-28 08:44:33 -07004011AudioFlinger::MixerThread *AudioFlinger::checkMixerThread_l(int output) const
Eric Laurenta553c252009-07-17 12:17:14 -07004012{
4013 PlaybackThread *thread = checkPlaybackThread_l(output);
4014 if (thread != NULL) {
4015 if (thread->type() == PlaybackThread::DIRECT) {
4016 thread = NULL;
4017 }
4018 }
4019 return (MixerThread *)thread;
4020}
4021
4022// checkRecordThread_l() must be called with AudioFlinger::mLock held
Eric Laurentddb78e72009-07-28 08:44:33 -07004023AudioFlinger::RecordThread *AudioFlinger::checkRecordThread_l(int input) const
Eric Laurenta553c252009-07-17 12:17:14 -07004024{
4025 RecordThread *thread = NULL;
Eric Laurentddb78e72009-07-28 08:44:33 -07004026 if (mRecordThreads.indexOfKey(input) >= 0) {
4027 thread = (RecordThread *)mRecordThreads.valueFor(input).get();
Eric Laurenta553c252009-07-17 12:17:14 -07004028 }
Eric Laurenta553c252009-07-17 12:17:14 -07004029 return thread;
4030}
4031
4032// ----------------------------------------------------------------------------
4033
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07004034status_t AudioFlinger::onTransact(
4035 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
4036{
4037 return BnAudioFlinger::onTransact(code, data, reply, flags);
4038}
4039
4040// ----------------------------------------------------------------------------
Eric Laurenta553c252009-07-17 12:17:14 -07004041
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07004042void AudioFlinger::instantiate() {
4043 defaultServiceManager()->addService(
4044 String16("media.audio_flinger"), new AudioFlinger());
4045}
4046
4047}; // namespace android