blob: 58eb590bac2b75987e76245b93aec5a98faf0b4d [file] [log] [blame]
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001/* //device/include/server/AudioFlinger/AudioFlinger.cpp
2**
3** Copyright 2007, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18
19#define LOG_TAG "AudioFlinger"
20//#define LOG_NDEBUG 0
21
22#include <math.h>
23#include <signal.h>
24#include <sys/time.h>
25#include <sys/resource.h>
26
Mathias Agopianc5b2c0b2009-05-19 19:08:10 -070027#include <binder/IServiceManager.h>
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070028#include <utils/Log.h>
Mathias Agopianc5b2c0b2009-05-19 19:08:10 -070029#include <binder/Parcel.h>
30#include <binder/IPCThreadState.h>
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070031#include <utils/String16.h>
32#include <utils/threads.h>
33
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -080034#include <cutils/properties.h>
35
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070036#include <media/AudioTrack.h>
37#include <media/AudioRecord.h>
38
39#include <private/media/AudioTrackShared.h>
40
The Android Open Source Project8a7a6752009-01-15 16:12:10 -080041#include <hardware_legacy/AudioHardwareInterface.h>
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070042
43#include "AudioMixer.h"
44#include "AudioFlinger.h"
45
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -080046#ifdef WITH_A2DP
47#include "A2dpAudioInterface.h"
48#endif
49
Glenn Kastend5ea9692010-03-05 12:18:01 -080050#ifdef LVMX
51#include "lifevibes.h"
52#endif
53
The Android Open Source Projectedbf3b62009-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 Project7c1b96a2008-10-21 07:00:00 -070063namespace android {
64
The Android Open Source Project4f68be12009-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 Projecte09fd9e2008-12-17 18:05:43 -080068//static const nsecs_t kStandbyTimeInNsecs = seconds(3);
The Android Open Source Project7c1b96a2008-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;
Eric Laurent101e77a2010-03-11 14:47:00 -080075// allow less retry attempts on direct output thread.
76// direct outputs can be a scarce resource in audio hardware and should
77// be released as quickly as possible.
78static const int8_t kMaxTrackRetriesDirect = 2;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070079
The Android Open Source Project22f8def2009-03-09 11:52:12 -070080static const int kDumpLockRetries = 50;
81static const int kDumpLockSleep = 20000;
82
Dave Sparks8a95a452009-09-30 03:09:03 -070083static const nsecs_t kWarningThrottle = seconds(5);
84
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080085
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070086#define AUDIOFLINGER_SECURITY_ENABLED 1
87
88// ----------------------------------------------------------------------------
89
90static bool recordingAllowed() {
91#ifndef HAVE_ANDROID_OS
92 return true;
93#endif
94#if AUDIOFLINGER_SECURITY_ENABLED
95 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
96 bool ok = checkCallingPermission(String16("android.permission.RECORD_AUDIO"));
97 if (!ok) LOGE("Request requires android.permission.RECORD_AUDIO");
98 return ok;
99#else
100 if (!checkCallingPermission(String16("android.permission.RECORD_AUDIO")))
101 LOGW("WARNING: Need to add android.permission.RECORD_AUDIO to manifest");
102 return true;
103#endif
104}
105
106static bool settingsAllowed() {
107#ifndef HAVE_ANDROID_OS
108 return true;
109#endif
110#if AUDIOFLINGER_SECURITY_ENABLED
111 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
112 bool ok = checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS"));
113 if (!ok) LOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS");
114 return ok;
115#else
116 if (!checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS")))
117 LOGW("WARNING: Need to add android.permission.MODIFY_AUDIO_SETTINGS to manifest");
118 return true;
119#endif
120}
121
122// ----------------------------------------------------------------------------
123
124AudioFlinger::AudioFlinger()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800125 : BnAudioFlinger(),
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700126 mAudioHardware(0), mMasterVolume(1.0f), mMasterMute(false), mNextThreadId(0)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700127{
128 mHardwareStatus = AUDIO_HW_IDLE;
Eric Laurent9d91ad52009-07-17 12:17:14 -0700129
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700130 mAudioHardware = AudioHardwareInterface::create();
Eric Laurent9d91ad52009-07-17 12:17:14 -0700131
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700132 mHardwareStatus = AUDIO_HW_INIT;
133 if (mAudioHardware->initCheck() == NO_ERROR) {
134 // open 16-bit output stream for s/w mixer
Eric Laurent9d91ad52009-07-17 12:17:14 -0700135
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800136 setMode(AudioSystem::MODE_NORMAL);
137
138 setMasterVolume(1.0f);
139 setMasterMute(false);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700140 } else {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700141 LOGE("Couldn't even initialize the stubbed audio hardware!");
142 }
Glenn Kastend5ea9692010-03-05 12:18:01 -0800143#ifdef LVMX
144 LifeVibes::init();
Eric Laurentd878cd82010-05-12 02:05:53 -0700145 mLifeVibesClientPid = -1;
Glenn Kastend5ea9692010-03-05 12:18:01 -0800146#endif
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700147}
148
149AudioFlinger::~AudioFlinger()
150{
Eric Laurentc80b1a02009-08-28 10:39:03 -0700151 while (!mRecordThreads.isEmpty()) {
152 // closeInput() will remove first entry from mRecordThreads
153 closeInput(mRecordThreads.keyAt(0));
154 }
155 while (!mPlaybackThreads.isEmpty()) {
156 // closeOutput() will remove first entry from mPlaybackThreads
157 closeOutput(mPlaybackThreads.keyAt(0));
158 }
159 if (mAudioHardware) {
160 delete mAudioHardware;
161 }
The Android Open Source Project27629322009-01-09 17:51:23 -0800162}
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800163
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700164
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700165
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700166status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args)
167{
168 const size_t SIZE = 256;
169 char buffer[SIZE];
170 String8 result;
171
172 result.append("Clients:\n");
173 for (size_t i = 0; i < mClients.size(); ++i) {
174 wp<Client> wClient = mClients.valueAt(i);
175 if (wClient != 0) {
176 sp<Client> client = wClient.promote();
177 if (client != 0) {
178 snprintf(buffer, SIZE, " pid: %d\n", client->pid());
179 result.append(buffer);
180 }
181 }
182 }
183 write(fd, result.string(), result.size());
184 return NO_ERROR;
185}
186
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700187
188status_t AudioFlinger::dumpInternals(int fd, const Vector<String16>& args)
189{
190 const size_t SIZE = 256;
191 char buffer[SIZE];
192 String8 result;
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700193 int hardwareStatus = mHardwareStatus;
Eric Laurent9d91ad52009-07-17 12:17:14 -0700194
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700195 snprintf(buffer, SIZE, "Hardware status: %d\n", hardwareStatus);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700196 result.append(buffer);
197 write(fd, result.string(), result.size());
198 return NO_ERROR;
199}
200
201status_t AudioFlinger::dumpPermissionDenial(int fd, const Vector<String16>& args)
202{
203 const size_t SIZE = 256;
204 char buffer[SIZE];
205 String8 result;
206 snprintf(buffer, SIZE, "Permission Denial: "
207 "can't dump AudioFlinger from pid=%d, uid=%d\n",
208 IPCThreadState::self()->getCallingPid(),
209 IPCThreadState::self()->getCallingUid());
210 result.append(buffer);
211 write(fd, result.string(), result.size());
212 return NO_ERROR;
213}
214
The Android Open Source Project4f68be12009-03-18 17:39:46 -0700215static bool tryLock(Mutex& mutex)
216{
217 bool locked = false;
218 for (int i = 0; i < kDumpLockRetries; ++i) {
219 if (mutex.tryLock() == NO_ERROR) {
220 locked = true;
221 break;
222 }
223 usleep(kDumpLockSleep);
224 }
225 return locked;
226}
227
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700228status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
229{
230 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
231 dumpPermissionDenial(fd, args);
232 } else {
The Android Open Source Project4f68be12009-03-18 17:39:46 -0700233 // get state of hardware lock
234 bool hardwareLocked = tryLock(mHardwareLock);
235 if (!hardwareLocked) {
236 String8 result(kHardwareLockedString);
237 write(fd, result.string(), result.size());
238 } else {
239 mHardwareLock.unlock();
240 }
241
242 bool locked = tryLock(mLock);
243
244 // failed to lock - AudioFlinger is probably deadlocked
245 if (!locked) {
246 String8 result(kDeadlockedString);
247 write(fd, result.string(), result.size());
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700248 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700249
250 dumpClients(fd, args);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700251 dumpInternals(fd, args);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800252
Eric Laurent9d91ad52009-07-17 12:17:14 -0700253 // dump playback threads
254 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700255 mPlaybackThreads.valueAt(i)->dump(fd, args);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700256 }
257
258 // dump record threads
Eric Laurentfd558a92009-07-23 13:35:01 -0700259 for (size_t i = 0; i < mRecordThreads.size(); i++) {
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700260 mRecordThreads.valueAt(i)->dump(fd, args);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700261 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800262
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700263 if (mAudioHardware) {
264 mAudioHardware->dumpState(fd, args);
265 }
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700266 if (locked) mLock.unlock();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700267 }
268 return NO_ERROR;
269}
270
Eric Laurent9d91ad52009-07-17 12:17:14 -0700271
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700272// IAudioFlinger interface
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800273
274
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700275sp<IAudioTrack> AudioFlinger::createTrack(
276 pid_t pid,
277 int streamType,
278 uint32_t sampleRate,
279 int format,
280 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800281 int frameCount,
282 uint32_t flags,
283 const sp<IMemory>& sharedBuffer,
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700284 int output,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800285 status_t *status)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700286{
Eric Laurent9d91ad52009-07-17 12:17:14 -0700287 sp<PlaybackThread::Track> track;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700288 sp<TrackHandle> trackHandle;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700289 sp<Client> client;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800290 wp<Client> wclient;
291 status_t lStatus;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700292
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800293 if (streamType >= AudioSystem::NUM_STREAM_TYPES) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800294 LOGE("invalid stream type");
295 lStatus = BAD_VALUE;
296 goto Exit;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700297 }
298
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800299 {
300 Mutex::Autolock _l(mLock);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700301 PlaybackThread *thread = checkPlaybackThread_l(output);
302 if (thread == NULL) {
303 LOGE("unknown output thread");
304 lStatus = BAD_VALUE;
305 goto Exit;
306 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800307
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800308 wclient = mClients.valueFor(pid);
309
310 if (wclient != NULL) {
311 client = wclient.promote();
312 } else {
313 client = new Client(this, pid);
314 mClients.add(pid, client);
315 }
Eric Laurent9d91ad52009-07-17 12:17:14 -0700316 track = thread->createTrack_l(client, streamType, sampleRate, format,
317 channelCount, frameCount, sharedBuffer, &lStatus);
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700318 }
319 if (lStatus == NO_ERROR) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800320 trackHandle = new TrackHandle(track);
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700321 } else {
Eric Laurent0f8ab672009-09-17 05:12:56 -0700322 // remove local strong reference to Client before deleting the Track so that the Client
323 // destructor is called by the TrackBase destructor with mLock held
324 client.clear();
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700325 track.clear();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800326 }
327
328Exit:
329 if(status) {
330 *status = lStatus;
331 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700332 return trackHandle;
333}
334
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700335uint32_t AudioFlinger::sampleRate(int output) const
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700336{
Eric Laurent9d91ad52009-07-17 12:17:14 -0700337 Mutex::Autolock _l(mLock);
338 PlaybackThread *thread = checkPlaybackThread_l(output);
339 if (thread == NULL) {
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700340 LOGW("sampleRate() unknown thread %d", output);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700341 return 0;
342 }
343 return thread->sampleRate();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700344}
345
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700346int AudioFlinger::channelCount(int output) const
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700347{
Eric Laurent9d91ad52009-07-17 12:17:14 -0700348 Mutex::Autolock _l(mLock);
349 PlaybackThread *thread = checkPlaybackThread_l(output);
350 if (thread == NULL) {
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700351 LOGW("channelCount() unknown thread %d", output);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700352 return 0;
353 }
354 return thread->channelCount();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700355}
356
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700357int AudioFlinger::format(int output) const
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700358{
Eric Laurent9d91ad52009-07-17 12:17:14 -0700359 Mutex::Autolock _l(mLock);
360 PlaybackThread *thread = checkPlaybackThread_l(output);
361 if (thread == NULL) {
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700362 LOGW("format() unknown thread %d", output);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700363 return 0;
364 }
365 return thread->format();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700366}
367
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700368size_t AudioFlinger::frameCount(int output) const
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700369{
Eric Laurent9d91ad52009-07-17 12:17:14 -0700370 Mutex::Autolock _l(mLock);
371 PlaybackThread *thread = checkPlaybackThread_l(output);
372 if (thread == NULL) {
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700373 LOGW("frameCount() unknown thread %d", output);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700374 return 0;
375 }
376 return thread->frameCount();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700377}
378
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700379uint32_t AudioFlinger::latency(int output) const
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800380{
Eric Laurent9d91ad52009-07-17 12:17:14 -0700381 Mutex::Autolock _l(mLock);
382 PlaybackThread *thread = checkPlaybackThread_l(output);
383 if (thread == NULL) {
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700384 LOGW("latency() unknown thread %d", output);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700385 return 0;
386 }
387 return thread->latency();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800388}
389
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700390status_t AudioFlinger::setMasterVolume(float value)
391{
392 // check calling permissions
393 if (!settingsAllowed()) {
394 return PERMISSION_DENIED;
395 }
396
397 // when hw supports master volume, don't scale in sw mixer
398 AutoMutex lock(mHardwareLock);
399 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
400 if (mAudioHardware->setMasterVolume(value) == NO_ERROR) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800401 value = 1.0f;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700402 }
403 mHardwareStatus = AUDIO_HW_IDLE;
Eric Laurent9d91ad52009-07-17 12:17:14 -0700404
405 mMasterVolume = value;
406 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700407 mPlaybackThreads.valueAt(i)->setMasterVolume(value);
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700408
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700409 return NO_ERROR;
410}
411
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700412status_t AudioFlinger::setMode(int mode)
413{
414 // check calling permissions
415 if (!settingsAllowed()) {
416 return PERMISSION_DENIED;
417 }
418 if ((mode < 0) || (mode >= AudioSystem::NUM_MODES)) {
419 LOGW("Illegal value: setMode(%d)", mode);
420 return BAD_VALUE;
421 }
422
423 AutoMutex lock(mHardwareLock);
424 mHardwareStatus = AUDIO_HW_SET_MODE;
425 status_t ret = mAudioHardware->setMode(mode);
Glenn Kastend5ea9692010-03-05 12:18:01 -0800426#ifdef LVMX
427 if (NO_ERROR == ret) {
428 LifeVibes::setMode(mode);
429 }
430#endif
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700431 mHardwareStatus = AUDIO_HW_IDLE;
432 return ret;
433}
434
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700435status_t AudioFlinger::setMicMute(bool state)
436{
437 // check calling permissions
438 if (!settingsAllowed()) {
439 return PERMISSION_DENIED;
440 }
441
442 AutoMutex lock(mHardwareLock);
443 mHardwareStatus = AUDIO_HW_SET_MIC_MUTE;
444 status_t ret = mAudioHardware->setMicMute(state);
445 mHardwareStatus = AUDIO_HW_IDLE;
446 return ret;
447}
448
449bool AudioFlinger::getMicMute() const
450{
451 bool state = AudioSystem::MODE_INVALID;
452 mHardwareStatus = AUDIO_HW_GET_MIC_MUTE;
453 mAudioHardware->getMicMute(&state);
454 mHardwareStatus = AUDIO_HW_IDLE;
455 return state;
456}
457
458status_t AudioFlinger::setMasterMute(bool muted)
459{
460 // check calling permissions
461 if (!settingsAllowed()) {
462 return PERMISSION_DENIED;
463 }
Eric Laurent9d91ad52009-07-17 12:17:14 -0700464
465 mMasterMute = muted;
466 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700467 mPlaybackThreads.valueAt(i)->setMasterMute(muted);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700468
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700469 return NO_ERROR;
470}
471
472float AudioFlinger::masterVolume() const
473{
Eric Laurent9d91ad52009-07-17 12:17:14 -0700474 return mMasterVolume;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700475}
476
477bool AudioFlinger::masterMute() const
478{
Eric Laurent9d91ad52009-07-17 12:17:14 -0700479 return mMasterMute;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700480}
481
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700482status_t AudioFlinger::setStreamVolume(int stream, float value, int output)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700483{
484 // check calling permissions
485 if (!settingsAllowed()) {
486 return PERMISSION_DENIED;
487 }
488
Eric Laurent9d91ad52009-07-17 12:17:14 -0700489 if (stream < 0 || uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700490 return BAD_VALUE;
491 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800492
Eric Laurent9d91ad52009-07-17 12:17:14 -0700493 AutoMutex lock(mLock);
494 PlaybackThread *thread = NULL;
495 if (output) {
496 thread = checkPlaybackThread_l(output);
497 if (thread == NULL) {
498 return BAD_VALUE;
499 }
500 }
501
Eric Laurent9d91ad52009-07-17 12:17:14 -0700502 mStreamTypes[stream].volume = value;
503
504 if (thread == NULL) {
Eric Laurent63da2b62009-10-21 08:14:22 -0700505 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700506 mPlaybackThreads.valueAt(i)->setStreamVolume(stream, value);
Eric Laurent63da2b62009-10-21 08:14:22 -0700507 }
Eric Laurent9d91ad52009-07-17 12:17:14 -0700508 } else {
509 thread->setStreamVolume(stream, value);
510 }
Eric Laurent4dd495b2009-04-21 07:56:33 -0700511
Eric Laurent63da2b62009-10-21 08:14:22 -0700512 return NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700513}
514
515status_t AudioFlinger::setStreamMute(int stream, bool muted)
516{
517 // check calling permissions
518 if (!settingsAllowed()) {
519 return PERMISSION_DENIED;
520 }
521
Eric Laurent9d91ad52009-07-17 12:17:14 -0700522 if (stream < 0 || uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES ||
Eric Laurentb1596ee2009-03-26 01:57:59 -0700523 uint32_t(stream) == AudioSystem::ENFORCED_AUDIBLE) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700524 return BAD_VALUE;
525 }
The Android Open Source Project4f68be12009-03-18 17:39:46 -0700526
Eric Laurent9d91ad52009-07-17 12:17:14 -0700527 mStreamTypes[stream].mute = muted;
528 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700529 mPlaybackThreads.valueAt(i)->setStreamMute(stream, muted);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800530
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700531 return NO_ERROR;
532}
533
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700534float AudioFlinger::streamVolume(int stream, int output) const
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700535{
Eric Laurent9d91ad52009-07-17 12:17:14 -0700536 if (stream < 0 || uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700537 return 0.0f;
538 }
Eric Laurent9d91ad52009-07-17 12:17:14 -0700539
540 AutoMutex lock(mLock);
541 float volume;
542 if (output) {
543 PlaybackThread *thread = checkPlaybackThread_l(output);
544 if (thread == NULL) {
545 return 0.0f;
546 }
547 volume = thread->streamVolume(stream);
548 } else {
549 volume = mStreamTypes[stream].volume;
550 }
551
Eric Laurent4dd495b2009-04-21 07:56:33 -0700552 return volume;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700553}
554
555bool AudioFlinger::streamMute(int stream) const
556{
Eric Laurent9d91ad52009-07-17 12:17:14 -0700557 if (stream < 0 || stream >= (int)AudioSystem::NUM_STREAM_TYPES) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700558 return true;
559 }
Eric Laurent9d91ad52009-07-17 12:17:14 -0700560
561 return mStreamTypes[stream].mute;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700562}
563
Eric Laurent43c0b0a2010-01-25 08:49:09 -0800564bool AudioFlinger::isStreamActive(int stream) const
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700565{
Eric Laurentb025ca02009-07-09 03:20:57 -0700566 Mutex::Autolock _l(mLock);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700567 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurent43c0b0a2010-01-25 08:49:09 -0800568 if (mPlaybackThreads.valueAt(i)->isStreamActive(stream)) {
Eric Laurent9d91ad52009-07-17 12:17:14 -0700569 return true;
570 }
571 }
572 return false;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700573}
574
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700575status_t AudioFlinger::setParameters(int ioHandle, const String8& keyValuePairs)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700576{
Eric Laurent9d91ad52009-07-17 12:17:14 -0700577 status_t result;
578
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700579 LOGV("setParameters(): io %d, keyvalue %s, tid %d, calling tid %d",
Eric Laurent9d91ad52009-07-17 12:17:14 -0700580 ioHandle, keyValuePairs.string(), gettid(), IPCThreadState::self()->getCallingPid());
581 // check calling permissions
582 if (!settingsAllowed()) {
583 return PERMISSION_DENIED;
The Android Open Source Project8a7a6752009-01-15 16:12:10 -0800584 }
Eric Laurent9d91ad52009-07-17 12:17:14 -0700585
Glenn Kastend5ea9692010-03-05 12:18:01 -0800586#ifdef LVMX
587 AudioParameter param = AudioParameter(keyValuePairs);
588 LifeVibes::setParameters(ioHandle,keyValuePairs);
589 String8 key = String8(AudioParameter::keyRouting);
590 int device;
591 if (NO_ERROR != param.getInt(key, device)) {
592 device = -1;
593 }
594
595 key = String8(LifevibesTag);
596 String8 value;
597 int musicEnabled = -1;
598 if (NO_ERROR == param.get(key, value)) {
599 if (value == LifevibesEnable) {
Eric Laurentd878cd82010-05-12 02:05:53 -0700600 mLifeVibesClientPid = IPCThreadState::self()->getCallingPid();
Glenn Kastend5ea9692010-03-05 12:18:01 -0800601 musicEnabled = 1;
602 } else if (value == LifevibesDisable) {
Eric Laurentd878cd82010-05-12 02:05:53 -0700603 mLifeVibesClientPid = -1;
Glenn Kastend5ea9692010-03-05 12:18:01 -0800604 musicEnabled = 0;
605 }
606 }
607#endif
608
Eric Laurent9d91ad52009-07-17 12:17:14 -0700609 // ioHandle == 0 means the parameters are global to the audio hardware interface
610 if (ioHandle == 0) {
611 AutoMutex lock(mHardwareLock);
612 mHardwareStatus = AUDIO_SET_PARAMETER;
613 result = mAudioHardware->setParameters(keyValuePairs);
Glenn Kastend5ea9692010-03-05 12:18:01 -0800614#ifdef LVMX
Eric Laurentd878cd82010-05-12 02:05:53 -0700615 if (musicEnabled != -1) {
Glenn Kastend5ea9692010-03-05 12:18:01 -0800616 LifeVibes::enableMusic((bool) musicEnabled);
617 }
618#endif
Eric Laurent9d91ad52009-07-17 12:17:14 -0700619 mHardwareStatus = AUDIO_HW_IDLE;
620 return result;
621 }
622
Eric Laurent2d70c802009-09-29 11:12:57 -0700623 // hold a strong ref on thread in case closeOutput() or closeInput() is called
624 // and the thread is exited once the lock is released
625 sp<ThreadBase> thread;
626 {
627 Mutex::Autolock _l(mLock);
628 thread = checkPlaybackThread_l(ioHandle);
629 if (thread == NULL) {
630 thread = checkRecordThread_l(ioHandle);
631 }
Eric Laurent9d91ad52009-07-17 12:17:14 -0700632 }
Eric Laurent2d70c802009-09-29 11:12:57 -0700633 if (thread != NULL) {
Glenn Kastend5ea9692010-03-05 12:18:01 -0800634 result = thread->setParameters(keyValuePairs);
635#ifdef LVMX
636 if ((NO_ERROR == result) && (device != -1)) {
637 LifeVibes::setDevice(LifeVibes::threadIdToAudioOutputType(thread->id()), device);
638 }
639#endif
640 return result;
Eric Laurent9d91ad52009-07-17 12:17:14 -0700641 }
Eric Laurent9d91ad52009-07-17 12:17:14 -0700642 return BAD_VALUE;
643}
644
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700645String8 AudioFlinger::getParameters(int ioHandle, const String8& keys)
Eric Laurent9d91ad52009-07-17 12:17:14 -0700646{
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700647// LOGV("getParameters() io %d, keys %s, tid %d, calling tid %d",
Eric Laurent9d91ad52009-07-17 12:17:14 -0700648// ioHandle, keys.string(), gettid(), IPCThreadState::self()->getCallingPid());
649
650 if (ioHandle == 0) {
651 return mAudioHardware->getParameters(keys);
652 }
Eric Laurent2d70c802009-09-29 11:12:57 -0700653
654 Mutex::Autolock _l(mLock);
655
Eric Laurent9d91ad52009-07-17 12:17:14 -0700656 PlaybackThread *playbackThread = checkPlaybackThread_l(ioHandle);
657 if (playbackThread != NULL) {
658 return playbackThread->getParameters(keys);
659 }
660 RecordThread *recordThread = checkRecordThread_l(ioHandle);
661 if (recordThread != NULL) {
662 return recordThread->getParameters(keys);
663 }
664 return String8("");
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700665}
666
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800667size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
668{
669 return mAudioHardware->getInputBufferSize(sampleRate, format, channelCount);
670}
671
Eric Laurent134ccbd2010-02-26 02:47:27 -0800672unsigned int AudioFlinger::getInputFramesLost(int ioHandle)
673{
674 if (ioHandle == 0) {
675 return 0;
676 }
677
678 Mutex::Autolock _l(mLock);
679
680 RecordThread *recordThread = checkRecordThread_l(ioHandle);
681 if (recordThread != NULL) {
682 return recordThread->getInputFramesLost();
683 }
684 return 0;
685}
686
Eric Laurent63da2b62009-10-21 08:14:22 -0700687status_t AudioFlinger::setVoiceVolume(float value)
688{
689 // check calling permissions
690 if (!settingsAllowed()) {
691 return PERMISSION_DENIED;
692 }
693
694 AutoMutex lock(mHardwareLock);
695 mHardwareStatus = AUDIO_SET_VOICE_VOLUME;
696 status_t ret = mAudioHardware->setVoiceVolume(value);
697 mHardwareStatus = AUDIO_HW_IDLE;
698
699 return ret;
700}
701
Eric Laurente9ed2722010-01-19 17:37:09 -0800702status_t AudioFlinger::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int output)
703{
704 status_t status;
705
706 Mutex::Autolock _l(mLock);
707
708 PlaybackThread *playbackThread = checkPlaybackThread_l(output);
709 if (playbackThread != NULL) {
710 return playbackThread->getRenderPosition(halFrames, dspFrames);
711 }
712
713 return BAD_VALUE;
714}
715
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800716void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
717{
Eric Laurent9d91ad52009-07-17 12:17:14 -0700718
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800719 Mutex::Autolock _l(mLock);
720
Eric Laurentd878cd82010-05-12 02:05:53 -0700721 int pid = IPCThreadState::self()->getCallingPid();
722 if (mNotificationClients.indexOfKey(pid) < 0) {
723 sp<NotificationClient> notificationClient = new NotificationClient(this,
724 client,
725 pid);
726 LOGV("registerClient() client %p, pid %d", notificationClient.get(), pid);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700727
Eric Laurentd878cd82010-05-12 02:05:53 -0700728 mNotificationClients.add(pid, notificationClient);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700729
Eric Laurentd878cd82010-05-12 02:05:53 -0700730 sp<IBinder> binder = client->asBinder();
731 binder->linkToDeath(notificationClient);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800732
Eric Laurentd878cd82010-05-12 02:05:53 -0700733 // the config change is always sent from playback or record threads to avoid deadlock
734 // with AudioSystem::gLock
735 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
736 mPlaybackThreads.valueAt(i)->sendConfigEvent(AudioSystem::OUTPUT_OPENED);
737 }
Eric Laurent9d91ad52009-07-17 12:17:14 -0700738
Eric Laurentd878cd82010-05-12 02:05:53 -0700739 for (size_t i = 0; i < mRecordThreads.size(); i++) {
740 mRecordThreads.valueAt(i)->sendConfigEvent(AudioSystem::INPUT_OPENED);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800741 }
742 }
743}
744
Eric Laurentd878cd82010-05-12 02:05:53 -0700745void AudioFlinger::removeNotificationClient(pid_t pid)
746{
747 Mutex::Autolock _l(mLock);
748
749 int index = mNotificationClients.indexOfKey(pid);
750 if (index >= 0) {
751 sp <NotificationClient> client = mNotificationClients.valueFor(pid);
752 LOGV("removeNotificationClient() %p, pid %d", client.get(), pid);
753#ifdef LVMX
754 if (pid == mLifeVibesClientPid) {
755 LOGV("Disabling lifevibes");
756 LifeVibes::enableMusic(false);
757 mLifeVibesClientPid = -1;
758 }
759#endif
760 mNotificationClients.removeItem(pid);
761 }
762}
763
Eric Laurentb3687ae2009-09-15 07:10:12 -0700764// audioConfigChanged_l() must be called with AudioFlinger::mLock held
Eric Laurentd878cd82010-05-12 02:05:53 -0700765void AudioFlinger::audioConfigChanged_l(int event, int ioHandle, void *param2)
766{
Eric Laurent09b4ba82009-11-19 09:00:56 -0800767 size_t size = mNotificationClients.size();
768 for (size_t i = 0; i < size; i++) {
Eric Laurentd878cd82010-05-12 02:05:53 -0700769 mNotificationClients.valueAt(i)->client()->ioConfigChanged(event, ioHandle, param2);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700770 }
771}
772
Eric Laurent0f8ab672009-09-17 05:12:56 -0700773// removeClient_l() must be called with AudioFlinger::mLock held
774void AudioFlinger::removeClient_l(pid_t pid)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700775{
Eric Laurent0f8ab672009-09-17 05:12:56 -0700776 LOGV("removeClient_l() pid %d, tid %d, calling tid %d", pid, gettid(), IPCThreadState::self()->getCallingPid());
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700777 mClients.removeItem(pid);
778}
779
Eric Laurentd878cd82010-05-12 02:05:53 -0700780
Eric Laurent9d91ad52009-07-17 12:17:14 -0700781// ----------------------------------------------------------------------------
782
Eric Laurent09b4ba82009-11-19 09:00:56 -0800783AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, int id)
Eric Laurent9d91ad52009-07-17 12:17:14 -0700784 : Thread(false),
785 mAudioFlinger(audioFlinger), mSampleRate(0), mFrameCount(0), mChannelCount(0),
Eric Laurente1512162010-05-14 05:45:46 -0700786 mFrameSize(1), mFormat(0), mStandby(false), mId(id), mExiting(false)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700787{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800788}
789
Eric Laurent9d91ad52009-07-17 12:17:14 -0700790AudioFlinger::ThreadBase::~ThreadBase()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800791{
Eric Laurent3464c012009-08-04 09:45:33 -0700792 mParamCond.broadcast();
793 mNewParameters.clear();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800794}
795
Eric Laurent9d91ad52009-07-17 12:17:14 -0700796void AudioFlinger::ThreadBase::exit()
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700797{
Eric Laurent2d70c802009-09-29 11:12:57 -0700798 // keep a strong ref on ourself so that we wont get
Eric Laurent9d91ad52009-07-17 12:17:14 -0700799 // destroyed in the middle of requestExitAndWait()
800 sp <ThreadBase> strongMe = this;
801
802 LOGV("ThreadBase::exit");
803 {
804 AutoMutex lock(&mLock);
Eric Laurent09b4ba82009-11-19 09:00:56 -0800805 mExiting = true;
Eric Laurent9d91ad52009-07-17 12:17:14 -0700806 requestExit();
807 mWaitWorkCV.signal();
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700808 }
Eric Laurent9d91ad52009-07-17 12:17:14 -0700809 requestExitAndWait();
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700810}
Eric Laurent9d91ad52009-07-17 12:17:14 -0700811
812uint32_t AudioFlinger::ThreadBase::sampleRate() const
813{
814 return mSampleRate;
815}
816
817int AudioFlinger::ThreadBase::channelCount() const
818{
Eric Laurente1512162010-05-14 05:45:46 -0700819 return (int)mChannelCount;
Eric Laurent9d91ad52009-07-17 12:17:14 -0700820}
821
822int AudioFlinger::ThreadBase::format() const
823{
824 return mFormat;
825}
826
827size_t AudioFlinger::ThreadBase::frameCount() const
828{
829 return mFrameCount;
830}
831
832status_t AudioFlinger::ThreadBase::setParameters(const String8& keyValuePairs)
833{
Eric Laurent3464c012009-08-04 09:45:33 -0700834 status_t status;
Eric Laurent9d91ad52009-07-17 12:17:14 -0700835
Eric Laurent3464c012009-08-04 09:45:33 -0700836 LOGV("ThreadBase::setParameters() %s", keyValuePairs.string());
Eric Laurent9d91ad52009-07-17 12:17:14 -0700837 Mutex::Autolock _l(mLock);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700838
Eric Laurent3464c012009-08-04 09:45:33 -0700839 mNewParameters.add(keyValuePairs);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700840 mWaitWorkCV.signal();
Eric Laurent2d70c802009-09-29 11:12:57 -0700841 // wait condition with timeout in case the thread loop has exited
842 // before the request could be processed
843 if (mParamCond.waitRelative(mLock, seconds(2)) == NO_ERROR) {
844 status = mParamStatus;
845 mWaitWorkCV.signal();
846 } else {
847 status = TIMED_OUT;
848 }
Eric Laurent3464c012009-08-04 09:45:33 -0700849 return status;
Eric Laurent9d91ad52009-07-17 12:17:14 -0700850}
851
852void AudioFlinger::ThreadBase::sendConfigEvent(int event, int param)
853{
854 Mutex::Autolock _l(mLock);
Eric Laurent3464c012009-08-04 09:45:33 -0700855 sendConfigEvent_l(event, param);
856}
857
858// sendConfigEvent_l() must be called with ThreadBase::mLock held
859void AudioFlinger::ThreadBase::sendConfigEvent_l(int event, int param)
860{
Eric Laurent9d91ad52009-07-17 12:17:14 -0700861 ConfigEvent *configEvent = new ConfigEvent();
862 configEvent->mEvent = event;
863 configEvent->mParam = param;
864 mConfigEvents.add(configEvent);
865 LOGV("sendConfigEvent() num events %d event %d, param %d", mConfigEvents.size(), event, param);
866 mWaitWorkCV.signal();
867}
868
869void AudioFlinger::ThreadBase::processConfigEvents()
870{
871 mLock.lock();
872 while(!mConfigEvents.isEmpty()) {
873 LOGV("processConfigEvents() remaining events %d", mConfigEvents.size());
874 ConfigEvent *configEvent = mConfigEvents[0];
875 mConfigEvents.removeAt(0);
Eric Laurentb3687ae2009-09-15 07:10:12 -0700876 // release mLock because audioConfigChanged() will lock AudioFlinger mLock
877 // before calling Audioflinger::audioConfigChanged_l() thus creating
Eric Laurent9d91ad52009-07-17 12:17:14 -0700878 // potential cross deadlock between AudioFlinger::mLock and mLock
879 mLock.unlock();
880 audioConfigChanged(configEvent->mEvent, configEvent->mParam);
881 delete configEvent;
882 mLock.lock();
883 }
884 mLock.unlock();
885}
886
Eric Laurentee47d432009-11-07 00:01:32 -0800887status_t AudioFlinger::ThreadBase::dumpBase(int fd, const Vector<String16>& args)
888{
889 const size_t SIZE = 256;
890 char buffer[SIZE];
891 String8 result;
892
893 bool locked = tryLock(mLock);
894 if (!locked) {
895 snprintf(buffer, SIZE, "thread %p maybe dead locked\n", this);
896 write(fd, buffer, strlen(buffer));
897 }
898
899 snprintf(buffer, SIZE, "standby: %d\n", mStandby);
900 result.append(buffer);
901 snprintf(buffer, SIZE, "Sample rate: %d\n", mSampleRate);
902 result.append(buffer);
903 snprintf(buffer, SIZE, "Frame count: %d\n", mFrameCount);
904 result.append(buffer);
905 snprintf(buffer, SIZE, "Channel Count: %d\n", mChannelCount);
906 result.append(buffer);
907 snprintf(buffer, SIZE, "Format: %d\n", mFormat);
908 result.append(buffer);
909 snprintf(buffer, SIZE, "Frame size: %d\n", mFrameSize);
910 result.append(buffer);
911
912 snprintf(buffer, SIZE, "\nPending setParameters commands: \n");
913 result.append(buffer);
914 result.append(" Index Command");
915 for (size_t i = 0; i < mNewParameters.size(); ++i) {
916 snprintf(buffer, SIZE, "\n %02d ", i);
917 result.append(buffer);
918 result.append(mNewParameters[i]);
919 }
920
921 snprintf(buffer, SIZE, "\n\nPending config events: \n");
922 result.append(buffer);
923 snprintf(buffer, SIZE, " Index event param\n");
924 result.append(buffer);
925 for (size_t i = 0; i < mConfigEvents.size(); i++) {
926 snprintf(buffer, SIZE, " %02d %02d %d\n", i, mConfigEvents[i]->mEvent, mConfigEvents[i]->mParam);
927 result.append(buffer);
928 }
929 result.append("\n");
930
931 write(fd, result.string(), result.size());
932
933 if (locked) {
934 mLock.unlock();
935 }
936 return NO_ERROR;
937}
938
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800939
940// ----------------------------------------------------------------------------
941
Eric Laurent09b4ba82009-11-19 09:00:56 -0800942AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id)
943 : ThreadBase(audioFlinger, id),
Eric Laurentf9df2492009-08-06 08:49:39 -0700944 mMixBuffer(0), mSuspended(0), mBytesWritten(0), mOutput(output),
Eric Laurent9395d9b2009-07-23 13:17:39 -0700945 mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800946{
Eric Laurent9d91ad52009-07-17 12:17:14 -0700947 readOutputParameters();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800948
Eric Laurent9d91ad52009-07-17 12:17:14 -0700949 mMasterVolume = mAudioFlinger->masterVolume();
950 mMasterMute = mAudioFlinger->masterMute();
951
952 for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
953 mStreamTypes[stream].volume = mAudioFlinger->streamVolumeInternal(stream);
954 mStreamTypes[stream].mute = mAudioFlinger->streamMute(stream);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800955 }
Eric Laurent9d91ad52009-07-17 12:17:14 -0700956 // notify client processes that a new input has been opened
957 sendConfigEvent(AudioSystem::OUTPUT_OPENED);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800958}
959
Eric Laurent9d91ad52009-07-17 12:17:14 -0700960AudioFlinger::PlaybackThread::~PlaybackThread()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800961{
962 delete [] mMixBuffer;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800963}
964
Eric Laurent9d91ad52009-07-17 12:17:14 -0700965status_t AudioFlinger::PlaybackThread::dump(int fd, const Vector<String16>& args)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800966{
967 dumpInternals(fd, args);
968 dumpTracks(fd, args);
969 return NO_ERROR;
970}
971
Eric Laurent9d91ad52009-07-17 12:17:14 -0700972status_t AudioFlinger::PlaybackThread::dumpTracks(int fd, const Vector<String16>& args)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800973{
974 const size_t SIZE = 256;
975 char buffer[SIZE];
976 String8 result;
977
Eric Laurent9d91ad52009-07-17 12:17:14 -0700978 snprintf(buffer, SIZE, "Output thread %p tracks\n", this);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800979 result.append(buffer);
Eric Laurentee47d432009-11-07 00:01:32 -0800980 result.append(" Name Clien Typ Fmt Chn Buf S M F SRate LeftV RighV Serv User\n");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800981 for (size_t i = 0; i < mTracks.size(); ++i) {
Eric Laurentc828f6a2009-03-31 14:34:35 -0700982 sp<Track> track = mTracks[i];
983 if (track != 0) {
984 track->dump(buffer, SIZE);
985 result.append(buffer);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800986 }
987 }
988
Eric Laurent9d91ad52009-07-17 12:17:14 -0700989 snprintf(buffer, SIZE, "Output thread %p active tracks\n", this);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800990 result.append(buffer);
Eric Laurentee47d432009-11-07 00:01:32 -0800991 result.append(" Name Clien Typ Fmt Chn Buf S M F SRate LeftV RighV Serv User\n");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800992 for (size_t i = 0; i < mActiveTracks.size(); ++i) {
Eric Laurentc828f6a2009-03-31 14:34:35 -0700993 wp<Track> wTrack = mActiveTracks[i];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800994 if (wTrack != 0) {
995 sp<Track> track = wTrack.promote();
996 if (track != 0) {
997 track->dump(buffer, SIZE);
998 result.append(buffer);
999 }
1000 }
1001 }
1002 write(fd, result.string(), result.size());
1003 return NO_ERROR;
1004}
1005
Eric Laurent9d91ad52009-07-17 12:17:14 -07001006status_t AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String16>& args)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001007{
1008 const size_t SIZE = 256;
1009 char buffer[SIZE];
1010 String8 result;
1011
Eric Laurentee47d432009-11-07 00:01:32 -08001012 snprintf(buffer, SIZE, "\nOutput thread %p internals\n", this);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001013 result.append(buffer);
1014 snprintf(buffer, SIZE, "last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime));
1015 result.append(buffer);
1016 snprintf(buffer, SIZE, "total writes: %d\n", mNumWrites);
1017 result.append(buffer);
1018 snprintf(buffer, SIZE, "delayed writes: %d\n", mNumDelayedWrites);
1019 result.append(buffer);
1020 snprintf(buffer, SIZE, "blocked in write: %d\n", mInWrite);
1021 result.append(buffer);
Eric Laurent7e2aad12009-12-18 05:47:48 -08001022 snprintf(buffer, SIZE, "suspend count: %d\n", mSuspended);
1023 result.append(buffer);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001024 write(fd, result.string(), result.size());
Eric Laurentee47d432009-11-07 00:01:32 -08001025
1026 dumpBase(fd, args);
1027
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001028 return NO_ERROR;
1029}
1030
1031// Thread virtuals
Eric Laurent9d91ad52009-07-17 12:17:14 -07001032status_t AudioFlinger::PlaybackThread::readyToRun()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001033{
1034 if (mSampleRate == 0) {
1035 LOGE("No working audio driver found.");
1036 return NO_INIT;
1037 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07001038 LOGI("AudioFlinger's thread %p ready to run", this);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001039 return NO_ERROR;
1040}
1041
Eric Laurent9d91ad52009-07-17 12:17:14 -07001042void AudioFlinger::PlaybackThread::onFirstRef()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001043{
1044 const size_t SIZE = 256;
1045 char buffer[SIZE];
1046
Eric Laurent9d91ad52009-07-17 12:17:14 -07001047 snprintf(buffer, SIZE, "Playback Thread %p", this);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001048
1049 run(buffer, ANDROID_PRIORITY_URGENT_AUDIO);
1050}
1051
Eric Laurent9d91ad52009-07-17 12:17:14 -07001052// PlaybackThread::createTrack_l() must be called with AudioFlinger::mLock held
1053sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrack_l(
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001054 const sp<AudioFlinger::Client>& client,
1055 int streamType,
1056 uint32_t sampleRate,
1057 int format,
1058 int channelCount,
1059 int frameCount,
1060 const sp<IMemory>& sharedBuffer,
1061 status_t *status)
1062{
1063 sp<Track> track;
1064 status_t lStatus;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001065
1066 if (mType == DIRECT) {
Eric Laurente1512162010-05-14 05:45:46 -07001067 if (sampleRate != mSampleRate || format != mFormat || channelCount != (int)mChannelCount) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07001068 LOGE("createTrack_l() Bad parameter: sampleRate %d format %d, channelCount %d for output %p",
1069 sampleRate, format, channelCount, mOutput);
1070 lStatus = BAD_VALUE;
1071 goto Exit;
1072 }
1073 } else {
1074 // Resampler implementation limits input sampling rate to 2 x output sampling rate.
1075 if (sampleRate > mSampleRate*2) {
1076 LOGE("Sample rate out of range: %d mSampleRate %d", sampleRate, mSampleRate);
1077 lStatus = BAD_VALUE;
1078 goto Exit;
1079 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001080 }
1081
Eric Laurent9d91ad52009-07-17 12:17:14 -07001082 if (mOutput == 0) {
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001083 LOGE("Audio driver not initialized.");
1084 lStatus = NO_INIT;
1085 goto Exit;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001086 }
1087
Eric Laurent9d91ad52009-07-17 12:17:14 -07001088 { // scope for mLock
1089 Mutex::Autolock _l(mLock);
1090 track = new Track(this, client, streamType, sampleRate, format,
1091 channelCount, frameCount, sharedBuffer);
Eric Laurent7b570852009-11-09 04:45:39 -08001092 if (track->getCblk() == NULL || track->name() < 0) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07001093 lStatus = NO_MEMORY;
1094 goto Exit;
1095 }
1096 mTracks.add(track);
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001097 }
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001098 lStatus = NO_ERROR;
1099
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001100Exit:
1101 if(status) {
1102 *status = lStatus;
1103 }
1104 return track;
1105}
1106
Eric Laurent9d91ad52009-07-17 12:17:14 -07001107uint32_t AudioFlinger::PlaybackThread::latency() const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001108{
1109 if (mOutput) {
1110 return mOutput->latency();
1111 }
1112 else {
1113 return 0;
1114 }
1115}
1116
Eric Laurent9d91ad52009-07-17 12:17:14 -07001117status_t AudioFlinger::PlaybackThread::setMasterVolume(float value)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001118{
Glenn Kastend5ea9692010-03-05 12:18:01 -08001119#ifdef LVMX
1120 int audioOutputType = LifeVibes::getMixerType(mId, mType);
1121 if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) {
1122 LifeVibes::setMasterVolume(audioOutputType, value);
1123 }
1124#endif
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001125 mMasterVolume = value;
1126 return NO_ERROR;
1127}
1128
Eric Laurent9d91ad52009-07-17 12:17:14 -07001129status_t AudioFlinger::PlaybackThread::setMasterMute(bool muted)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001130{
Glenn Kastend5ea9692010-03-05 12:18:01 -08001131#ifdef LVMX
1132 int audioOutputType = LifeVibes::getMixerType(mId, mType);
1133 if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) {
1134 LifeVibes::setMasterMute(audioOutputType, muted);
1135 }
1136#endif
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001137 mMasterMute = muted;
1138 return NO_ERROR;
1139}
1140
Eric Laurent9d91ad52009-07-17 12:17:14 -07001141float AudioFlinger::PlaybackThread::masterVolume() const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001142{
1143 return mMasterVolume;
1144}
1145
Eric Laurent9d91ad52009-07-17 12:17:14 -07001146bool AudioFlinger::PlaybackThread::masterMute() const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001147{
1148 return mMasterMute;
1149}
1150
Eric Laurent9d91ad52009-07-17 12:17:14 -07001151status_t AudioFlinger::PlaybackThread::setStreamVolume(int stream, float value)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001152{
Glenn Kastend5ea9692010-03-05 12:18:01 -08001153#ifdef LVMX
1154 int audioOutputType = LifeVibes::getMixerType(mId, mType);
1155 if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) {
1156 LifeVibes::setStreamVolume(audioOutputType, stream, value);
1157 }
1158#endif
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001159 mStreamTypes[stream].volume = value;
1160 return NO_ERROR;
1161}
1162
Eric Laurent9d91ad52009-07-17 12:17:14 -07001163status_t AudioFlinger::PlaybackThread::setStreamMute(int stream, bool muted)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001164{
Glenn Kastend5ea9692010-03-05 12:18:01 -08001165#ifdef LVMX
1166 int audioOutputType = LifeVibes::getMixerType(mId, mType);
1167 if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) {
1168 LifeVibes::setStreamMute(audioOutputType, stream, muted);
1169 }
1170#endif
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001171 mStreamTypes[stream].mute = muted;
1172 return NO_ERROR;
1173}
1174
Eric Laurent9d91ad52009-07-17 12:17:14 -07001175float AudioFlinger::PlaybackThread::streamVolume(int stream) const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001176{
1177 return mStreamTypes[stream].volume;
1178}
1179
Eric Laurent9d91ad52009-07-17 12:17:14 -07001180bool AudioFlinger::PlaybackThread::streamMute(int stream) const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001181{
1182 return mStreamTypes[stream].mute;
1183}
1184
Eric Laurent43c0b0a2010-01-25 08:49:09 -08001185bool AudioFlinger::PlaybackThread::isStreamActive(int stream) const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001186{
Eric Laurent9d91ad52009-07-17 12:17:14 -07001187 Mutex::Autolock _l(mLock);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001188 size_t count = mActiveTracks.size();
1189 for (size_t i = 0 ; i < count ; ++i) {
1190 sp<Track> t = mActiveTracks[i].promote();
1191 if (t == 0) continue;
1192 Track* const track = t.get();
Eric Laurent43c0b0a2010-01-25 08:49:09 -08001193 if (t->type() == stream)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001194 return true;
1195 }
1196 return false;
1197}
1198
Eric Laurent9d91ad52009-07-17 12:17:14 -07001199// addTrack_l() must be called with ThreadBase::mLock held
1200status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001201{
1202 status_t status = ALREADY_EXISTS;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001203
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001204 // set retry count for buffer fill
1205 track->mRetryCount = kMaxTrackStartupRetries;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001206 if (mActiveTracks.indexOf(track) < 0) {
1207 // the track is newly added, make sure it fills up all its
1208 // buffers before playing. This is to ensure the client will
1209 // effectively get the latency it requested.
1210 track->mFillingUpStatus = Track::FS_FILLING;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001211 track->mResetDone = false;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001212 mActiveTracks.add(track);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001213 status = NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001214 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07001215
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001216 LOGV("mWaitWorkCV.broadcast");
Eric Laurent9d91ad52009-07-17 12:17:14 -07001217 mWaitWorkCV.broadcast();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001218
1219 return status;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001220}
1221
Eric Laurent9d91ad52009-07-17 12:17:14 -07001222// destroyTrack_l() must be called with ThreadBase::mLock held
1223void AudioFlinger::PlaybackThread::destroyTrack_l(const sp<Track>& track)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001224{
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001225 track->mState = TrackBase::TERMINATED;
1226 if (mActiveTracks.indexOf(track) < 0) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001227 mTracks.remove(track);
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001228 deleteTrackName_l(track->name());
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001229 }
1230}
1231
Eric Laurent9d91ad52009-07-17 12:17:14 -07001232String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys)
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001233{
Eric Laurent9d91ad52009-07-17 12:17:14 -07001234 return mOutput->getParameters(keys);
1235}
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001236
Eric Laurent9d91ad52009-07-17 12:17:14 -07001237void AudioFlinger::PlaybackThread::audioConfigChanged(int event, int param) {
1238 AudioSystem::OutputDescriptor desc;
1239 void *param2 = 0;
1240
1241 LOGV("PlaybackThread::audioConfigChanged, thread %p, event %d, param %d", this, event, param);
1242
1243 switch (event) {
1244 case AudioSystem::OUTPUT_OPENED:
1245 case AudioSystem::OUTPUT_CONFIG_CHANGED:
Eric Laurente1512162010-05-14 05:45:46 -07001246 desc.channels = mChannels;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001247 desc.samplingRate = mSampleRate;
1248 desc.format = mFormat;
1249 desc.frameCount = mFrameCount;
1250 desc.latency = latency();
1251 param2 = &desc;
1252 break;
1253
1254 case AudioSystem::STREAM_CONFIG_CHANGED:
1255 param2 = &param;
1256 case AudioSystem::OUTPUT_CLOSED:
1257 default:
1258 break;
1259 }
Eric Laurentb3687ae2009-09-15 07:10:12 -07001260 Mutex::Autolock _l(mAudioFlinger->mLock);
Eric Laurent09b4ba82009-11-19 09:00:56 -08001261 mAudioFlinger->audioConfigChanged_l(event, mId, param2);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001262}
1263
1264void AudioFlinger::PlaybackThread::readOutputParameters()
1265{
1266 mSampleRate = mOutput->sampleRate();
Eric Laurente1512162010-05-14 05:45:46 -07001267 mChannels = mOutput->channels();
1268 mChannelCount = (uint16_t)AudioSystem::popCount(mChannels);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001269 mFormat = mOutput->format();
Eric Laurente1512162010-05-14 05:45:46 -07001270 mFrameSize = (uint16_t)mOutput->frameSize();
Eric Laurent9d91ad52009-07-17 12:17:14 -07001271 mFrameCount = mOutput->bufferSize() / mFrameSize;
1272
Eric Laurent9d91ad52009-07-17 12:17:14 -07001273 // FIXME - Current mixer implementation only supports stereo output: Always
1274 // Allocate a stereo buffer even if HW output is mono.
1275 if (mMixBuffer != NULL) delete mMixBuffer;
1276 mMixBuffer = new int16_t[mFrameCount * 2];
1277 memset(mMixBuffer, 0, mFrameCount * 2 * sizeof(int16_t));
1278}
1279
Eric Laurente9ed2722010-01-19 17:37:09 -08001280status_t AudioFlinger::PlaybackThread::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames)
1281{
1282 if (halFrames == 0 || dspFrames == 0) {
1283 return BAD_VALUE;
1284 }
1285 if (mOutput == 0) {
1286 return INVALID_OPERATION;
1287 }
1288 *halFrames = mBytesWritten/mOutput->frameSize();
1289
1290 return mOutput->getRenderPosition(dspFrames);
1291}
1292
Eric Laurent9d91ad52009-07-17 12:17:14 -07001293// ----------------------------------------------------------------------------
1294
Eric Laurent09b4ba82009-11-19 09:00:56 -08001295AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id)
1296 : PlaybackThread(audioFlinger, output, id),
Eric Laurent9d91ad52009-07-17 12:17:14 -07001297 mAudioMixer(0)
1298{
1299 mType = PlaybackThread::MIXER;
1300 mAudioMixer = new AudioMixer(mFrameCount, mSampleRate);
1301
1302 // FIXME - Current mixer implementation only supports stereo output
1303 if (mChannelCount == 1) {
1304 LOGE("Invalid audio hardware channel count");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001305 }
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001306}
1307
Eric Laurent9d91ad52009-07-17 12:17:14 -07001308AudioFlinger::MixerThread::~MixerThread()
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001309{
Eric Laurent9d91ad52009-07-17 12:17:14 -07001310 delete mAudioMixer;
1311}
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001312
Eric Laurent9d91ad52009-07-17 12:17:14 -07001313bool AudioFlinger::MixerThread::threadLoop()
1314{
Eric Laurent9d91ad52009-07-17 12:17:14 -07001315 int16_t* curBuf = mMixBuffer;
1316 Vector< sp<Track> > tracksToRemove;
Eric Laurent0e49d352009-11-09 23:32:22 -08001317 uint32_t mixerStatus = MIXER_IDLE;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001318 nsecs_t standbyTime = systemTime();
1319 size_t mixBufferSize = mFrameCount * mFrameSize;
Dave Sparks8a95a452009-09-30 03:09:03 -07001320 // FIXME: Relaxed timing because of a certain device that can't meet latency
1321 // Should be reduced to 2x after the vendor fixes the driver issue
1322 nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 3;
1323 nsecs_t lastWarning = 0;
Eric Laurent0e49d352009-11-09 23:32:22 -08001324 bool longStandbyExit = false;
1325 uint32_t activeSleepTime = activeSleepTimeUs();
1326 uint32_t idleSleepTime = idleSleepTimeUs();
1327 uint32_t sleepTime = idleSleepTime;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001328
Eric Laurent9d91ad52009-07-17 12:17:14 -07001329 while (!exitPending())
1330 {
1331 processConfigEvents();
1332
Eric Laurent0e49d352009-11-09 23:32:22 -08001333 mixerStatus = MIXER_IDLE;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001334 { // scope for mLock
1335
1336 Mutex::Autolock _l(mLock);
1337
1338 if (checkForNewParameters_l()) {
1339 mixBufferSize = mFrameCount * mFrameSize;
Dave Sparks8a95a452009-09-30 03:09:03 -07001340 // FIXME: Relaxed timing because of a certain device that can't meet latency
1341 // Should be reduced to 2x after the vendor fixes the driver issue
1342 maxPeriod = seconds(mFrameCount) / mSampleRate * 3;
Eric Laurent0e49d352009-11-09 23:32:22 -08001343 activeSleepTime = activeSleepTimeUs();
1344 idleSleepTime = idleSleepTimeUs();
Eric Laurent9d91ad52009-07-17 12:17:14 -07001345 }
1346
1347 const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
1348
1349 // put audio hardware into standby after short delay
1350 if UNLIKELY((!activeTracks.size() && systemTime() > standbyTime) ||
1351 mSuspended) {
1352 if (!mStandby) {
1353 LOGV("Audio hardware entering standby, mixer %p, mSuspended %d\n", this, mSuspended);
1354 mOutput->standby();
1355 mStandby = true;
1356 mBytesWritten = 0;
1357 }
1358
1359 if (!activeTracks.size() && mConfigEvents.isEmpty()) {
1360 // we're about to wait, flush the binder command buffer
1361 IPCThreadState::self()->flushCommands();
1362
1363 if (exitPending()) break;
1364
1365 // wait until we have something to do...
1366 LOGV("MixerThread %p TID %d going to sleep\n", this, gettid());
1367 mWaitWorkCV.wait(mLock);
1368 LOGV("MixerThread %p TID %d waking up\n", this, gettid());
1369
1370 if (mMasterMute == false) {
1371 char value[PROPERTY_VALUE_MAX];
1372 property_get("ro.audio.silent", value, "0");
1373 if (atoi(value)) {
1374 LOGD("Silence is golden");
1375 setMasterMute(true);
1376 }
1377 }
1378
1379 standbyTime = systemTime() + kStandbyTimeInNsecs;
Eric Laurent0e49d352009-11-09 23:32:22 -08001380 sleepTime = idleSleepTime;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001381 continue;
1382 }
1383 }
1384
Eric Laurent0e49d352009-11-09 23:32:22 -08001385 mixerStatus = prepareTracks_l(activeTracks, &tracksToRemove);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001386 }
1387
Eric Laurent0e49d352009-11-09 23:32:22 -08001388 if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
Eric Laurentaef692f2009-09-22 00:35:48 -07001389 // mix buffers...
1390 mAudioMixer->process(curBuf);
1391 sleepTime = 0;
1392 standbyTime = systemTime() + kStandbyTimeInNsecs;
Eric Laurent3522c802009-09-07 08:38:38 -07001393 } else {
Eric Laurentf5e868b2009-10-05 20:29:18 -07001394 // If no tracks are ready, sleep once for the duration of an output
1395 // buffer size, then write 0s to the output
1396 if (sleepTime == 0) {
Eric Laurent0e49d352009-11-09 23:32:22 -08001397 if (mixerStatus == MIXER_TRACKS_ENABLED) {
1398 sleepTime = activeSleepTime;
1399 } else {
1400 sleepTime = idleSleepTime;
1401 }
1402 } else if (mBytesWritten != 0 ||
1403 (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)) {
Eric Laurentaef692f2009-09-22 00:35:48 -07001404 memset (curBuf, 0, mixBufferSize);
Eric Laurent3522c802009-09-07 08:38:38 -07001405 sleepTime = 0;
Eric Laurent0e49d352009-11-09 23:32:22 -08001406 LOGV_IF((mBytesWritten == 0 && (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)), "anticipated start");
Eric Laurent3522c802009-09-07 08:38:38 -07001407 }
Eric Laurentaef692f2009-09-22 00:35:48 -07001408 }
1409
1410 if (mSuspended) {
Eric Laurent0e49d352009-11-09 23:32:22 -08001411 sleepTime = idleSleepTime;
Eric Laurentaef692f2009-09-22 00:35:48 -07001412 }
1413 // sleepTime == 0 means we must write to audio hardware
1414 if (sleepTime == 0) {
1415 mLastWriteTime = systemTime();
1416 mInWrite = true;
Eric Laurente9ed2722010-01-19 17:37:09 -08001417 mBytesWritten += mixBufferSize;
Glenn Kastend5ea9692010-03-05 12:18:01 -08001418#ifdef LVMX
1419 int audioOutputType = LifeVibes::getMixerType(mId, mType);
1420 if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) {
1421 LifeVibes::process(audioOutputType, curBuf, mixBufferSize);
1422 }
1423#endif
Eric Laurentaef692f2009-09-22 00:35:48 -07001424 int bytesWritten = (int)mOutput->write(curBuf, mixBufferSize);
Eric Laurente9ed2722010-01-19 17:37:09 -08001425 if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
Eric Laurentaef692f2009-09-22 00:35:48 -07001426 mNumWrites++;
1427 mInWrite = false;
Dave Sparks8a95a452009-09-30 03:09:03 -07001428 nsecs_t now = systemTime();
1429 nsecs_t delta = now - mLastWriteTime;
Eric Laurentaef692f2009-09-22 00:35:48 -07001430 if (delta > maxPeriod) {
Eric Laurentaef692f2009-09-22 00:35:48 -07001431 mNumDelayedWrites++;
Dave Sparks8a95a452009-09-30 03:09:03 -07001432 if ((now - lastWarning) > kWarningThrottle) {
1433 LOGW("write blocked for %llu msecs, %d delayed writes, thread %p",
1434 ns2ms(delta), mNumDelayedWrites, this);
1435 lastWarning = now;
1436 }
Eric Laurent0e49d352009-11-09 23:32:22 -08001437 if (mStandby) {
1438 longStandbyExit = true;
1439 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07001440 }
Eric Laurent0e49d352009-11-09 23:32:22 -08001441 mStandby = false;
Eric Laurentaef692f2009-09-22 00:35:48 -07001442 } else {
1443 usleep(sleepTime);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001444 }
1445
1446 // finally let go of all our tracks, without the lock held
1447 // since we can't guarantee the destructors won't acquire that
1448 // same lock.
1449 tracksToRemove.clear();
1450 }
1451
1452 if (!mStandby) {
1453 mOutput->standby();
1454 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07001455
1456 LOGV("MixerThread %p exiting", this);
1457 return false;
1458}
1459
1460// prepareTracks_l() must be called with ThreadBase::mLock held
Eric Laurent0e49d352009-11-09 23:32:22 -08001461uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove)
Eric Laurent9d91ad52009-07-17 12:17:14 -07001462{
1463
Eric Laurent0e49d352009-11-09 23:32:22 -08001464 uint32_t mixerStatus = MIXER_IDLE;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001465 // find out which tracks need to be processed
1466 size_t count = activeTracks.size();
Glenn Kastend5ea9692010-03-05 12:18:01 -08001467
1468 float masterVolume = mMasterVolume;
1469 bool masterMute = mMasterMute;
1470
1471#ifdef LVMX
1472 bool tracksConnectedChanged = false;
1473 bool stateChanged = false;
1474
1475 int audioOutputType = LifeVibes::getMixerType(mId, mType);
1476 if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType))
1477 {
1478 int activeTypes = 0;
1479 for (size_t i=0 ; i<count ; i++) {
1480 sp<Track> t = activeTracks[i].promote();
1481 if (t == 0) continue;
1482 Track* const track = t.get();
1483 int iTracktype=track->type();
1484 activeTypes |= 1<<track->type();
1485 }
1486 LifeVibes::computeVolumes(audioOutputType, activeTypes, tracksConnectedChanged, stateChanged, masterVolume, masterMute);
1487 }
1488#endif
1489
Eric Laurent9d91ad52009-07-17 12:17:14 -07001490 for (size_t i=0 ; i<count ; i++) {
1491 sp<Track> t = activeTracks[i].promote();
1492 if (t == 0) continue;
1493
1494 Track* const track = t.get();
1495 audio_track_cblk_t* cblk = track->cblk();
1496
1497 // The first time a track is added we wait
1498 // for all its buffers to be filled before processing it
1499 mAudioMixer->setActiveTrack(track->name());
1500 if (cblk->framesReady() && (track->isReady() || track->isStopped()) &&
Eric Laurentdeea5022010-03-31 12:21:17 -07001501 !track->isPaused() && !track->isTerminated())
Eric Laurent9d91ad52009-07-17 12:17:14 -07001502 {
Eric Laurent7e2aad12009-12-18 05:47:48 -08001503 //LOGV("track %d u=%08x, s=%08x [OK] on thread %p", track->name(), cblk->user, cblk->server, this);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001504
1505 // compute volume for this track
1506 int16_t left, right;
Glenn Kastend5ea9692010-03-05 12:18:01 -08001507 if (track->isMuted() || masterMute || track->isPausing() ||
Eric Laurent9d91ad52009-07-17 12:17:14 -07001508 mStreamTypes[track->type()].mute) {
1509 left = right = 0;
1510 if (track->isPausing()) {
1511 track->setPaused();
1512 }
1513 } else {
Glenn Kastend5ea9692010-03-05 12:18:01 -08001514 // read original volumes with volume control
Eric Laurent9d91ad52009-07-17 12:17:14 -07001515 float typeVolume = mStreamTypes[track->type()].volume;
Glenn Kastend5ea9692010-03-05 12:18:01 -08001516#ifdef LVMX
1517 bool streamMute=false;
1518 // read the volume from the LivesVibes audio engine.
1519 if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType))
1520 {
1521 LifeVibes::getStreamVolumes(audioOutputType, track->type(), &typeVolume, &streamMute);
1522 if (streamMute) {
1523 typeVolume = 0;
1524 }
1525 }
1526#endif
1527 float v = masterVolume * typeVolume;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001528 float v_clamped = v * cblk->volume[0];
1529 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
1530 left = int16_t(v_clamped);
1531 v_clamped = v * cblk->volume[1];
1532 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
1533 right = int16_t(v_clamped);
1534 }
1535
1536 // XXX: these things DON'T need to be done each time
1537 mAudioMixer->setBufferProvider(track);
1538 mAudioMixer->enable(AudioMixer::MIXING);
1539
Eric Laurent08d3d1d2009-09-03 03:45:52 -07001540 int param = AudioMixer::VOLUME;
1541 if (track->mFillingUpStatus == Track::FS_FILLED) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07001542 // no ramp for the first volume setting
1543 track->mFillingUpStatus = Track::FS_ACTIVE;
1544 if (track->mState == TrackBase::RESUMING) {
1545 track->mState = TrackBase::ACTIVE;
1546 param = AudioMixer::RAMP_VOLUME;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001547 }
Eric Laurent08d3d1d2009-09-03 03:45:52 -07001548 } else if (cblk->server != 0) {
1549 // If the track is stopped before the first frame was mixed,
1550 // do not apply ramp
Eric Laurent9d91ad52009-07-17 12:17:14 -07001551 param = AudioMixer::RAMP_VOLUME;
1552 }
Glenn Kastend5ea9692010-03-05 12:18:01 -08001553#ifdef LVMX
1554 if ( tracksConnectedChanged || stateChanged )
1555 {
1556 // only do the ramp when the volume is changed by the user / application
1557 param = AudioMixer::VOLUME;
1558 }
1559#endif
Eric Laurent9d91ad52009-07-17 12:17:14 -07001560 mAudioMixer->setParameter(param, AudioMixer::VOLUME0, left);
1561 mAudioMixer->setParameter(param, AudioMixer::VOLUME1, right);
1562 mAudioMixer->setParameter(
1563 AudioMixer::TRACK,
1564 AudioMixer::FORMAT, track->format());
1565 mAudioMixer->setParameter(
1566 AudioMixer::TRACK,
1567 AudioMixer::CHANNEL_COUNT, track->channelCount());
1568 mAudioMixer->setParameter(
1569 AudioMixer::RESAMPLE,
1570 AudioMixer::SAMPLE_RATE,
1571 int(cblk->sampleRate));
1572
1573 // reset retry count
1574 track->mRetryCount = kMaxTrackRetries;
Eric Laurent0e49d352009-11-09 23:32:22 -08001575 mixerStatus = MIXER_TRACKS_READY;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001576 } else {
Eric Laurent7e2aad12009-12-18 05:47:48 -08001577 //LOGV("track %d u=%08x, s=%08x [NOT READY] on thread %p", track->name(), cblk->user, cblk->server, this);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001578 if (track->isStopped()) {
1579 track->reset();
1580 }
1581 if (track->isTerminated() || track->isStopped() || track->isPaused()) {
1582 // We have consumed all the buffers of this track.
1583 // Remove it from the list of active tracks.
1584 tracksToRemove->add(track);
1585 mAudioMixer->disable(AudioMixer::MIXING);
1586 } else {
1587 // No buffers for this track. Give it a few chances to
1588 // fill a buffer, then remove it from active list.
1589 if (--(track->mRetryCount) <= 0) {
Eric Laurentf5e868b2009-10-05 20:29:18 -07001590 LOGV("BUFFER TIMEOUT: remove(%d) from active list on thread %p", track->name(), this);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001591 tracksToRemove->add(track);
Eric Laurent0e49d352009-11-09 23:32:22 -08001592 } else if (mixerStatus != MIXER_TRACKS_READY) {
1593 mixerStatus = MIXER_TRACKS_ENABLED;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001594 }
Eric Laurent0e49d352009-11-09 23:32:22 -08001595
1596 mAudioMixer->disable(AudioMixer::MIXING);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001597 }
1598 }
1599 }
1600
1601 // remove all the tracks that need to be...
1602 count = tracksToRemove->size();
1603 if (UNLIKELY(count)) {
1604 for (size_t i=0 ; i<count ; i++) {
1605 const sp<Track>& track = tracksToRemove->itemAt(i);
1606 mActiveTracks.remove(track);
1607 if (track->isTerminated()) {
1608 mTracks.remove(track);
1609 deleteTrackName_l(track->mName);
1610 }
1611 }
1612 }
1613
Eric Laurent0e49d352009-11-09 23:32:22 -08001614 return mixerStatus;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001615}
1616
1617void AudioFlinger::MixerThread::getTracks(
1618 SortedVector < sp<Track> >& tracks,
1619 SortedVector < wp<Track> >& activeTracks,
1620 int streamType)
1621{
1622 LOGV ("MixerThread::getTracks() mixer %p, mTracks.size %d, mActiveTracks.size %d", this, mTracks.size(), mActiveTracks.size());
1623 Mutex::Autolock _l(mLock);
1624 size_t size = mTracks.size();
1625 for (size_t i = 0; i < size; i++) {
1626 sp<Track> t = mTracks[i];
1627 if (t->type() == streamType) {
1628 tracks.add(t);
1629 int j = mActiveTracks.indexOf(t);
1630 if (j >= 0) {
1631 t = mActiveTracks[j].promote();
1632 if (t != NULL) {
1633 activeTracks.add(t);
1634 }
1635 }
1636 }
1637 }
1638
1639 size = activeTracks.size();
1640 for (size_t i = 0; i < size; i++) {
1641 mActiveTracks.remove(activeTracks[i]);
1642 }
1643
1644 size = tracks.size();
1645 for (size_t i = 0; i < size; i++) {
1646 sp<Track> t = tracks[i];
1647 mTracks.remove(t);
1648 deleteTrackName_l(t->name());
1649 }
1650}
1651
1652void AudioFlinger::MixerThread::putTracks(
1653 SortedVector < sp<Track> >& tracks,
1654 SortedVector < wp<Track> >& activeTracks)
1655{
1656 LOGV ("MixerThread::putTracks() mixer %p, tracks.size %d, activeTracks.size %d", this, tracks.size(), activeTracks.size());
1657 Mutex::Autolock _l(mLock);
1658 size_t size = tracks.size();
1659 for (size_t i = 0; i < size ; i++) {
1660 sp<Track> t = tracks[i];
1661 int name = getTrackName_l();
1662
1663 if (name < 0) return;
1664
1665 t->mName = name;
1666 t->mThread = this;
1667 mTracks.add(t);
1668
1669 int j = activeTracks.indexOf(t);
1670 if (j >= 0) {
1671 mActiveTracks.add(t);
Eric Laurent06437712009-09-01 05:56:26 -07001672 // force buffer refilling and no ramp volume when the track is mixed for the first time
1673 t->mFillingUpStatus = Track::FS_FILLING;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001674 }
1675 }
1676}
1677
Eric Laurent9d91ad52009-07-17 12:17:14 -07001678// getTrackName_l() must be called with ThreadBase::mLock held
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001679int AudioFlinger::MixerThread::getTrackName_l()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001680{
1681 return mAudioMixer->getTrackName();
1682}
1683
Eric Laurent9d91ad52009-07-17 12:17:14 -07001684// deleteTrackName_l() must be called with ThreadBase::mLock held
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001685void AudioFlinger::MixerThread::deleteTrackName_l(int name)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001686{
Eric Laurentfed93822009-12-07 10:53:10 -08001687 LOGV("remove track (%d) and delete from mixer", name);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001688 mAudioMixer->deleteTrackName(name);
1689}
1690
Eric Laurent9d91ad52009-07-17 12:17:14 -07001691// checkForNewParameters_l() must be called with ThreadBase::mLock held
1692bool AudioFlinger::MixerThread::checkForNewParameters_l()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001693{
Eric Laurent9d91ad52009-07-17 12:17:14 -07001694 bool reconfig = false;
1695
Eric Laurent3464c012009-08-04 09:45:33 -07001696 while (!mNewParameters.isEmpty()) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07001697 status_t status = NO_ERROR;
Eric Laurent3464c012009-08-04 09:45:33 -07001698 String8 keyValuePair = mNewParameters[0];
1699 AudioParameter param = AudioParameter(keyValuePair);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001700 int value;
Eric Laurent3464c012009-08-04 09:45:33 -07001701
Eric Laurent9d91ad52009-07-17 12:17:14 -07001702 if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
1703 reconfig = true;
1704 }
1705 if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
1706 if (value != AudioSystem::PCM_16_BIT) {
1707 status = BAD_VALUE;
1708 } else {
1709 reconfig = true;
1710 }
1711 }
1712 if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
1713 if (value != AudioSystem::CHANNEL_OUT_STEREO) {
1714 status = BAD_VALUE;
1715 } else {
1716 reconfig = true;
1717 }
1718 }
1719 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
1720 // do not accept frame count changes if tracks are open as the track buffer
1721 // size depends on frame count and correct behavior would not be garantied
1722 // if frame count is changed after track creation
1723 if (!mTracks.isEmpty()) {
1724 status = INVALID_OPERATION;
1725 } else {
1726 reconfig = true;
1727 }
1728 }
1729 if (status == NO_ERROR) {
Eric Laurent3464c012009-08-04 09:45:33 -07001730 status = mOutput->setParameters(keyValuePair);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001731 if (!mStandby && status == INVALID_OPERATION) {
1732 mOutput->standby();
1733 mStandby = true;
1734 mBytesWritten = 0;
Eric Laurent3464c012009-08-04 09:45:33 -07001735 status = mOutput->setParameters(keyValuePair);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001736 }
1737 if (status == NO_ERROR && reconfig) {
1738 delete mAudioMixer;
1739 readOutputParameters();
1740 mAudioMixer = new AudioMixer(mFrameCount, mSampleRate);
1741 for (size_t i = 0; i < mTracks.size() ; i++) {
1742 int name = getTrackName_l();
1743 if (name < 0) break;
1744 mTracks[i]->mName = name;
Eric Laurent878c0e12009-08-10 08:15:12 -07001745 // limit track sample rate to 2 x new output sample rate
1746 if (mTracks[i]->mCblk->sampleRate > 2 * sampleRate()) {
1747 mTracks[i]->mCblk->sampleRate = 2 * sampleRate();
1748 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07001749 }
Eric Laurent3464c012009-08-04 09:45:33 -07001750 sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001751 }
1752 }
Eric Laurentee47d432009-11-07 00:01:32 -08001753
1754 mNewParameters.removeAt(0);
1755
Eric Laurent9d91ad52009-07-17 12:17:14 -07001756 mParamStatus = status;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001757 mParamCond.signal();
Eric Laurent3464c012009-08-04 09:45:33 -07001758 mWaitWorkCV.wait(mLock);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001759 }
1760 return reconfig;
1761}
1762
1763status_t AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>& args)
1764{
1765 const size_t SIZE = 256;
1766 char buffer[SIZE];
1767 String8 result;
1768
1769 PlaybackThread::dumpInternals(fd, args);
1770
1771 snprintf(buffer, SIZE, "AudioMixer tracks: %08x\n", mAudioMixer->trackNames());
1772 result.append(buffer);
1773 write(fd, result.string(), result.size());
1774 return NO_ERROR;
1775}
1776
Eric Laurent0e49d352009-11-09 23:32:22 -08001777uint32_t AudioFlinger::MixerThread::activeSleepTimeUs()
Eric Laurentf5e868b2009-10-05 20:29:18 -07001778{
Eric Laurent0e49d352009-11-09 23:32:22 -08001779 return (uint32_t)(mOutput->latency() * 1000) / 2;
1780}
1781
1782uint32_t AudioFlinger::MixerThread::idleSleepTimeUs()
1783{
1784 return (uint32_t)((mFrameCount * 1000) / mSampleRate) * 1000;
Eric Laurentf5e868b2009-10-05 20:29:18 -07001785}
1786
Eric Laurent9d91ad52009-07-17 12:17:14 -07001787// ----------------------------------------------------------------------------
Eric Laurent09b4ba82009-11-19 09:00:56 -08001788AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id)
1789 : PlaybackThread(audioFlinger, output, id),
Eric Laurent9d91ad52009-07-17 12:17:14 -07001790 mLeftVolume (1.0), mRightVolume(1.0)
1791{
1792 mType = PlaybackThread::DIRECT;
1793}
1794
1795AudioFlinger::DirectOutputThread::~DirectOutputThread()
1796{
1797}
1798
1799
1800bool AudioFlinger::DirectOutputThread::threadLoop()
1801{
Eric Laurent0e49d352009-11-09 23:32:22 -08001802 uint32_t mixerStatus = MIXER_IDLE;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001803 sp<Track> trackToRemove;
1804 sp<Track> activeTrack;
1805 nsecs_t standbyTime = systemTime();
1806 int8_t *curBuf;
1807 size_t mixBufferSize = mFrameCount*mFrameSize;
Eric Laurent0e49d352009-11-09 23:32:22 -08001808 uint32_t activeSleepTime = activeSleepTimeUs();
1809 uint32_t idleSleepTime = idleSleepTimeUs();
1810 uint32_t sleepTime = idleSleepTime;
Eric Laurent101e77a2010-03-11 14:47:00 -08001811 // use shorter standby delay as on normal output to release
1812 // hardware resources as soon as possible
1813 nsecs_t standbyDelay = microseconds(activeSleepTime*2);
Eric Laurent0e49d352009-11-09 23:32:22 -08001814
Eric Laurent9d91ad52009-07-17 12:17:14 -07001815
1816 while (!exitPending())
1817 {
1818 processConfigEvents();
1819
Eric Laurent0e49d352009-11-09 23:32:22 -08001820 mixerStatus = MIXER_IDLE;
1821
Eric Laurent9d91ad52009-07-17 12:17:14 -07001822 { // scope for the mLock
1823
1824 Mutex::Autolock _l(mLock);
1825
1826 if (checkForNewParameters_l()) {
1827 mixBufferSize = mFrameCount*mFrameSize;
Eric Laurent0e49d352009-11-09 23:32:22 -08001828 activeSleepTime = activeSleepTimeUs();
1829 idleSleepTime = idleSleepTimeUs();
Eric Laurent101e77a2010-03-11 14:47:00 -08001830 standbyDelay = microseconds(activeSleepTime*2);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001831 }
1832
1833 // put audio hardware into standby after short delay
1834 if UNLIKELY((!mActiveTracks.size() && systemTime() > standbyTime) ||
1835 mSuspended) {
1836 // wait until we have something to do...
1837 if (!mStandby) {
1838 LOGV("Audio hardware entering standby, mixer %p\n", this);
1839 mOutput->standby();
1840 mStandby = true;
1841 mBytesWritten = 0;
1842 }
1843
1844 if (!mActiveTracks.size() && mConfigEvents.isEmpty()) {
1845 // we're about to wait, flush the binder command buffer
1846 IPCThreadState::self()->flushCommands();
1847
1848 if (exitPending()) break;
1849
1850 LOGV("DirectOutputThread %p TID %d going to sleep\n", this, gettid());
1851 mWaitWorkCV.wait(mLock);
1852 LOGV("DirectOutputThread %p TID %d waking up in active mode\n", this, gettid());
1853
1854 if (mMasterMute == false) {
1855 char value[PROPERTY_VALUE_MAX];
1856 property_get("ro.audio.silent", value, "0");
1857 if (atoi(value)) {
1858 LOGD("Silence is golden");
1859 setMasterMute(true);
1860 }
1861 }
1862
Eric Laurent101e77a2010-03-11 14:47:00 -08001863 standbyTime = systemTime() + standbyDelay;
Eric Laurent0e49d352009-11-09 23:32:22 -08001864 sleepTime = idleSleepTime;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001865 continue;
1866 }
1867 }
1868
1869 // find out which tracks need to be processed
1870 if (mActiveTracks.size() != 0) {
1871 sp<Track> t = mActiveTracks[0].promote();
1872 if (t == 0) continue;
1873
1874 Track* const track = t.get();
1875 audio_track_cblk_t* cblk = track->cblk();
1876
1877 // The first time a track is added we wait
1878 // for all its buffers to be filled before processing it
1879 if (cblk->framesReady() && (track->isReady() || track->isStopped()) &&
Eric Laurent775fa3c2010-04-09 06:11:48 -07001880 !track->isPaused() && !track->isTerminated())
Eric Laurent9d91ad52009-07-17 12:17:14 -07001881 {
1882 //LOGV("track %d u=%08x, s=%08x [OK]", track->name(), cblk->user, cblk->server);
1883
1884 // compute volume for this track
1885 float left, right;
1886 if (track->isMuted() || mMasterMute || track->isPausing() ||
1887 mStreamTypes[track->type()].mute) {
1888 left = right = 0;
1889 if (track->isPausing()) {
1890 track->setPaused();
1891 }
1892 } else {
1893 float typeVolume = mStreamTypes[track->type()].volume;
1894 float v = mMasterVolume * typeVolume;
1895 float v_clamped = v * cblk->volume[0];
1896 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
1897 left = v_clamped/MAX_GAIN;
1898 v_clamped = v * cblk->volume[1];
1899 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
1900 right = v_clamped/MAX_GAIN;
1901 }
1902
1903 if (left != mLeftVolume || right != mRightVolume) {
1904 mOutput->setVolume(left, right);
1905 left = mLeftVolume;
1906 right = mRightVolume;
1907 }
1908
1909 if (track->mFillingUpStatus == Track::FS_FILLED) {
1910 track->mFillingUpStatus = Track::FS_ACTIVE;
1911 if (track->mState == TrackBase::RESUMING) {
1912 track->mState = TrackBase::ACTIVE;
1913 }
1914 }
1915
1916 // reset retry count
Eric Laurent101e77a2010-03-11 14:47:00 -08001917 track->mRetryCount = kMaxTrackRetriesDirect;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001918 activeTrack = t;
Eric Laurent0e49d352009-11-09 23:32:22 -08001919 mixerStatus = MIXER_TRACKS_READY;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001920 } else {
1921 //LOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
1922 if (track->isStopped()) {
1923 track->reset();
1924 }
1925 if (track->isTerminated() || track->isStopped() || track->isPaused()) {
1926 // We have consumed all the buffers of this track.
1927 // Remove it from the list of active tracks.
1928 trackToRemove = track;
1929 } else {
1930 // No buffers for this track. Give it a few chances to
1931 // fill a buffer, then remove it from active list.
1932 if (--(track->mRetryCount) <= 0) {
1933 LOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
1934 trackToRemove = track;
Eric Laurent0e49d352009-11-09 23:32:22 -08001935 } else {
1936 mixerStatus = MIXER_TRACKS_ENABLED;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001937 }
Eric Laurent0e49d352009-11-09 23:32:22 -08001938 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07001939 }
1940 }
1941
1942 // remove all the tracks that need to be...
1943 if (UNLIKELY(trackToRemove != 0)) {
1944 mActiveTracks.remove(trackToRemove);
1945 if (trackToRemove->isTerminated()) {
1946 mTracks.remove(trackToRemove);
1947 deleteTrackName_l(trackToRemove->mName);
1948 }
1949 }
1950 }
1951
Eric Laurent0e49d352009-11-09 23:32:22 -08001952 if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
Eric Laurentaef692f2009-09-22 00:35:48 -07001953 AudioBufferProvider::Buffer buffer;
1954 size_t frameCount = mFrameCount;
1955 curBuf = (int8_t *)mMixBuffer;
1956 // output audio to hardware
1957 while(frameCount) {
1958 buffer.frameCount = frameCount;
1959 activeTrack->getNextBuffer(&buffer);
1960 if (UNLIKELY(buffer.raw == 0)) {
1961 memset(curBuf, 0, frameCount * mFrameSize);
1962 break;
1963 }
1964 memcpy(curBuf, buffer.raw, buffer.frameCount * mFrameSize);
1965 frameCount -= buffer.frameCount;
1966 curBuf += buffer.frameCount * mFrameSize;
1967 activeTrack->releaseBuffer(&buffer);
1968 }
1969 sleepTime = 0;
Eric Laurent101e77a2010-03-11 14:47:00 -08001970 standbyTime = systemTime() + standbyDelay;
Eric Laurent3522c802009-09-07 08:38:38 -07001971 } else {
Eric Laurentf5e868b2009-10-05 20:29:18 -07001972 if (sleepTime == 0) {
Eric Laurent0e49d352009-11-09 23:32:22 -08001973 if (mixerStatus == MIXER_TRACKS_ENABLED) {
1974 sleepTime = activeSleepTime;
1975 } else {
1976 sleepTime = idleSleepTime;
1977 }
Eric Laurentf5e868b2009-10-05 20:29:18 -07001978 } else if (mBytesWritten != 0 && AudioSystem::isLinearPCM(mFormat)) {
Eric Laurentaef692f2009-09-22 00:35:48 -07001979 memset (mMixBuffer, 0, mFrameCount * mFrameSize);
Eric Laurent3522c802009-09-07 08:38:38 -07001980 sleepTime = 0;
Eric Laurent3522c802009-09-07 08:38:38 -07001981 }
Eric Laurentaef692f2009-09-22 00:35:48 -07001982 }
Eric Laurent3522c802009-09-07 08:38:38 -07001983
Eric Laurentaef692f2009-09-22 00:35:48 -07001984 if (mSuspended) {
Eric Laurent0e49d352009-11-09 23:32:22 -08001985 sleepTime = idleSleepTime;
Eric Laurentaef692f2009-09-22 00:35:48 -07001986 }
1987 // sleepTime == 0 means we must write to audio hardware
1988 if (sleepTime == 0) {
1989 mLastWriteTime = systemTime();
1990 mInWrite = true;
Eric Laurente9ed2722010-01-19 17:37:09 -08001991 mBytesWritten += mixBufferSize;
Eric Laurentaef692f2009-09-22 00:35:48 -07001992 int bytesWritten = (int)mOutput->write(mMixBuffer, mixBufferSize);
Eric Laurente9ed2722010-01-19 17:37:09 -08001993 if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
Eric Laurentaef692f2009-09-22 00:35:48 -07001994 mNumWrites++;
1995 mInWrite = false;
1996 mStandby = false;
1997 } else {
1998 usleep(sleepTime);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001999 }
2000
2001 // finally let go of removed track, without the lock held
2002 // since we can't guarantee the destructors won't acquire that
2003 // same lock.
2004 trackToRemove.clear();
2005 activeTrack.clear();
2006 }
2007
2008 if (!mStandby) {
2009 mOutput->standby();
2010 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002011
2012 LOGV("DirectOutputThread %p exiting", this);
2013 return false;
2014}
2015
2016// getTrackName_l() must be called with ThreadBase::mLock held
2017int AudioFlinger::DirectOutputThread::getTrackName_l()
2018{
2019 return 0;
2020}
2021
2022// deleteTrackName_l() must be called with ThreadBase::mLock held
2023void AudioFlinger::DirectOutputThread::deleteTrackName_l(int name)
2024{
2025}
2026
2027// checkForNewParameters_l() must be called with ThreadBase::mLock held
2028bool AudioFlinger::DirectOutputThread::checkForNewParameters_l()
2029{
2030 bool reconfig = false;
2031
Eric Laurent3464c012009-08-04 09:45:33 -07002032 while (!mNewParameters.isEmpty()) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07002033 status_t status = NO_ERROR;
Eric Laurent3464c012009-08-04 09:45:33 -07002034 String8 keyValuePair = mNewParameters[0];
2035 AudioParameter param = AudioParameter(keyValuePair);
Eric Laurent9d91ad52009-07-17 12:17:14 -07002036 int value;
Eric Laurent3464c012009-08-04 09:45:33 -07002037
Eric Laurent9d91ad52009-07-17 12:17:14 -07002038 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
2039 // do not accept frame count changes if tracks are open as the track buffer
2040 // size depends on frame count and correct behavior would not be garantied
2041 // if frame count is changed after track creation
2042 if (!mTracks.isEmpty()) {
2043 status = INVALID_OPERATION;
2044 } else {
2045 reconfig = true;
2046 }
2047 }
2048 if (status == NO_ERROR) {
Eric Laurent3464c012009-08-04 09:45:33 -07002049 status = mOutput->setParameters(keyValuePair);
Eric Laurent9d91ad52009-07-17 12:17:14 -07002050 if (!mStandby && status == INVALID_OPERATION) {
2051 mOutput->standby();
2052 mStandby = true;
2053 mBytesWritten = 0;
Eric Laurent3464c012009-08-04 09:45:33 -07002054 status = mOutput->setParameters(keyValuePair);
Eric Laurent9d91ad52009-07-17 12:17:14 -07002055 }
2056 if (status == NO_ERROR && reconfig) {
2057 readOutputParameters();
Eric Laurent3464c012009-08-04 09:45:33 -07002058 sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
Eric Laurent9d91ad52009-07-17 12:17:14 -07002059 }
2060 }
Eric Laurentee47d432009-11-07 00:01:32 -08002061
2062 mNewParameters.removeAt(0);
2063
Eric Laurent9d91ad52009-07-17 12:17:14 -07002064 mParamStatus = status;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002065 mParamCond.signal();
Eric Laurent3464c012009-08-04 09:45:33 -07002066 mWaitWorkCV.wait(mLock);
Eric Laurent9d91ad52009-07-17 12:17:14 -07002067 }
2068 return reconfig;
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08002069}
2070
Eric Laurent0e49d352009-11-09 23:32:22 -08002071uint32_t AudioFlinger::DirectOutputThread::activeSleepTimeUs()
Eric Laurentf5e868b2009-10-05 20:29:18 -07002072{
2073 uint32_t time;
2074 if (AudioSystem::isLinearPCM(mFormat)) {
Eric Laurent0e49d352009-11-09 23:32:22 -08002075 time = (uint32_t)(mOutput->latency() * 1000) / 2;
2076 } else {
2077 time = 10000;
2078 }
2079 return time;
2080}
2081
2082uint32_t AudioFlinger::DirectOutputThread::idleSleepTimeUs()
2083{
2084 uint32_t time;
2085 if (AudioSystem::isLinearPCM(mFormat)) {
2086 time = (uint32_t)((mFrameCount * 1000) / mSampleRate) * 1000;
Eric Laurentf5e868b2009-10-05 20:29:18 -07002087 } else {
2088 time = 10000;
2089 }
2090 return time;
2091}
2092
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002093// ----------------------------------------------------------------------------
2094
Eric Laurent09b4ba82009-11-19 09:00:56 -08002095AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger, AudioFlinger::MixerThread* mainThread, int id)
Eric Laurent7e2aad12009-12-18 05:47:48 -08002096 : MixerThread(audioFlinger, mainThread->getOutput(), id), mWaitTimeMs(UINT_MAX)
Eric Laurent9d91ad52009-07-17 12:17:14 -07002097{
2098 mType = PlaybackThread::DUPLICATING;
2099 addOutputTrack(mainThread);
2100}
2101
2102AudioFlinger::DuplicatingThread::~DuplicatingThread()
2103{
Eric Laurentfed93822009-12-07 10:53:10 -08002104 for (size_t i = 0; i < mOutputTracks.size(); i++) {
2105 mOutputTracks[i]->destroy();
2106 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002107 mOutputTracks.clear();
2108}
2109
2110bool AudioFlinger::DuplicatingThread::threadLoop()
2111{
Eric Laurent9d91ad52009-07-17 12:17:14 -07002112 int16_t* curBuf = mMixBuffer;
2113 Vector< sp<Track> > tracksToRemove;
Eric Laurent0e49d352009-11-09 23:32:22 -08002114 uint32_t mixerStatus = MIXER_IDLE;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002115 nsecs_t standbyTime = systemTime();
2116 size_t mixBufferSize = mFrameCount*mFrameSize;
2117 SortedVector< sp<OutputTrack> > outputTracks;
Eric Laurentf5e868b2009-10-05 20:29:18 -07002118 uint32_t writeFrames = 0;
Eric Laurent0e49d352009-11-09 23:32:22 -08002119 uint32_t activeSleepTime = activeSleepTimeUs();
2120 uint32_t idleSleepTime = idleSleepTimeUs();
2121 uint32_t sleepTime = idleSleepTime;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002122
2123 while (!exitPending())
2124 {
2125 processConfigEvents();
2126
Eric Laurent0e49d352009-11-09 23:32:22 -08002127 mixerStatus = MIXER_IDLE;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002128 { // scope for the mLock
2129
2130 Mutex::Autolock _l(mLock);
2131
2132 if (checkForNewParameters_l()) {
2133 mixBufferSize = mFrameCount*mFrameSize;
Eric Laurent7e2aad12009-12-18 05:47:48 -08002134 updateWaitTime();
Eric Laurent0e49d352009-11-09 23:32:22 -08002135 activeSleepTime = activeSleepTimeUs();
2136 idleSleepTime = idleSleepTimeUs();
Eric Laurent9d91ad52009-07-17 12:17:14 -07002137 }
2138
2139 const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
2140
2141 for (size_t i = 0; i < mOutputTracks.size(); i++) {
2142 outputTracks.add(mOutputTracks[i]);
2143 }
2144
2145 // put audio hardware into standby after short delay
2146 if UNLIKELY((!activeTracks.size() && systemTime() > standbyTime) ||
2147 mSuspended) {
2148 if (!mStandby) {
2149 for (size_t i = 0; i < outputTracks.size(); i++) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07002150 outputTracks[i]->stop();
Eric Laurent9d91ad52009-07-17 12:17:14 -07002151 }
2152 mStandby = true;
2153 mBytesWritten = 0;
2154 }
2155
2156 if (!activeTracks.size() && mConfigEvents.isEmpty()) {
2157 // we're about to wait, flush the binder command buffer
2158 IPCThreadState::self()->flushCommands();
2159 outputTracks.clear();
2160
2161 if (exitPending()) break;
2162
2163 LOGV("DuplicatingThread %p TID %d going to sleep\n", this, gettid());
2164 mWaitWorkCV.wait(mLock);
2165 LOGV("DuplicatingThread %p TID %d waking up\n", this, gettid());
2166 if (mMasterMute == false) {
2167 char value[PROPERTY_VALUE_MAX];
2168 property_get("ro.audio.silent", value, "0");
2169 if (atoi(value)) {
2170 LOGD("Silence is golden");
2171 setMasterMute(true);
2172 }
2173 }
2174
2175 standbyTime = systemTime() + kStandbyTimeInNsecs;
Eric Laurent0e49d352009-11-09 23:32:22 -08002176 sleepTime = idleSleepTime;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002177 continue;
2178 }
2179 }
2180
Eric Laurent0e49d352009-11-09 23:32:22 -08002181 mixerStatus = prepareTracks_l(activeTracks, &tracksToRemove);
Eric Laurentaef692f2009-09-22 00:35:48 -07002182 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002183
Eric Laurent0e49d352009-11-09 23:32:22 -08002184 if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07002185 // mix buffers...
Eric Laurent7e2aad12009-12-18 05:47:48 -08002186 if (outputsReady(outputTracks)) {
2187 mAudioMixer->process(curBuf);
2188 } else {
2189 memset(curBuf, 0, mixBufferSize);
2190 }
Eric Laurentaef692f2009-09-22 00:35:48 -07002191 sleepTime = 0;
Eric Laurentf5e868b2009-10-05 20:29:18 -07002192 writeFrames = mFrameCount;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002193 } else {
Eric Laurentf5e868b2009-10-05 20:29:18 -07002194 if (sleepTime == 0) {
Eric Laurent0e49d352009-11-09 23:32:22 -08002195 if (mixerStatus == MIXER_TRACKS_ENABLED) {
2196 sleepTime = activeSleepTime;
2197 } else {
2198 sleepTime = idleSleepTime;
2199 }
Eric Laurentf5e868b2009-10-05 20:29:18 -07002200 } else if (mBytesWritten != 0) {
2201 // flush remaining overflow buffers in output tracks
2202 for (size_t i = 0; i < outputTracks.size(); i++) {
2203 if (outputTracks[i]->isActive()) {
2204 sleepTime = 0;
2205 writeFrames = 0;
2206 break;
2207 }
2208 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002209 }
2210 }
Eric Laurentaef692f2009-09-22 00:35:48 -07002211
2212 if (mSuspended) {
Eric Laurent0e49d352009-11-09 23:32:22 -08002213 sleepTime = idleSleepTime;
Eric Laurentaef692f2009-09-22 00:35:48 -07002214 }
2215 // sleepTime == 0 means we must write to audio hardware
2216 if (sleepTime == 0) {
Eric Laurentf5e868b2009-10-05 20:29:18 -07002217 standbyTime = systemTime() + kStandbyTimeInNsecs;
Eric Laurentaef692f2009-09-22 00:35:48 -07002218 for (size_t i = 0; i < outputTracks.size(); i++) {
Eric Laurentf5e868b2009-10-05 20:29:18 -07002219 outputTracks[i]->write(curBuf, writeFrames);
Eric Laurent9d91ad52009-07-17 12:17:14 -07002220 }
Eric Laurentaef692f2009-09-22 00:35:48 -07002221 mStandby = false;
2222 mBytesWritten += mixBufferSize;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002223 } else {
Eric Laurentaef692f2009-09-22 00:35:48 -07002224 usleep(sleepTime);
Eric Laurent9d91ad52009-07-17 12:17:14 -07002225 }
2226
2227 // finally let go of all our tracks, without the lock held
2228 // since we can't guarantee the destructors won't acquire that
2229 // same lock.
2230 tracksToRemove.clear();
2231 outputTracks.clear();
2232 }
2233
Eric Laurent9d91ad52009-07-17 12:17:14 -07002234 return false;
2235}
2236
2237void AudioFlinger::DuplicatingThread::addOutputTrack(MixerThread *thread)
2238{
2239 int frameCount = (3 * mFrameCount * mSampleRate) / thread->sampleRate();
2240 OutputTrack *outputTrack = new OutputTrack((ThreadBase *)thread,
Eric Laurent7e2aad12009-12-18 05:47:48 -08002241 this,
Eric Laurent9d91ad52009-07-17 12:17:14 -07002242 mSampleRate,
2243 mFormat,
2244 mChannelCount,
2245 frameCount);
Eric Laurentf5aba822009-08-10 23:22:32 -07002246 if (outputTrack->cblk() != NULL) {
2247 thread->setStreamVolume(AudioSystem::NUM_STREAM_TYPES, 1.0f);
2248 mOutputTracks.add(outputTrack);
2249 LOGV("addOutputTrack() track %p, on thread %p", outputTrack, thread);
Eric Laurent7e2aad12009-12-18 05:47:48 -08002250 updateWaitTime();
Eric Laurentf5aba822009-08-10 23:22:32 -07002251 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002252}
2253
2254void AudioFlinger::DuplicatingThread::removeOutputTrack(MixerThread *thread)
2255{
2256 Mutex::Autolock _l(mLock);
2257 for (size_t i = 0; i < mOutputTracks.size(); i++) {
2258 if (mOutputTracks[i]->thread() == (ThreadBase *)thread) {
Eric Laurentf5aba822009-08-10 23:22:32 -07002259 mOutputTracks[i]->destroy();
Eric Laurent9d91ad52009-07-17 12:17:14 -07002260 mOutputTracks.removeAt(i);
Eric Laurent7e2aad12009-12-18 05:47:48 -08002261 updateWaitTime();
Eric Laurent9d91ad52009-07-17 12:17:14 -07002262 return;
2263 }
2264 }
2265 LOGV("removeOutputTrack(): unkonwn thread: %p", thread);
2266}
2267
Eric Laurent7e2aad12009-12-18 05:47:48 -08002268void AudioFlinger::DuplicatingThread::updateWaitTime()
2269{
2270 mWaitTimeMs = UINT_MAX;
2271 for (size_t i = 0; i < mOutputTracks.size(); i++) {
2272 sp<ThreadBase> strong = mOutputTracks[i]->thread().promote();
2273 if (strong != NULL) {
2274 uint32_t waitTimeMs = (strong->frameCount() * 2 * 1000) / strong->sampleRate();
2275 if (waitTimeMs < mWaitTimeMs) {
2276 mWaitTimeMs = waitTimeMs;
2277 }
2278 }
2279 }
2280}
2281
2282
2283bool AudioFlinger::DuplicatingThread::outputsReady(SortedVector< sp<OutputTrack> > &outputTracks)
2284{
2285 for (size_t i = 0; i < outputTracks.size(); i++) {
2286 sp <ThreadBase> thread = outputTracks[i]->thread().promote();
2287 if (thread == 0) {
2288 LOGW("DuplicatingThread::outputsReady() could not promote thread on output track %p", outputTracks[i].get());
2289 return false;
2290 }
2291 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
2292 if (playbackThread->standby() && !playbackThread->isSuspended()) {
2293 LOGV("DuplicatingThread output track %p on thread %p Not Ready", outputTracks[i].get(), thread.get());
2294 return false;
2295 }
2296 }
2297 return true;
2298}
2299
2300uint32_t AudioFlinger::DuplicatingThread::activeSleepTimeUs()
2301{
2302 return (mWaitTimeMs * 1000) / 2;
2303}
2304
Eric Laurent9d91ad52009-07-17 12:17:14 -07002305// ----------------------------------------------------------------------------
2306
The Android Open Source Project22f8def2009-03-09 11:52:12 -07002307// TrackBase constructor must be called with AudioFlinger::mLock held
Eric Laurent9d91ad52009-07-17 12:17:14 -07002308AudioFlinger::ThreadBase::TrackBase::TrackBase(
2309 const wp<ThreadBase>& thread,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002310 const sp<Client>& client,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002311 uint32_t sampleRate,
2312 int format,
2313 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002314 int frameCount,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002315 uint32_t flags,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002316 const sp<IMemory>& sharedBuffer)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002317 : RefBase(),
Eric Laurent9d91ad52009-07-17 12:17:14 -07002318 mThread(thread),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002319 mClient(client),
Eric Laurent6ad8c642009-09-09 05:16:08 -07002320 mCblk(0),
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002321 mFrameCount(0),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002322 mState(IDLE),
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002323 mClientTid(-1),
2324 mFormat(format),
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002325 mFlags(flags & ~SYSTEM_FLAGS_MASK)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002326{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002327 LOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size());
2328
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002329 // LOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002330 size_t size = sizeof(audio_track_cblk_t);
2331 size_t bufferSize = frameCount*channelCount*sizeof(int16_t);
2332 if (sharedBuffer == 0) {
2333 size += bufferSize;
2334 }
2335
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002336 if (client != NULL) {
2337 mCblkMemory = client->heap()->allocate(size);
2338 if (mCblkMemory != 0) {
2339 mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer());
2340 if (mCblk) { // construct the shared structure in-place.
2341 new(mCblk) audio_track_cblk_t();
2342 // clear all buffers
2343 mCblk->frameCount = frameCount;
Eric Laurent0bac5382009-07-07 07:10:45 -07002344 mCblk->sampleRate = sampleRate;
Eric Laurente1512162010-05-14 05:45:46 -07002345 mCblk->channelCount = (uint8_t)channelCount;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002346 if (sharedBuffer == 0) {
2347 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
2348 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
2349 // Force underrun condition to avoid false underrun callback until first data is
2350 // written to buffer
2351 mCblk->flowControlFlag = 1;
2352 } else {
2353 mBuffer = sharedBuffer->pointer();
2354 }
2355 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002356 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002357 } else {
2358 LOGE("not enough memory for AudioTrack size=%u", size);
2359 client->heap()->dump("AudioTrack");
2360 return;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002361 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002362 } else {
2363 mCblk = (audio_track_cblk_t *)(new uint8_t[size]);
2364 if (mCblk) { // construct the shared structure in-place.
2365 new(mCblk) audio_track_cblk_t();
2366 // clear all buffers
2367 mCblk->frameCount = frameCount;
Eric Laurent0bac5382009-07-07 07:10:45 -07002368 mCblk->sampleRate = sampleRate;
Eric Laurente1512162010-05-14 05:45:46 -07002369 mCblk->channelCount = (uint8_t)channelCount;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002370 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
2371 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
2372 // Force underrun condition to avoid false underrun callback until first data is
2373 // written to buffer
2374 mCblk->flowControlFlag = 1;
2375 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
2376 }
2377 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002378}
2379
Eric Laurentbdc0f842009-09-16 06:02:45 -07002380AudioFlinger::ThreadBase::TrackBase::~TrackBase()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002381{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002382 if (mCblk) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07002383 mCblk->~audio_track_cblk_t(); // destroy our shared-structure.
2384 if (mClient == NULL) {
2385 delete mCblk;
2386 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002387 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002388 mCblkMemory.clear(); // and free the shared memory
Eric Laurent0f8ab672009-09-17 05:12:56 -07002389 if (mClient != NULL) {
2390 Mutex::Autolock _l(mClient->audioFlinger()->mLock);
2391 mClient.clear();
2392 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002393}
2394
Eric Laurentbdc0f842009-09-16 06:02:45 -07002395void AudioFlinger::ThreadBase::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002396{
2397 buffer->raw = 0;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002398 mFrameCount = buffer->frameCount;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002399 step();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002400 buffer->frameCount = 0;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002401}
2402
Eric Laurentbdc0f842009-09-16 06:02:45 -07002403bool AudioFlinger::ThreadBase::TrackBase::step() {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002404 bool result;
2405 audio_track_cblk_t* cblk = this->cblk();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002406
2407 result = cblk->stepServer(mFrameCount);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002408 if (!result) {
2409 LOGV("stepServer failed acquiring cblk mutex");
2410 mFlags |= STEPSERVER_FAILED;
2411 }
2412 return result;
2413}
2414
Eric Laurentbdc0f842009-09-16 06:02:45 -07002415void AudioFlinger::ThreadBase::TrackBase::reset() {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002416 audio_track_cblk_t* cblk = this->cblk();
2417
2418 cblk->user = 0;
2419 cblk->server = 0;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002420 cblk->userBase = 0;
2421 cblk->serverBase = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002422 mFlags &= (uint32_t)(~SYSTEM_FLAGS_MASK);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002423 LOGV("TrackBase::reset");
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002424}
2425
Eric Laurentbdc0f842009-09-16 06:02:45 -07002426sp<IMemory> AudioFlinger::ThreadBase::TrackBase::getCblk() const
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002427{
2428 return mCblkMemory;
2429}
2430
Eric Laurentbdc0f842009-09-16 06:02:45 -07002431int AudioFlinger::ThreadBase::TrackBase::sampleRate() const {
The Android Open Source Project4f68be12009-03-18 17:39:46 -07002432 return (int)mCblk->sampleRate;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002433}
2434
Eric Laurentbdc0f842009-09-16 06:02:45 -07002435int AudioFlinger::ThreadBase::TrackBase::channelCount() const {
Eric Laurente1512162010-05-14 05:45:46 -07002436 return (int)mCblk->channelCount;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002437}
2438
Eric Laurentbdc0f842009-09-16 06:02:45 -07002439void* AudioFlinger::ThreadBase::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002440 audio_track_cblk_t* cblk = this->cblk();
Eric Laurent9d91ad52009-07-17 12:17:14 -07002441 int8_t *bufferStart = (int8_t *)mBuffer + (offset-cblk->serverBase)*cblk->frameSize;
2442 int8_t *bufferEnd = bufferStart + frames * cblk->frameSize;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002443
2444 // Check validity of returned pointer in case the track control block would have been corrupted.
Eric Laurent9d91ad52009-07-17 12:17:14 -07002445 if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd ||
2446 ((unsigned long)bufferStart & (unsigned long)(cblk->frameSize - 1))) {
The Android Open Source Project4f68be12009-03-18 17:39:46 -07002447 LOGE("TrackBase::getBuffer buffer out of range:\n start: %p, end %p , mBuffer %p mBufferEnd %p\n \
Eric Laurente1512162010-05-14 05:45:46 -07002448 server %d, serverBase %d, user %d, userBase %d, channelCount %d",
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002449 bufferStart, bufferEnd, mBuffer, mBufferEnd,
Eric Laurente1512162010-05-14 05:45:46 -07002450 cblk->server, cblk->serverBase, cblk->user, cblk->userBase, cblk->channelCount);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002451 return 0;
2452 }
2453
2454 return bufferStart;
2455}
2456
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002457// ----------------------------------------------------------------------------
2458
Eric Laurent9d91ad52009-07-17 12:17:14 -07002459// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
2460AudioFlinger::PlaybackThread::Track::Track(
2461 const wp<ThreadBase>& thread,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002462 const sp<Client>& client,
2463 int streamType,
2464 uint32_t sampleRate,
2465 int format,
2466 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002467 int frameCount,
2468 const sp<IMemory>& sharedBuffer)
Eric Laurent9d91ad52009-07-17 12:17:14 -07002469 : TrackBase(thread, client, sampleRate, format, channelCount, frameCount, 0, sharedBuffer),
2470 mMute(false), mSharedBuffer(sharedBuffer), mName(-1)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002471{
Eric Laurent6ad8c642009-09-09 05:16:08 -07002472 if (mCblk != NULL) {
2473 sp<ThreadBase> baseThread = thread.promote();
2474 if (baseThread != 0) {
2475 PlaybackThread *playbackThread = (PlaybackThread *)baseThread.get();
2476 mName = playbackThread->getTrackName_l();
2477 }
2478 LOGV("Track constructor name %d, calling thread %d", mName, IPCThreadState::self()->getCallingPid());
2479 if (mName < 0) {
2480 LOGE("no more track names available");
2481 }
2482 mVolume[0] = 1.0f;
2483 mVolume[1] = 1.0f;
2484 mStreamType = streamType;
2485 // NOTE: audio_track_cblk_t::frameSize for 8 bit PCM data is based on a sample size of
2486 // 16 bit because data is converted to 16 bit before being stored in buffer by AudioTrack
2487 mCblk->frameSize = AudioSystem::isLinearPCM(format) ? channelCount * sizeof(int16_t) : sizeof(int8_t);
Eric Laurent9d91ad52009-07-17 12:17:14 -07002488 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002489}
2490
Eric Laurent9d91ad52009-07-17 12:17:14 -07002491AudioFlinger::PlaybackThread::Track::~Track()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002492{
Eric Laurent9d91ad52009-07-17 12:17:14 -07002493 LOGV("PlaybackThread::Track destructor");
2494 sp<ThreadBase> thread = mThread.promote();
2495 if (thread != 0) {
Eric Laurentd3fc8ac2009-12-01 02:17:41 -08002496 Mutex::Autolock _l(thread->mLock);
Eric Laurent9d91ad52009-07-17 12:17:14 -07002497 mState = TERMINATED;
The Android Open Source Project22f8def2009-03-09 11:52:12 -07002498 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002499}
2500
Eric Laurent9d91ad52009-07-17 12:17:14 -07002501void AudioFlinger::PlaybackThread::Track::destroy()
2502{
2503 // NOTE: destroyTrack_l() can remove a strong reference to this Track
2504 // by removing it from mTracks vector, so there is a risk that this Tracks's
2505 // desctructor is called. As the destructor needs to lock mLock,
2506 // we must acquire a strong reference on this Track before locking mLock
2507 // here so that the destructor is called only when exiting this function.
2508 // On the other hand, as long as Track::destroy() is only called by
2509 // TrackHandle destructor, the TrackHandle still holds a strong ref on
2510 // this Track with its member mTrack.
2511 sp<Track> keep(this);
2512 { // scope for mLock
2513 sp<ThreadBase> thread = mThread.promote();
2514 if (thread != 0) {
Eric Laurentd3fc8ac2009-12-01 02:17:41 -08002515 if (!isOutputTrack()) {
2516 if (mState == ACTIVE || mState == RESUMING) {
2517 AudioSystem::stopOutput(thread->id(), (AudioSystem::stream_type)mStreamType);
2518 }
2519 AudioSystem::releaseOutput(thread->id());
Eric Laurent09b4ba82009-11-19 09:00:56 -08002520 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002521 Mutex::Autolock _l(thread->mLock);
2522 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
2523 playbackThread->destroyTrack_l(this);
2524 }
2525 }
2526}
2527
2528void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002529{
Eric Laurentee47d432009-11-07 00:01:32 -08002530 snprintf(buffer, size, " %5d %5d %3u %3u %3u %04u %1d %1d %1d %5u %5u %5u %08x %08x\n",
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002531 mName - AudioMixer::TRACK0,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002532 (mClient == NULL) ? getpid() : mClient->pid(),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002533 mStreamType,
2534 mFormat,
Eric Laurente1512162010-05-14 05:45:46 -07002535 mCblk->channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002536 mFrameCount,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002537 mState,
2538 mMute,
2539 mFillingUpStatus,
2540 mCblk->sampleRate,
2541 mCblk->volume[0],
2542 mCblk->volume[1],
2543 mCblk->server,
2544 mCblk->user);
2545}
2546
Eric Laurent9d91ad52009-07-17 12:17:14 -07002547status_t AudioFlinger::PlaybackThread::Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002548{
2549 audio_track_cblk_t* cblk = this->cblk();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002550 uint32_t framesReady;
2551 uint32_t framesReq = buffer->frameCount;
2552
2553 // Check if last stepServer failed, try to step now
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002554 if (mFlags & TrackBase::STEPSERVER_FAILED) {
2555 if (!step()) goto getNextBuffer_exit;
2556 LOGV("stepServer recovered");
2557 mFlags &= ~TrackBase::STEPSERVER_FAILED;
2558 }
2559
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002560 framesReady = cblk->framesReady();
2561
2562 if (LIKELY(framesReady)) {
2563 uint32_t s = cblk->server;
2564 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
2565
2566 bufferEnd = (cblk->loopEnd < bufferEnd) ? cblk->loopEnd : bufferEnd;
2567 if (framesReq > framesReady) {
2568 framesReq = framesReady;
2569 }
2570 if (s + framesReq > bufferEnd) {
2571 framesReq = bufferEnd - s;
2572 }
2573
2574 buffer->raw = getBuffer(s, framesReq);
2575 if (buffer->raw == 0) goto getNextBuffer_exit;
2576
2577 buffer->frameCount = framesReq;
2578 return NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002579 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002580
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002581getNextBuffer_exit:
2582 buffer->raw = 0;
2583 buffer->frameCount = 0;
Eric Laurentf5e868b2009-10-05 20:29:18 -07002584 LOGV("getNextBuffer() no more data for track %d on thread %p", mName, mThread.unsafe_get());
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002585 return NOT_ENOUGH_DATA;
2586}
2587
Eric Laurent9d91ad52009-07-17 12:17:14 -07002588bool AudioFlinger::PlaybackThread::Track::isReady() const {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002589 if (mFillingUpStatus != FS_FILLING) return true;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002590
2591 if (mCblk->framesReady() >= mCblk->frameCount ||
2592 mCblk->forceReady) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002593 mFillingUpStatus = FS_FILLED;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002594 mCblk->forceReady = 0;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002595 return true;
2596 }
2597 return false;
2598}
2599
Eric Laurent9d91ad52009-07-17 12:17:14 -07002600status_t AudioFlinger::PlaybackThread::Track::start()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002601{
Eric Laurent09b4ba82009-11-19 09:00:56 -08002602 status_t status = NO_ERROR;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002603 LOGV("start(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
2604 sp<ThreadBase> thread = mThread.promote();
2605 if (thread != 0) {
2606 Mutex::Autolock _l(thread->mLock);
Eric Laurent09b4ba82009-11-19 09:00:56 -08002607 int state = mState;
2608 // here the track could be either new, or restarted
2609 // in both cases "unstop" the track
2610 if (mState == PAUSED) {
2611 mState = TrackBase::RESUMING;
2612 LOGV("PAUSED => RESUMING (%d) on thread %p", mName, this);
2613 } else {
2614 mState = TrackBase::ACTIVE;
2615 LOGV("? => ACTIVE (%d) on thread %p", mName, this);
2616 }
2617
2618 if (!isOutputTrack() && state != ACTIVE && state != RESUMING) {
2619 thread->mLock.unlock();
2620 status = AudioSystem::startOutput(thread->id(), (AudioSystem::stream_type)mStreamType);
2621 thread->mLock.lock();
2622 }
2623 if (status == NO_ERROR) {
2624 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
2625 playbackThread->addTrack_l(this);
2626 } else {
2627 mState = state;
2628 }
2629 } else {
2630 status = BAD_VALUE;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002631 }
Eric Laurent09b4ba82009-11-19 09:00:56 -08002632 return status;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002633}
2634
Eric Laurent9d91ad52009-07-17 12:17:14 -07002635void AudioFlinger::PlaybackThread::Track::stop()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002636{
Eric Laurent9d91ad52009-07-17 12:17:14 -07002637 LOGV("stop(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
2638 sp<ThreadBase> thread = mThread.promote();
2639 if (thread != 0) {
2640 Mutex::Autolock _l(thread->mLock);
Eric Laurent09b4ba82009-11-19 09:00:56 -08002641 int state = mState;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002642 if (mState > STOPPED) {
2643 mState = STOPPED;
2644 // If the track is not active (PAUSED and buffers full), flush buffers
2645 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
2646 if (playbackThread->mActiveTracks.indexOf(this) < 0) {
2647 reset();
2648 }
Eric Laurentf5e868b2009-10-05 20:29:18 -07002649 LOGV("(> STOPPED) => STOPPED (%d) on thread %p", mName, playbackThread);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002650 }
Eric Laurent09b4ba82009-11-19 09:00:56 -08002651 if (!isOutputTrack() && (state == ACTIVE || state == RESUMING)) {
2652 thread->mLock.unlock();
2653 AudioSystem::stopOutput(thread->id(), (AudioSystem::stream_type)mStreamType);
2654 thread->mLock.lock();
2655 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002656 }
2657}
2658
Eric Laurent9d91ad52009-07-17 12:17:14 -07002659void AudioFlinger::PlaybackThread::Track::pause()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002660{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002661 LOGV("pause(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
Eric Laurent9d91ad52009-07-17 12:17:14 -07002662 sp<ThreadBase> thread = mThread.promote();
2663 if (thread != 0) {
2664 Mutex::Autolock _l(thread->mLock);
2665 if (mState == ACTIVE || mState == RESUMING) {
2666 mState = PAUSING;
Eric Laurentf5e868b2009-10-05 20:29:18 -07002667 LOGV("ACTIVE/RESUMING => PAUSING (%d) on thread %p", mName, thread.get());
Eric Laurent09b4ba82009-11-19 09:00:56 -08002668 if (!isOutputTrack()) {
2669 thread->mLock.unlock();
2670 AudioSystem::stopOutput(thread->id(), (AudioSystem::stream_type)mStreamType);
2671 thread->mLock.lock();
2672 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002673 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002674 }
2675}
2676
Eric Laurent9d91ad52009-07-17 12:17:14 -07002677void AudioFlinger::PlaybackThread::Track::flush()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002678{
2679 LOGV("flush(%d)", mName);
Eric Laurent9d91ad52009-07-17 12:17:14 -07002680 sp<ThreadBase> thread = mThread.promote();
2681 if (thread != 0) {
2682 Mutex::Autolock _l(thread->mLock);
2683 if (mState != STOPPED && mState != PAUSED && mState != PAUSING) {
2684 return;
2685 }
2686 // No point remaining in PAUSED state after a flush => go to
2687 // STOPPED state
2688 mState = STOPPED;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002689
Eric Laurent9d91ad52009-07-17 12:17:14 -07002690 mCblk->lock.lock();
2691 // NOTE: reset() will reset cblk->user and cblk->server with
2692 // the risk that at the same time, the AudioMixer is trying to read
2693 // data. In this case, getNextBuffer() would return a NULL pointer
2694 // as audio buffer => the AudioMixer code MUST always test that pointer
2695 // returned by getNextBuffer() is not NULL!
2696 reset();
2697 mCblk->lock.unlock();
2698 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002699}
2700
Eric Laurent9d91ad52009-07-17 12:17:14 -07002701void AudioFlinger::PlaybackThread::Track::reset()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002702{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002703 // Do not reset twice to avoid discarding data written just after a flush and before
2704 // the audioflinger thread detects the track is stopped.
2705 if (!mResetDone) {
2706 TrackBase::reset();
2707 // Force underrun condition to avoid false underrun callback until first data is
2708 // written to buffer
2709 mCblk->flowControlFlag = 1;
2710 mCblk->forceReady = 0;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002711 mFillingUpStatus = FS_FILLING;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002712 mResetDone = true;
2713 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002714}
2715
Eric Laurent9d91ad52009-07-17 12:17:14 -07002716void AudioFlinger::PlaybackThread::Track::mute(bool muted)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002717{
2718 mMute = muted;
2719}
2720
Eric Laurent9d91ad52009-07-17 12:17:14 -07002721void AudioFlinger::PlaybackThread::Track::setVolume(float left, float right)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002722{
2723 mVolume[0] = left;
2724 mVolume[1] = right;
2725}
2726
2727// ----------------------------------------------------------------------------
2728
The Android Open Source Project22f8def2009-03-09 11:52:12 -07002729// RecordTrack constructor must be called with AudioFlinger::mLock held
Eric Laurent9d91ad52009-07-17 12:17:14 -07002730AudioFlinger::RecordThread::RecordTrack::RecordTrack(
2731 const wp<ThreadBase>& thread,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002732 const sp<Client>& client,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002733 uint32_t sampleRate,
2734 int format,
2735 int channelCount,
2736 int frameCount,
2737 uint32_t flags)
Eric Laurent9d91ad52009-07-17 12:17:14 -07002738 : TrackBase(thread, client, sampleRate, format,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002739 channelCount, frameCount, flags, 0),
Eric Laurent9d91ad52009-07-17 12:17:14 -07002740 mOverflow(false)
2741{
Eric Laurent6ad8c642009-09-09 05:16:08 -07002742 if (mCblk != NULL) {
2743 LOGV("RecordTrack constructor, size %d", (int)mBufferEnd - (int)mBuffer);
2744 if (format == AudioSystem::PCM_16_BIT) {
2745 mCblk->frameSize = channelCount * sizeof(int16_t);
2746 } else if (format == AudioSystem::PCM_8_BIT) {
2747 mCblk->frameSize = channelCount * sizeof(int8_t);
2748 } else {
2749 mCblk->frameSize = sizeof(int8_t);
2750 }
2751 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002752}
2753
2754AudioFlinger::RecordThread::RecordTrack::~RecordTrack()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002755{
Eric Laurent09b4ba82009-11-19 09:00:56 -08002756 sp<ThreadBase> thread = mThread.promote();
2757 if (thread != 0) {
2758 AudioSystem::releaseInput(thread->id());
2759 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002760}
2761
Eric Laurent9d91ad52009-07-17 12:17:14 -07002762status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002763{
2764 audio_track_cblk_t* cblk = this->cblk();
2765 uint32_t framesAvail;
2766 uint32_t framesReq = buffer->frameCount;
2767
2768 // Check if last stepServer failed, try to step now
2769 if (mFlags & TrackBase::STEPSERVER_FAILED) {
2770 if (!step()) goto getNextBuffer_exit;
2771 LOGV("stepServer recovered");
2772 mFlags &= ~TrackBase::STEPSERVER_FAILED;
2773 }
2774
2775 framesAvail = cblk->framesAvailable_l();
2776
2777 if (LIKELY(framesAvail)) {
2778 uint32_t s = cblk->server;
2779 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
2780
2781 if (framesReq > framesAvail) {
2782 framesReq = framesAvail;
2783 }
2784 if (s + framesReq > bufferEnd) {
2785 framesReq = bufferEnd - s;
2786 }
2787
2788 buffer->raw = getBuffer(s, framesReq);
2789 if (buffer->raw == 0) goto getNextBuffer_exit;
2790
2791 buffer->frameCount = framesReq;
2792 return NO_ERROR;
2793 }
2794
2795getNextBuffer_exit:
2796 buffer->raw = 0;
2797 buffer->frameCount = 0;
2798 return NOT_ENOUGH_DATA;
2799}
2800
Eric Laurent9d91ad52009-07-17 12:17:14 -07002801status_t AudioFlinger::RecordThread::RecordTrack::start()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002802{
Eric Laurent9d91ad52009-07-17 12:17:14 -07002803 sp<ThreadBase> thread = mThread.promote();
2804 if (thread != 0) {
2805 RecordThread *recordThread = (RecordThread *)thread.get();
2806 return recordThread->start(this);
Eric Laurent09b4ba82009-11-19 09:00:56 -08002807 } else {
2808 return BAD_VALUE;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002809 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002810}
2811
Eric Laurent9d91ad52009-07-17 12:17:14 -07002812void AudioFlinger::RecordThread::RecordTrack::stop()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002813{
Eric Laurent9d91ad52009-07-17 12:17:14 -07002814 sp<ThreadBase> thread = mThread.promote();
2815 if (thread != 0) {
2816 RecordThread *recordThread = (RecordThread *)thread.get();
2817 recordThread->stop(this);
2818 TrackBase::reset();
2819 // Force overerrun condition to avoid false overrun callback until first data is
2820 // read from buffer
2821 mCblk->flowControlFlag = 1;
2822 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002823}
2824
Eric Laurentee47d432009-11-07 00:01:32 -08002825void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size)
2826{
2827 snprintf(buffer, size, " %05d %03u %03u %04u %01d %05u %08x %08x\n",
2828 (mClient == NULL) ? getpid() : mClient->pid(),
2829 mFormat,
Eric Laurente1512162010-05-14 05:45:46 -07002830 mCblk->channelCount,
Eric Laurentee47d432009-11-07 00:01:32 -08002831 mFrameCount,
2832 mState,
2833 mCblk->sampleRate,
2834 mCblk->server,
2835 mCblk->user);
2836}
2837
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002838
2839// ----------------------------------------------------------------------------
2840
Eric Laurent9d91ad52009-07-17 12:17:14 -07002841AudioFlinger::PlaybackThread::OutputTrack::OutputTrack(
2842 const wp<ThreadBase>& thread,
Eric Laurent7e2aad12009-12-18 05:47:48 -08002843 DuplicatingThread *sourceThread,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002844 uint32_t sampleRate,
2845 int format,
2846 int channelCount,
2847 int frameCount)
Eric Laurent9d91ad52009-07-17 12:17:14 -07002848 : Track(thread, NULL, AudioSystem::NUM_STREAM_TYPES, sampleRate, format, channelCount, frameCount, NULL),
Eric Laurent7e2aad12009-12-18 05:47:48 -08002849 mActive(false), mSourceThread(sourceThread)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002850{
Eric Laurent9d91ad52009-07-17 12:17:14 -07002851
2852 PlaybackThread *playbackThread = (PlaybackThread *)thread.unsafe_get();
Eric Laurentf5aba822009-08-10 23:22:32 -07002853 if (mCblk != NULL) {
2854 mCblk->out = 1;
2855 mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
2856 mCblk->volume[0] = mCblk->volume[1] = 0x1000;
2857 mOutBuffer.frameCount = 0;
Eric Laurentf5aba822009-08-10 23:22:32 -07002858 playbackThread->mTracks.add(this);
Eric Laurente1512162010-05-14 05:45:46 -07002859 LOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, mCblk->frameCount %d, mCblk->sampleRate %d, mCblk->channelCount %d mBufferEnd %p",
2860 mCblk, mBuffer, mCblk->buffers, mCblk->frameCount, mCblk->sampleRate, mCblk->channelCount, mBufferEnd);
Eric Laurentf5aba822009-08-10 23:22:32 -07002861 } else {
2862 LOGW("Error creating output track on thread %p", playbackThread);
2863 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002864}
2865
Eric Laurent9d91ad52009-07-17 12:17:14 -07002866AudioFlinger::PlaybackThread::OutputTrack::~OutputTrack()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002867{
Eric Laurentf5aba822009-08-10 23:22:32 -07002868 clearBufferQueue();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002869}
2870
Eric Laurent9d91ad52009-07-17 12:17:14 -07002871status_t AudioFlinger::PlaybackThread::OutputTrack::start()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002872{
2873 status_t status = Track::start();
Eric Laurent9d91ad52009-07-17 12:17:14 -07002874 if (status != NO_ERROR) {
2875 return status;
2876 }
2877
2878 mActive = true;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002879 mRetryCount = 127;
2880 return status;
2881}
2882
Eric Laurent9d91ad52009-07-17 12:17:14 -07002883void AudioFlinger::PlaybackThread::OutputTrack::stop()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002884{
2885 Track::stop();
2886 clearBufferQueue();
2887 mOutBuffer.frameCount = 0;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002888 mActive = false;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002889}
2890
Eric Laurent9d91ad52009-07-17 12:17:14 -07002891bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t frames)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002892{
2893 Buffer *pInBuffer;
2894 Buffer inBuffer;
Eric Laurente1512162010-05-14 05:45:46 -07002895 uint32_t channelCount = mCblk->channelCount;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002896 bool outputBufferFull = false;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002897 inBuffer.frameCount = frames;
2898 inBuffer.i16 = data;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002899
Eric Laurent7e2aad12009-12-18 05:47:48 -08002900 uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
Eric Laurent9d91ad52009-07-17 12:17:14 -07002901
Eric Laurentf5e868b2009-10-05 20:29:18 -07002902 if (!mActive && frames != 0) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07002903 start();
2904 sp<ThreadBase> thread = mThread.promote();
2905 if (thread != 0) {
2906 MixerThread *mixerThread = (MixerThread *)thread.get();
2907 if (mCblk->frameCount > frames){
2908 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
2909 uint32_t startFrames = (mCblk->frameCount - frames);
2910 pInBuffer = new Buffer;
Eric Laurente1512162010-05-14 05:45:46 -07002911 pInBuffer->mBuffer = new int16_t[startFrames * channelCount];
Eric Laurent9d91ad52009-07-17 12:17:14 -07002912 pInBuffer->frameCount = startFrames;
2913 pInBuffer->i16 = pInBuffer->mBuffer;
Eric Laurente1512162010-05-14 05:45:46 -07002914 memset(pInBuffer->raw, 0, startFrames * channelCount * sizeof(int16_t));
Eric Laurent9d91ad52009-07-17 12:17:14 -07002915 mBufferQueue.add(pInBuffer);
2916 } else {
2917 LOGW ("OutputTrack::write() %p no more buffers in queue", this);
2918 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002919 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002920 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002921 }
2922
Eric Laurent9d91ad52009-07-17 12:17:14 -07002923 while (waitTimeLeftMs) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002924 // First write pending buffers, then new data
2925 if (mBufferQueue.size()) {
2926 pInBuffer = mBufferQueue.itemAt(0);
2927 } else {
2928 pInBuffer = &inBuffer;
2929 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002930
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002931 if (pInBuffer->frameCount == 0) {
2932 break;
2933 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002934
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002935 if (mOutBuffer.frameCount == 0) {
2936 mOutBuffer.frameCount = pInBuffer->frameCount;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002937 nsecs_t startTime = systemTime();
2938 if (obtainBuffer(&mOutBuffer, waitTimeLeftMs) == (status_t)AudioTrack::NO_MORE_BUFFERS) {
Eric Laurent7e2aad12009-12-18 05:47:48 -08002939 LOGV ("OutputTrack::write() %p thread %p no more output buffers", this, mThread.unsafe_get());
Eric Laurent9d91ad52009-07-17 12:17:14 -07002940 outputBufferFull = true;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002941 break;
2942 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002943 uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
Eric Laurent9d91ad52009-07-17 12:17:14 -07002944 if (waitTimeLeftMs >= waitTimeMs) {
2945 waitTimeLeftMs -= waitTimeMs;
2946 } else {
2947 waitTimeLeftMs = 0;
2948 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002949 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002950
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002951 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount : pInBuffer->frameCount;
Eric Laurente1512162010-05-14 05:45:46 -07002952 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * channelCount * sizeof(int16_t));
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002953 mCblk->stepUser(outFrames);
2954 pInBuffer->frameCount -= outFrames;
Eric Laurente1512162010-05-14 05:45:46 -07002955 pInBuffer->i16 += outFrames * channelCount;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002956 mOutBuffer.frameCount -= outFrames;
Eric Laurente1512162010-05-14 05:45:46 -07002957 mOutBuffer.i16 += outFrames * channelCount;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002958
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002959 if (pInBuffer->frameCount == 0) {
2960 if (mBufferQueue.size()) {
2961 mBufferQueue.removeAt(0);
2962 delete [] pInBuffer->mBuffer;
2963 delete pInBuffer;
Eric Laurent7e2aad12009-12-18 05:47:48 -08002964 LOGV("OutputTrack::write() %p thread %p released overflow buffer %d", this, mThread.unsafe_get(), mBufferQueue.size());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002965 } else {
2966 break;
2967 }
2968 }
2969 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002970
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002971 // If we could not write all frames, allocate a buffer and queue it for next time.
2972 if (inBuffer.frameCount) {
Eric Laurent7e2aad12009-12-18 05:47:48 -08002973 sp<ThreadBase> thread = mThread.promote();
2974 if (thread != 0 && !thread->standby()) {
2975 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
2976 pInBuffer = new Buffer;
Eric Laurente1512162010-05-14 05:45:46 -07002977 pInBuffer->mBuffer = new int16_t[inBuffer.frameCount * channelCount];
Eric Laurent7e2aad12009-12-18 05:47:48 -08002978 pInBuffer->frameCount = inBuffer.frameCount;
2979 pInBuffer->i16 = pInBuffer->mBuffer;
Eric Laurente1512162010-05-14 05:45:46 -07002980 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * channelCount * sizeof(int16_t));
Eric Laurent7e2aad12009-12-18 05:47:48 -08002981 mBufferQueue.add(pInBuffer);
2982 LOGV("OutputTrack::write() %p thread %p adding overflow buffer %d", this, mThread.unsafe_get(), mBufferQueue.size());
2983 } else {
2984 LOGW("OutputTrack::write() %p thread %p no more overflow buffers", mThread.unsafe_get(), this);
2985 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002986 }
2987 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002988
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002989 // Calling write() with a 0 length buffer, means that no more data will be written:
Eric Laurent9d91ad52009-07-17 12:17:14 -07002990 // If no more buffers are pending, fill output track buffer to make sure it is started
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002991 // by output mixer.
Eric Laurent9d91ad52009-07-17 12:17:14 -07002992 if (frames == 0 && mBufferQueue.size() == 0) {
2993 if (mCblk->user < mCblk->frameCount) {
2994 frames = mCblk->frameCount - mCblk->user;
2995 pInBuffer = new Buffer;
Eric Laurente1512162010-05-14 05:45:46 -07002996 pInBuffer->mBuffer = new int16_t[frames * channelCount];
Eric Laurent9d91ad52009-07-17 12:17:14 -07002997 pInBuffer->frameCount = frames;
2998 pInBuffer->i16 = pInBuffer->mBuffer;
Eric Laurente1512162010-05-14 05:45:46 -07002999 memset(pInBuffer->raw, 0, frames * channelCount * sizeof(int16_t));
Eric Laurent9d91ad52009-07-17 12:17:14 -07003000 mBufferQueue.add(pInBuffer);
Eric Laurentf5e868b2009-10-05 20:29:18 -07003001 } else if (mActive) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07003002 stop();
3003 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08003004 }
3005
Eric Laurent9d91ad52009-07-17 12:17:14 -07003006 return outputBufferFull;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08003007}
3008
Eric Laurent9d91ad52009-07-17 12:17:14 -07003009status_t AudioFlinger::PlaybackThread::OutputTrack::obtainBuffer(AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08003010{
3011 int active;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08003012 status_t result;
3013 audio_track_cblk_t* cblk = mCblk;
3014 uint32_t framesReq = buffer->frameCount;
3015
Eric Laurent9d91ad52009-07-17 12:17:14 -07003016// LOGV("OutputTrack::obtainBuffer user %d, server %d", cblk->user, cblk->server);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08003017 buffer->frameCount = 0;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003018
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08003019 uint32_t framesAvail = cblk->framesAvailable();
3020
Eric Laurent9d91ad52009-07-17 12:17:14 -07003021
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08003022 if (framesAvail == 0) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07003023 Mutex::Autolock _l(cblk->lock);
3024 goto start_loop_here;
3025 while (framesAvail == 0) {
3026 active = mActive;
3027 if (UNLIKELY(!active)) {
3028 LOGV("Not active and NO_MORE_BUFFERS");
3029 return AudioTrack::NO_MORE_BUFFERS;
3030 }
3031 result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
3032 if (result != NO_ERROR) {
3033 return AudioTrack::NO_MORE_BUFFERS;
3034 }
3035 // read the server count again
3036 start_loop_here:
3037 framesAvail = cblk->framesAvailable_l();
3038 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08003039 }
3040
Eric Laurent9d91ad52009-07-17 12:17:14 -07003041// if (framesAvail < framesReq) {
3042// return AudioTrack::NO_MORE_BUFFERS;
3043// }
3044
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08003045 if (framesReq > framesAvail) {
3046 framesReq = framesAvail;
3047 }
3048
3049 uint32_t u = cblk->user;
3050 uint32_t bufferEnd = cblk->userBase + cblk->frameCount;
3051
3052 if (u + framesReq > bufferEnd) {
3053 framesReq = bufferEnd - u;
3054 }
3055
3056 buffer->frameCount = framesReq;
3057 buffer->raw = (void *)cblk->buffer(u);
3058 return NO_ERROR;
3059}
3060
3061
Eric Laurent9d91ad52009-07-17 12:17:14 -07003062void AudioFlinger::PlaybackThread::OutputTrack::clearBufferQueue()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08003063{
3064 size_t size = mBufferQueue.size();
3065 Buffer *pBuffer;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003066
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08003067 for (size_t i = 0; i < size; i++) {
3068 pBuffer = mBufferQueue.itemAt(i);
3069 delete [] pBuffer->mBuffer;
3070 delete pBuffer;
3071 }
3072 mBufferQueue.clear();
3073}
3074
3075// ----------------------------------------------------------------------------
3076
3077AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
3078 : RefBase(),
3079 mAudioFlinger(audioFlinger),
Mathias Agopian0dd0d292010-01-25 19:00:00 -08003080 mMemoryDealer(new MemoryDealer(1024*1024, "AudioFlinger::Client")),
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08003081 mPid(pid)
3082{
3083 // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
3084}
3085
Eric Laurent0f8ab672009-09-17 05:12:56 -07003086// Client destructor must be called with AudioFlinger::mLock held
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08003087AudioFlinger::Client::~Client()
3088{
Eric Laurent0f8ab672009-09-17 05:12:56 -07003089 mAudioFlinger->removeClient_l(mPid);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08003090}
3091
3092const sp<MemoryDealer>& AudioFlinger::Client::heap() const
3093{
3094 return mMemoryDealer;
3095}
3096
3097// ----------------------------------------------------------------------------
3098
Eric Laurentd878cd82010-05-12 02:05:53 -07003099AudioFlinger::NotificationClient::NotificationClient(const sp<AudioFlinger>& audioFlinger,
3100 const sp<IAudioFlingerClient>& client,
3101 pid_t pid)
3102 : mAudioFlinger(audioFlinger), mPid(pid), mClient(client)
3103{
3104}
3105
3106AudioFlinger::NotificationClient::~NotificationClient()
3107{
3108 mClient.clear();
3109}
3110
3111void AudioFlinger::NotificationClient::binderDied(const wp<IBinder>& who)
3112{
3113 sp<NotificationClient> keep(this);
3114 {
3115 mAudioFlinger->removeNotificationClient(mPid);
3116 }
3117}
3118
3119// ----------------------------------------------------------------------------
3120
Eric Laurent9d91ad52009-07-17 12:17:14 -07003121AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::PlaybackThread::Track>& track)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003122 : BnAudioTrack(),
3123 mTrack(track)
3124{
3125}
3126
3127AudioFlinger::TrackHandle::~TrackHandle() {
3128 // just stop the track on deletion, associated resources
3129 // will be freed from the main thread once all pending buffers have
3130 // been played. Unless it's not in the active track list, in which
3131 // case we free everything now...
3132 mTrack->destroy();
3133}
3134
3135status_t AudioFlinger::TrackHandle::start() {
3136 return mTrack->start();
3137}
3138
3139void AudioFlinger::TrackHandle::stop() {
3140 mTrack->stop();
3141}
3142
3143void AudioFlinger::TrackHandle::flush() {
3144 mTrack->flush();
3145}
3146
3147void AudioFlinger::TrackHandle::mute(bool e) {
3148 mTrack->mute(e);
3149}
3150
3151void AudioFlinger::TrackHandle::pause() {
3152 mTrack->pause();
3153}
3154
3155void AudioFlinger::TrackHandle::setVolume(float left, float right) {
3156 mTrack->setVolume(left, right);
3157}
3158
3159sp<IMemory> AudioFlinger::TrackHandle::getCblk() const {
3160 return mTrack->getCblk();
3161}
3162
3163status_t AudioFlinger::TrackHandle::onTransact(
3164 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
3165{
3166 return BnAudioTrack::onTransact(code, data, reply, flags);
3167}
3168
3169// ----------------------------------------------------------------------------
3170
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003171sp<IAudioRecord> AudioFlinger::openRecord(
3172 pid_t pid,
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003173 int input,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003174 uint32_t sampleRate,
3175 int format,
3176 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08003177 int frameCount,
3178 uint32_t flags,
3179 status_t *status)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003180{
Eric Laurent9d91ad52009-07-17 12:17:14 -07003181 sp<RecordThread::RecordTrack> recordTrack;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003182 sp<RecordHandle> recordHandle;
3183 sp<Client> client;
3184 wp<Client> wclient;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08003185 status_t lStatus;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003186 RecordThread *thread;
3187 size_t inFrameCount;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003188
3189 // check calling permissions
3190 if (!recordingAllowed()) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08003191 lStatus = PERMISSION_DENIED;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003192 goto Exit;
3193 }
3194
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003195 // add client to list
The Android Open Source Project22f8def2009-03-09 11:52:12 -07003196 { // scope for mLock
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003197 Mutex::Autolock _l(mLock);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003198 thread = checkRecordThread_l(input);
3199 if (thread == NULL) {
3200 lStatus = BAD_VALUE;
3201 goto Exit;
3202 }
3203
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003204 wclient = mClients.valueFor(pid);
3205 if (wclient != NULL) {
3206 client = wclient.promote();
3207 } else {
3208 client = new Client(this, pid);
3209 mClients.add(pid, client);
3210 }
The Android Open Source Project22f8def2009-03-09 11:52:12 -07003211
The Android Open Source Project22f8def2009-03-09 11:52:12 -07003212 // create new record track. The record track uses one track in mHardwareMixerThread by convention.
Eric Laurent9d91ad52009-07-17 12:17:14 -07003213 recordTrack = new RecordThread::RecordTrack(thread, client, sampleRate,
The Android Open Source Project22f8def2009-03-09 11:52:12 -07003214 format, channelCount, frameCount, flags);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003215 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08003216 if (recordTrack->getCblk() == NULL) {
Eric Laurent0f8ab672009-09-17 05:12:56 -07003217 // remove local strong reference to Client before deleting the RecordTrack so that the Client
3218 // destructor is called by the TrackBase destructor with mLock held
3219 client.clear();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08003220 recordTrack.clear();
3221 lStatus = NO_MEMORY;
3222 goto Exit;
3223 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003224
3225 // return to handle to client
3226 recordHandle = new RecordHandle(recordTrack);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08003227 lStatus = NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003228
3229Exit:
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08003230 if (status) {
3231 *status = lStatus;
3232 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003233 return recordHandle;
3234}
3235
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003236// ----------------------------------------------------------------------------
3237
Eric Laurent9d91ad52009-07-17 12:17:14 -07003238AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::RecordThread::RecordTrack>& recordTrack)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003239 : BnAudioRecord(),
3240 mRecordTrack(recordTrack)
3241{
3242}
3243
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08003244AudioFlinger::RecordHandle::~RecordHandle() {
3245 stop();
3246}
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003247
3248status_t AudioFlinger::RecordHandle::start() {
3249 LOGV("RecordHandle::start()");
3250 return mRecordTrack->start();
3251}
3252
3253void AudioFlinger::RecordHandle::stop() {
3254 LOGV("RecordHandle::stop()");
3255 mRecordTrack->stop();
3256}
3257
3258sp<IMemory> AudioFlinger::RecordHandle::getCblk() const {
3259 return mRecordTrack->getCblk();
3260}
3261
3262status_t AudioFlinger::RecordHandle::onTransact(
3263 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
3264{
3265 return BnAudioRecord::onTransact(code, data, reply, flags);
3266}
3267
3268// ----------------------------------------------------------------------------
3269
Eric Laurent09b4ba82009-11-19 09:00:56 -08003270AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, AudioStreamIn *input, uint32_t sampleRate, uint32_t channels, int id) :
3271 ThreadBase(audioFlinger, id),
Eric Laurent9d91ad52009-07-17 12:17:14 -07003272 mInput(input), mResampler(0), mRsmpOutBuffer(0), mRsmpInBuffer(0)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003273{
Eric Laurent9d91ad52009-07-17 12:17:14 -07003274 mReqChannelCount = AudioSystem::popCount(channels);
3275 mReqSampleRate = sampleRate;
3276 readInputParameters();
3277 sendConfigEvent(AudioSystem::INPUT_OPENED);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003278}
3279
Eric Laurent9d91ad52009-07-17 12:17:14 -07003280
3281AudioFlinger::RecordThread::~RecordThread()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003282{
Eric Laurent9d91ad52009-07-17 12:17:14 -07003283 delete[] mRsmpInBuffer;
3284 if (mResampler != 0) {
3285 delete mResampler;
3286 delete[] mRsmpOutBuffer;
3287 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003288}
3289
Eric Laurent9d91ad52009-07-17 12:17:14 -07003290void AudioFlinger::RecordThread::onFirstRef()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003291{
Eric Laurent9d91ad52009-07-17 12:17:14 -07003292 const size_t SIZE = 256;
3293 char buffer[SIZE];
3294
3295 snprintf(buffer, SIZE, "Record Thread %p", this);
3296
3297 run(buffer, PRIORITY_URGENT_AUDIO);
3298}
Eric Laurent09b4ba82009-11-19 09:00:56 -08003299
Eric Laurent9d91ad52009-07-17 12:17:14 -07003300bool AudioFlinger::RecordThread::threadLoop()
3301{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08003302 AudioBufferProvider::Buffer buffer;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003303 sp<RecordTrack> activeTrack;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003304
3305 // start recording
3306 while (!exitPending()) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08003307
Eric Laurent9d91ad52009-07-17 12:17:14 -07003308 processConfigEvents();
3309
3310 { // scope for mLock
3311 Mutex::Autolock _l(mLock);
3312 checkForNewParameters_l();
3313 if (mActiveTrack == 0 && mConfigEvents.isEmpty()) {
3314 if (!mStandby) {
3315 mInput->standby();
3316 mStandby = true;
3317 }
3318
3319 if (exitPending()) break;
3320
3321 LOGV("RecordThread: loop stopping");
3322 // go to sleep
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003323 mWaitWorkCV.wait(mLock);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003324 LOGV("RecordThread: loop starting");
3325 continue;
3326 }
3327 if (mActiveTrack != 0) {
3328 if (mActiveTrack->mState == TrackBase::PAUSING) {
Eric Laurent52910952009-12-05 05:20:01 -08003329 if (!mStandby) {
3330 mInput->standby();
3331 mStandby = true;
3332 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07003333 mActiveTrack.clear();
3334 mStartStopCond.broadcast();
3335 } else if (mActiveTrack->mState == TrackBase::RESUMING) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07003336 if (mReqChannelCount != mActiveTrack->channelCount()) {
3337 mActiveTrack.clear();
Eric Laurent52910952009-12-05 05:20:01 -08003338 mStartStopCond.broadcast();
3339 } else if (mBytesRead != 0) {
3340 // record start succeeds only if first read from audio input
3341 // succeeds
3342 if (mBytesRead > 0) {
3343 mActiveTrack->mState = TrackBase::ACTIVE;
3344 } else {
3345 mActiveTrack.clear();
3346 }
3347 mStartStopCond.broadcast();
Eric Laurent9d91ad52009-07-17 12:17:14 -07003348 }
Eric Laurent52910952009-12-05 05:20:01 -08003349 mStandby = false;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003350 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07003351 }
3352 }
3353
3354 if (mActiveTrack != 0) {
Eric Laurent52910952009-12-05 05:20:01 -08003355 if (mActiveTrack->mState != TrackBase::ACTIVE &&
3356 mActiveTrack->mState != TrackBase::RESUMING) {
Eric Laurent09b4ba82009-11-19 09:00:56 -08003357 usleep(5000);
3358 continue;
3359 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07003360 buffer.frameCount = mFrameCount;
3361 if (LIKELY(mActiveTrack->getNextBuffer(&buffer) == NO_ERROR)) {
3362 size_t framesOut = buffer.frameCount;
3363 if (mResampler == 0) {
3364 // no resampling
3365 while (framesOut) {
3366 size_t framesIn = mFrameCount - mRsmpInIndex;
3367 if (framesIn) {
3368 int8_t *src = (int8_t *)mRsmpInBuffer + mRsmpInIndex * mFrameSize;
3369 int8_t *dst = buffer.i8 + (buffer.frameCount - framesOut) * mActiveTrack->mCblk->frameSize;
3370 if (framesIn > framesOut)
3371 framesIn = framesOut;
3372 mRsmpInIndex += framesIn;
3373 framesOut -= framesIn;
Eric Laurente1512162010-05-14 05:45:46 -07003374 if ((int)mChannelCount == mReqChannelCount ||
Eric Laurent9d91ad52009-07-17 12:17:14 -07003375 mFormat != AudioSystem::PCM_16_BIT) {
3376 memcpy(dst, src, framesIn * mFrameSize);
3377 } else {
3378 int16_t *src16 = (int16_t *)src;
3379 int16_t *dst16 = (int16_t *)dst;
3380 if (mChannelCount == 1) {
3381 while (framesIn--) {
3382 *dst16++ = *src16;
3383 *dst16++ = *src16++;
3384 }
3385 } else {
3386 while (framesIn--) {
3387 *dst16++ = (int16_t)(((int32_t)*src16 + (int32_t)*(src16 + 1)) >> 1);
3388 src16 += 2;
3389 }
3390 }
3391 }
3392 }
3393 if (framesOut && mFrameCount == mRsmpInIndex) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07003394 if (framesOut == mFrameCount &&
Eric Laurente1512162010-05-14 05:45:46 -07003395 ((int)mChannelCount == mReqChannelCount || mFormat != AudioSystem::PCM_16_BIT)) {
Eric Laurent52910952009-12-05 05:20:01 -08003396 mBytesRead = mInput->read(buffer.raw, mInputBytes);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003397 framesOut = 0;
3398 } else {
Eric Laurent52910952009-12-05 05:20:01 -08003399 mBytesRead = mInput->read(mRsmpInBuffer, mInputBytes);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003400 mRsmpInIndex = 0;
3401 }
Eric Laurent52910952009-12-05 05:20:01 -08003402 if (mBytesRead < 0) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07003403 LOGE("Error reading audio input");
Eric Laurent52910952009-12-05 05:20:01 -08003404 if (mActiveTrack->mState == TrackBase::ACTIVE) {
Eric Laurent4f1fcc22010-03-02 18:38:06 -08003405 // Force input into standby so that it tries to
3406 // recover at next read attempt
3407 mInput->standby();
3408 usleep(5000);
Eric Laurent52910952009-12-05 05:20:01 -08003409 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07003410 mRsmpInIndex = mFrameCount;
3411 framesOut = 0;
3412 buffer.frameCount = 0;
3413 }
3414 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08003415 }
3416 } else {
Eric Laurent9d91ad52009-07-17 12:17:14 -07003417 // resampling
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003418
Eric Laurent9d91ad52009-07-17 12:17:14 -07003419 memset(mRsmpOutBuffer, 0, framesOut * 2 * sizeof(int32_t));
3420 // alter output frame count as if we were expecting stereo samples
3421 if (mChannelCount == 1 && mReqChannelCount == 1) {
3422 framesOut >>= 1;
3423 }
3424 mResampler->resample(mRsmpOutBuffer, framesOut, this);
3425 // ditherAndClamp() works as long as all buffers returned by mActiveTrack->getNextBuffer()
3426 // are 32 bit aligned which should be always true.
3427 if (mChannelCount == 2 && mReqChannelCount == 1) {
3428 AudioMixer::ditherAndClamp(mRsmpOutBuffer, mRsmpOutBuffer, framesOut);
3429 // the resampler always outputs stereo samples: do post stereo to mono conversion
3430 int16_t *src = (int16_t *)mRsmpOutBuffer;
3431 int16_t *dst = buffer.i16;
3432 while (framesOut--) {
3433 *dst++ = (int16_t)(((int32_t)*src + (int32_t)*(src + 1)) >> 1);
3434 src += 2;
3435 }
3436 } else {
3437 AudioMixer::ditherAndClamp((int32_t *)buffer.raw, mRsmpOutBuffer, framesOut);
3438 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003439
Eric Laurent9d91ad52009-07-17 12:17:14 -07003440 }
3441 mActiveTrack->releaseBuffer(&buffer);
3442 mActiveTrack->overflow();
3443 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003444 // client isn't retrieving buffers fast enough
3445 else {
Eric Laurent9d91ad52009-07-17 12:17:14 -07003446 if (!mActiveTrack->setOverflow())
3447 LOGW("RecordThread: buffer overflow");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08003448 // Release the processor for a while before asking for a new buffer.
3449 // This will give the application more chance to read from the buffer and
3450 // clear the overflow.
3451 usleep(5000);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003452 }
3453 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08003454 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003455
Eric Laurent9d91ad52009-07-17 12:17:14 -07003456 if (!mStandby) {
3457 mInput->standby();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08003458 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07003459 mActiveTrack.clear();
3460
Eric Laurent09b4ba82009-11-19 09:00:56 -08003461 mStartStopCond.broadcast();
3462
Eric Laurent9d91ad52009-07-17 12:17:14 -07003463 LOGV("RecordThread %p exiting", this);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003464 return false;
3465}
3466
Eric Laurent9d91ad52009-07-17 12:17:14 -07003467status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003468{
Eric Laurent9d91ad52009-07-17 12:17:14 -07003469 LOGV("RecordThread::start");
Eric Laurent09b4ba82009-11-19 09:00:56 -08003470 sp <ThreadBase> strongMe = this;
3471 status_t status = NO_ERROR;
3472 {
3473 AutoMutex lock(&mLock);
3474 if (mActiveTrack != 0) {
3475 if (recordTrack != mActiveTrack.get()) {
3476 status = -EBUSY;
3477 } else if (mActiveTrack->mState == TrackBase::PAUSING) {
Eric Laurent52910952009-12-05 05:20:01 -08003478 mActiveTrack->mState = TrackBase::ACTIVE;
Eric Laurent09b4ba82009-11-19 09:00:56 -08003479 }
3480 return status;
3481 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003482
Eric Laurent09b4ba82009-11-19 09:00:56 -08003483 recordTrack->mState = TrackBase::IDLE;
3484 mActiveTrack = recordTrack;
3485 mLock.unlock();
3486 status_t status = AudioSystem::startInput(mId);
3487 mLock.lock();
3488 if (status != NO_ERROR) {
3489 mActiveTrack.clear();
3490 return status;
3491 }
3492 mActiveTrack->mState = TrackBase::RESUMING;
Eric Laurent52910952009-12-05 05:20:01 -08003493 mRsmpInIndex = mFrameCount;
3494 mBytesRead = 0;
Eric Laurent09b4ba82009-11-19 09:00:56 -08003495 // signal thread to start
3496 LOGV("Signal record thread");
3497 mWaitWorkCV.signal();
3498 // do not wait for mStartStopCond if exiting
3499 if (mExiting) {
3500 mActiveTrack.clear();
3501 status = INVALID_OPERATION;
3502 goto startError;
3503 }
3504 mStartStopCond.wait(mLock);
3505 if (mActiveTrack == 0) {
3506 LOGV("Record failed to start");
3507 status = BAD_VALUE;
3508 goto startError;
3509 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07003510 LOGV("Record started OK");
Eric Laurent09b4ba82009-11-19 09:00:56 -08003511 return status;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003512 }
Eric Laurent09b4ba82009-11-19 09:00:56 -08003513startError:
3514 AudioSystem::stopInput(mId);
3515 return status;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003516}
3517
Eric Laurent9d91ad52009-07-17 12:17:14 -07003518void AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) {
3519 LOGV("RecordThread::stop");
Eric Laurent09b4ba82009-11-19 09:00:56 -08003520 sp <ThreadBase> strongMe = this;
3521 {
3522 AutoMutex lock(&mLock);
3523 if (mActiveTrack != 0 && recordTrack == mActiveTrack.get()) {
3524 mActiveTrack->mState = TrackBase::PAUSING;
3525 // do not wait for mStartStopCond if exiting
3526 if (mExiting) {
3527 return;
3528 }
3529 mStartStopCond.wait(mLock);
3530 // if we have been restarted, recordTrack == mActiveTrack.get() here
3531 if (mActiveTrack == 0 || recordTrack != mActiveTrack.get()) {
3532 mLock.unlock();
3533 AudioSystem::stopInput(mId);
3534 mLock.lock();
Eric Laurent52910952009-12-05 05:20:01 -08003535 LOGV("Record stopped OK");
Eric Laurent09b4ba82009-11-19 09:00:56 -08003536 }
3537 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003538 }
3539}
3540
Eric Laurent9d91ad52009-07-17 12:17:14 -07003541status_t AudioFlinger::RecordThread::dump(int fd, const Vector<String16>& args)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08003542{
3543 const size_t SIZE = 256;
3544 char buffer[SIZE];
3545 String8 result;
3546 pid_t pid = 0;
3547
Eric Laurentee47d432009-11-07 00:01:32 -08003548 snprintf(buffer, SIZE, "\nInput thread %p internals\n", this);
3549 result.append(buffer);
3550
3551 if (mActiveTrack != 0) {
3552 result.append("Active Track:\n");
3553 result.append(" Clien Fmt Chn Buf S SRate Serv User\n");
3554 mActiveTrack->dump(buffer, SIZE);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08003555 result.append(buffer);
Eric Laurentee47d432009-11-07 00:01:32 -08003556
3557 snprintf(buffer, SIZE, "In index: %d\n", mRsmpInIndex);
3558 result.append(buffer);
3559 snprintf(buffer, SIZE, "In size: %d\n", mInputBytes);
3560 result.append(buffer);
3561 snprintf(buffer, SIZE, "Resampling: %d\n", (mResampler != 0));
3562 result.append(buffer);
3563 snprintf(buffer, SIZE, "Out channel count: %d\n", mReqChannelCount);
3564 result.append(buffer);
3565 snprintf(buffer, SIZE, "Out sample rate: %d\n", mReqSampleRate);
3566 result.append(buffer);
3567
3568
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08003569 } else {
3570 result.append("No record client\n");
3571 }
3572 write(fd, result.string(), result.size());
Eric Laurentee47d432009-11-07 00:01:32 -08003573
3574 dumpBase(fd, args);
3575
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08003576 return NO_ERROR;
3577}
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003578
Eric Laurent9d91ad52009-07-17 12:17:14 -07003579status_t AudioFlinger::RecordThread::getNextBuffer(AudioBufferProvider::Buffer* buffer)
3580{
3581 size_t framesReq = buffer->frameCount;
3582 size_t framesReady = mFrameCount - mRsmpInIndex;
3583 int channelCount;
3584
3585 if (framesReady == 0) {
Eric Laurent52910952009-12-05 05:20:01 -08003586 mBytesRead = mInput->read(mRsmpInBuffer, mInputBytes);
3587 if (mBytesRead < 0) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07003588 LOGE("RecordThread::getNextBuffer() Error reading audio input");
Eric Laurent52910952009-12-05 05:20:01 -08003589 if (mActiveTrack->mState == TrackBase::ACTIVE) {
Eric Laurent4f1fcc22010-03-02 18:38:06 -08003590 // Force input into standby so that it tries to
3591 // recover at next read attempt
3592 mInput->standby();
3593 usleep(5000);
Eric Laurent52910952009-12-05 05:20:01 -08003594 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07003595 buffer->raw = 0;
3596 buffer->frameCount = 0;
3597 return NOT_ENOUGH_DATA;
3598 }
3599 mRsmpInIndex = 0;
3600 framesReady = mFrameCount;
3601 }
3602
3603 if (framesReq > framesReady) {
3604 framesReq = framesReady;
3605 }
3606
3607 if (mChannelCount == 1 && mReqChannelCount == 2) {
3608 channelCount = 1;
3609 } else {
3610 channelCount = 2;
3611 }
3612 buffer->raw = mRsmpInBuffer + mRsmpInIndex * channelCount;
3613 buffer->frameCount = framesReq;
3614 return NO_ERROR;
3615}
3616
3617void AudioFlinger::RecordThread::releaseBuffer(AudioBufferProvider::Buffer* buffer)
3618{
3619 mRsmpInIndex += buffer->frameCount;
3620 buffer->frameCount = 0;
3621}
3622
3623bool AudioFlinger::RecordThread::checkForNewParameters_l()
3624{
3625 bool reconfig = false;
3626
Eric Laurent3464c012009-08-04 09:45:33 -07003627 while (!mNewParameters.isEmpty()) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07003628 status_t status = NO_ERROR;
Eric Laurent3464c012009-08-04 09:45:33 -07003629 String8 keyValuePair = mNewParameters[0];
3630 AudioParameter param = AudioParameter(keyValuePair);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003631 int value;
3632 int reqFormat = mFormat;
3633 int reqSamplingRate = mReqSampleRate;
3634 int reqChannelCount = mReqChannelCount;
Eric Laurent3464c012009-08-04 09:45:33 -07003635
Eric Laurent9d91ad52009-07-17 12:17:14 -07003636 if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
3637 reqSamplingRate = value;
3638 reconfig = true;
3639 }
3640 if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
3641 reqFormat = value;
3642 reconfig = true;
3643 }
3644 if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
3645 reqChannelCount = AudioSystem::popCount(value);
3646 reconfig = true;
3647 }
3648 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
3649 // do not accept frame count changes if tracks are open as the track buffer
3650 // size depends on frame count and correct behavior would not be garantied
3651 // if frame count is changed after track creation
3652 if (mActiveTrack != 0) {
3653 status = INVALID_OPERATION;
3654 } else {
3655 reconfig = true;
3656 }
3657 }
3658 if (status == NO_ERROR) {
Eric Laurent3464c012009-08-04 09:45:33 -07003659 status = mInput->setParameters(keyValuePair);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003660 if (status == INVALID_OPERATION) {
3661 mInput->standby();
Eric Laurent3464c012009-08-04 09:45:33 -07003662 status = mInput->setParameters(keyValuePair);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003663 }
3664 if (reconfig) {
3665 if (status == BAD_VALUE &&
3666 reqFormat == mInput->format() && reqFormat == AudioSystem::PCM_16_BIT &&
3667 ((int)mInput->sampleRate() <= 2 * reqSamplingRate) &&
3668 (AudioSystem::popCount(mInput->channels()) < 3) && (reqChannelCount < 3)) {
3669 status = NO_ERROR;
3670 }
3671 if (status == NO_ERROR) {
3672 readInputParameters();
Eric Laurent3464c012009-08-04 09:45:33 -07003673 sendConfigEvent_l(AudioSystem::INPUT_CONFIG_CHANGED);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003674 }
3675 }
3676 }
Eric Laurentee47d432009-11-07 00:01:32 -08003677
3678 mNewParameters.removeAt(0);
3679
Eric Laurent9d91ad52009-07-17 12:17:14 -07003680 mParamStatus = status;
3681 mParamCond.signal();
Eric Laurent3464c012009-08-04 09:45:33 -07003682 mWaitWorkCV.wait(mLock);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003683 }
3684 return reconfig;
3685}
3686
3687String8 AudioFlinger::RecordThread::getParameters(const String8& keys)
3688{
3689 return mInput->getParameters(keys);
3690}
3691
3692void AudioFlinger::RecordThread::audioConfigChanged(int event, int param) {
3693 AudioSystem::OutputDescriptor desc;
3694 void *param2 = 0;
3695
3696 switch (event) {
3697 case AudioSystem::INPUT_OPENED:
3698 case AudioSystem::INPUT_CONFIG_CHANGED:
Eric Laurente1512162010-05-14 05:45:46 -07003699 desc.channels = mChannels;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003700 desc.samplingRate = mSampleRate;
3701 desc.format = mFormat;
3702 desc.frameCount = mFrameCount;
3703 desc.latency = 0;
3704 param2 = &desc;
3705 break;
3706
3707 case AudioSystem::INPUT_CLOSED:
3708 default:
3709 break;
3710 }
Eric Laurentb3687ae2009-09-15 07:10:12 -07003711 Mutex::Autolock _l(mAudioFlinger->mLock);
Eric Laurent09b4ba82009-11-19 09:00:56 -08003712 mAudioFlinger->audioConfigChanged_l(event, mId, param2);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003713}
3714
3715void AudioFlinger::RecordThread::readInputParameters()
3716{
3717 if (mRsmpInBuffer) delete mRsmpInBuffer;
3718 if (mRsmpOutBuffer) delete mRsmpOutBuffer;
3719 if (mResampler) delete mResampler;
3720 mResampler = 0;
3721
3722 mSampleRate = mInput->sampleRate();
Eric Laurente1512162010-05-14 05:45:46 -07003723 mChannels = mInput->channels();
3724 mChannelCount = (uint16_t)AudioSystem::popCount(mChannels);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003725 mFormat = mInput->format();
Eric Laurente1512162010-05-14 05:45:46 -07003726 mFrameSize = (uint16_t)mInput->frameSize();
Eric Laurent9d91ad52009-07-17 12:17:14 -07003727 mInputBytes = mInput->bufferSize();
3728 mFrameCount = mInputBytes / mFrameSize;
3729 mRsmpInBuffer = new int16_t[mFrameCount * mChannelCount];
3730
3731 if (mSampleRate != mReqSampleRate && mChannelCount < 3 && mReqChannelCount < 3)
3732 {
3733 int channelCount;
3734 // optmization: if mono to mono, use the resampler in stereo to stereo mode to avoid
3735 // stereo to mono post process as the resampler always outputs stereo.
3736 if (mChannelCount == 1 && mReqChannelCount == 2) {
3737 channelCount = 1;
3738 } else {
3739 channelCount = 2;
3740 }
3741 mResampler = AudioResampler::create(16, channelCount, mReqSampleRate);
3742 mResampler->setSampleRate(mSampleRate);
3743 mResampler->setVolume(AudioMixer::UNITY_GAIN, AudioMixer::UNITY_GAIN);
3744 mRsmpOutBuffer = new int32_t[mFrameCount * 2];
3745
3746 // optmization: if mono to mono, alter input frame count as if we were inputing stereo samples
3747 if (mChannelCount == 1 && mReqChannelCount == 1) {
3748 mFrameCount >>= 1;
3749 }
3750
3751 }
3752 mRsmpInIndex = mFrameCount;
3753}
3754
Eric Laurent134ccbd2010-02-26 02:47:27 -08003755unsigned int AudioFlinger::RecordThread::getInputFramesLost()
3756{
3757 return mInput->getInputFramesLost();
3758}
3759
Eric Laurent9d91ad52009-07-17 12:17:14 -07003760// ----------------------------------------------------------------------------
3761
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003762int AudioFlinger::openOutput(uint32_t *pDevices,
Eric Laurent9d91ad52009-07-17 12:17:14 -07003763 uint32_t *pSamplingRate,
3764 uint32_t *pFormat,
3765 uint32_t *pChannels,
3766 uint32_t *pLatencyMs,
3767 uint32_t flags)
3768{
3769 status_t status;
3770 PlaybackThread *thread = NULL;
3771 mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
3772 uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
3773 uint32_t format = pFormat ? *pFormat : 0;
3774 uint32_t channels = pChannels ? *pChannels : 0;
3775 uint32_t latency = pLatencyMs ? *pLatencyMs : 0;
3776
3777 LOGV("openOutput(), Device %x, SamplingRate %d, Format %d, Channels %x, flags %x",
3778 pDevices ? *pDevices : 0,
3779 samplingRate,
3780 format,
3781 channels,
3782 flags);
3783
3784 if (pDevices == NULL || *pDevices == 0) {
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003785 return 0;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003786 }
3787 Mutex::Autolock _l(mLock);
3788
3789 AudioStreamOut *output = mAudioHardware->openOutputStream(*pDevices,
3790 (int *)&format,
3791 &channels,
3792 &samplingRate,
3793 &status);
3794 LOGV("openOutput() openOutputStream returned output %p, SamplingRate %d, Format %d, Channels %x, status %d",
3795 output,
3796 samplingRate,
3797 format,
3798 channels,
3799 status);
3800
3801 mHardwareStatus = AUDIO_HW_IDLE;
3802 if (output != 0) {
3803 if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) ||
3804 (format != AudioSystem::PCM_16_BIT) ||
3805 (channels != AudioSystem::CHANNEL_OUT_STEREO)) {
Eric Laurent09b4ba82009-11-19 09:00:56 -08003806 thread = new DirectOutputThread(this, output, ++mNextThreadId);
3807 LOGV("openOutput() created direct output: ID %d thread %p", mNextThreadId, thread);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003808 } else {
Eric Laurent09b4ba82009-11-19 09:00:56 -08003809 thread = new MixerThread(this, output, ++mNextThreadId);
3810 LOGV("openOutput() created mixer output: ID %d thread %p", mNextThreadId, thread);
Glenn Kastend5ea9692010-03-05 12:18:01 -08003811
3812#ifdef LVMX
3813 unsigned bitsPerSample =
3814 (format == AudioSystem::PCM_16_BIT) ? 16 :
3815 ((format == AudioSystem::PCM_8_BIT) ? 8 : 0);
3816 unsigned channelCount = (channels == AudioSystem::CHANNEL_OUT_STEREO) ? 2 : 1;
3817 int audioOutputType = LifeVibes::threadIdToAudioOutputType(thread->id());
3818
3819 LifeVibes::init_aot(audioOutputType, samplingRate, bitsPerSample, channelCount);
3820 LifeVibes::setDevice(audioOutputType, *pDevices);
3821#endif
3822
Eric Laurent9d91ad52009-07-17 12:17:14 -07003823 }
Eric Laurent09b4ba82009-11-19 09:00:56 -08003824 mPlaybackThreads.add(mNextThreadId, thread);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003825
3826 if (pSamplingRate) *pSamplingRate = samplingRate;
3827 if (pFormat) *pFormat = format;
3828 if (pChannels) *pChannels = channels;
3829 if (pLatencyMs) *pLatencyMs = thread->latency();
Eric Laurent52910952009-12-05 05:20:01 -08003830
3831 return mNextThreadId;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003832 }
3833
Eric Laurent52910952009-12-05 05:20:01 -08003834 return 0;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003835}
3836
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003837int AudioFlinger::openDuplicateOutput(int output1, int output2)
Eric Laurent9d91ad52009-07-17 12:17:14 -07003838{
3839 Mutex::Autolock _l(mLock);
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003840 MixerThread *thread1 = checkMixerThread_l(output1);
3841 MixerThread *thread2 = checkMixerThread_l(output2);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003842
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003843 if (thread1 == NULL || thread2 == NULL) {
3844 LOGW("openDuplicateOutput() wrong output mixer type for output %d or %d", output1, output2);
3845 return 0;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003846 }
3847
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003848
Eric Laurent09b4ba82009-11-19 09:00:56 -08003849 DuplicatingThread *thread = new DuplicatingThread(this, thread1, ++mNextThreadId);
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003850 thread->addOutputTrack(thread2);
Eric Laurent09b4ba82009-11-19 09:00:56 -08003851 mPlaybackThreads.add(mNextThreadId, thread);
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003852 return mNextThreadId;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003853}
3854
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003855status_t AudioFlinger::closeOutput(int output)
Eric Laurent9d91ad52009-07-17 12:17:14 -07003856{
Eric Laurentdae20d92009-08-04 08:37:05 -07003857 // keep strong reference on the playback thread so that
3858 // it is not destroyed while exit() is executed
3859 sp <PlaybackThread> thread;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003860 {
3861 Mutex::Autolock _l(mLock);
3862 thread = checkPlaybackThread_l(output);
3863 if (thread == NULL) {
3864 return BAD_VALUE;
3865 }
3866
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003867 LOGV("closeOutput() %d", output);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003868
3869 if (thread->type() == PlaybackThread::MIXER) {
3870 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003871 if (mPlaybackThreads.valueAt(i)->type() == PlaybackThread::DUPLICATING) {
3872 DuplicatingThread *dupThread = (DuplicatingThread *)mPlaybackThreads.valueAt(i).get();
Eric Laurentdae20d92009-08-04 08:37:05 -07003873 dupThread->removeOutputTrack((MixerThread *)thread.get());
Eric Laurent9d91ad52009-07-17 12:17:14 -07003874 }
3875 }
3876 }
Eric Laurentb3687ae2009-09-15 07:10:12 -07003877 void *param2 = 0;
Eric Laurent09b4ba82009-11-19 09:00:56 -08003878 audioConfigChanged_l(AudioSystem::OUTPUT_CLOSED, output, param2);
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003879 mPlaybackThreads.removeItem(output);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003880 }
3881 thread->exit();
3882
Eric Laurentdae20d92009-08-04 08:37:05 -07003883 if (thread->type() != PlaybackThread::DUPLICATING) {
3884 mAudioHardware->closeOutputStream(thread->getOutput());
3885 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07003886 return NO_ERROR;
3887}
3888
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003889status_t AudioFlinger::suspendOutput(int output)
Eric Laurent9d91ad52009-07-17 12:17:14 -07003890{
3891 Mutex::Autolock _l(mLock);
3892 PlaybackThread *thread = checkPlaybackThread_l(output);
3893
3894 if (thread == NULL) {
3895 return BAD_VALUE;
3896 }
3897
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003898 LOGV("suspendOutput() %d", output);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003899 thread->suspend();
3900
3901 return NO_ERROR;
3902}
3903
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003904status_t AudioFlinger::restoreOutput(int output)
Eric Laurent9d91ad52009-07-17 12:17:14 -07003905{
3906 Mutex::Autolock _l(mLock);
3907 PlaybackThread *thread = checkPlaybackThread_l(output);
3908
3909 if (thread == NULL) {
3910 return BAD_VALUE;
3911 }
3912
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003913 LOGV("restoreOutput() %d", output);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003914
3915 thread->restore();
3916
3917 return NO_ERROR;
3918}
3919
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003920int AudioFlinger::openInput(uint32_t *pDevices,
Eric Laurent9d91ad52009-07-17 12:17:14 -07003921 uint32_t *pSamplingRate,
3922 uint32_t *pFormat,
3923 uint32_t *pChannels,
3924 uint32_t acoustics)
3925{
3926 status_t status;
3927 RecordThread *thread = NULL;
3928 uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
3929 uint32_t format = pFormat ? *pFormat : 0;
3930 uint32_t channels = pChannels ? *pChannels : 0;
3931 uint32_t reqSamplingRate = samplingRate;
3932 uint32_t reqFormat = format;
3933 uint32_t reqChannels = channels;
3934
3935 if (pDevices == NULL || *pDevices == 0) {
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003936 return 0;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003937 }
3938 Mutex::Autolock _l(mLock);
3939
3940 AudioStreamIn *input = mAudioHardware->openInputStream(*pDevices,
3941 (int *)&format,
3942 &channels,
3943 &samplingRate,
3944 &status,
3945 (AudioSystem::audio_in_acoustics)acoustics);
3946 LOGV("openInput() openInputStream returned input %p, SamplingRate %d, Format %d, Channels %x, acoustics %x, status %d",
3947 input,
3948 samplingRate,
3949 format,
3950 channels,
3951 acoustics,
3952 status);
3953
3954 // If the input could not be opened with the requested parameters and we can handle the conversion internally,
3955 // try to open again with the proposed parameters. The AudioFlinger can resample the input and do mono to stereo
3956 // or stereo to mono conversions on 16 bit PCM inputs.
3957 if (input == 0 && status == BAD_VALUE &&
3958 reqFormat == format && format == AudioSystem::PCM_16_BIT &&
3959 (samplingRate <= 2 * reqSamplingRate) &&
3960 (AudioSystem::popCount(channels) < 3) && (AudioSystem::popCount(reqChannels) < 3)) {
3961 LOGV("openInput() reopening with proposed sampling rate and channels");
3962 input = mAudioHardware->openInputStream(*pDevices,
3963 (int *)&format,
3964 &channels,
3965 &samplingRate,
3966 &status,
3967 (AudioSystem::audio_in_acoustics)acoustics);
3968 }
3969
3970 if (input != 0) {
3971 // Start record thread
Eric Laurent09b4ba82009-11-19 09:00:56 -08003972 thread = new RecordThread(this, input, reqSamplingRate, reqChannels, ++mNextThreadId);
3973 mRecordThreads.add(mNextThreadId, thread);
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003974 LOGV("openInput() created record thread: ID %d thread %p", mNextThreadId, thread);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003975 if (pSamplingRate) *pSamplingRate = reqSamplingRate;
3976 if (pFormat) *pFormat = format;
3977 if (pChannels) *pChannels = reqChannels;
3978
3979 input->standby();
Eric Laurent52910952009-12-05 05:20:01 -08003980
3981 return mNextThreadId;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003982 }
3983
Eric Laurent52910952009-12-05 05:20:01 -08003984 return 0;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003985}
3986
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003987status_t AudioFlinger::closeInput(int input)
Eric Laurent9d91ad52009-07-17 12:17:14 -07003988{
Eric Laurentdae20d92009-08-04 08:37:05 -07003989 // keep strong reference on the record thread so that
3990 // it is not destroyed while exit() is executed
3991 sp <RecordThread> thread;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003992 {
3993 Mutex::Autolock _l(mLock);
3994 thread = checkRecordThread_l(input);
3995 if (thread == NULL) {
3996 return BAD_VALUE;
3997 }
3998
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003999 LOGV("closeInput() %d", input);
Eric Laurentb3687ae2009-09-15 07:10:12 -07004000 void *param2 = 0;
Eric Laurent09b4ba82009-11-19 09:00:56 -08004001 audioConfigChanged_l(AudioSystem::INPUT_CLOSED, input, param2);
Eric Laurente0e9ecc2009-07-28 08:44:33 -07004002 mRecordThreads.removeItem(input);
Eric Laurent9d91ad52009-07-17 12:17:14 -07004003 }
4004 thread->exit();
4005
Eric Laurentdae20d92009-08-04 08:37:05 -07004006 mAudioHardware->closeInputStream(thread->getInput());
4007
Eric Laurent9d91ad52009-07-17 12:17:14 -07004008 return NO_ERROR;
4009}
4010
Eric Laurente0e9ecc2009-07-28 08:44:33 -07004011status_t AudioFlinger::setStreamOutput(uint32_t stream, int output)
Eric Laurent9d91ad52009-07-17 12:17:14 -07004012{
4013 Mutex::Autolock _l(mLock);
4014 MixerThread *dstThread = checkMixerThread_l(output);
4015 if (dstThread == NULL) {
Eric Laurente0e9ecc2009-07-28 08:44:33 -07004016 LOGW("setStreamOutput() bad output id %d", output);
Eric Laurent9d91ad52009-07-17 12:17:14 -07004017 return BAD_VALUE;
4018 }
4019
Eric Laurente0e9ecc2009-07-28 08:44:33 -07004020 LOGV("setStreamOutput() stream %d to output %d", stream, output);
Eric Laurent9d91ad52009-07-17 12:17:14 -07004021
4022 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurente0e9ecc2009-07-28 08:44:33 -07004023 PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
Eric Laurent9d91ad52009-07-17 12:17:14 -07004024 if (thread != dstThread &&
4025 thread->type() != PlaybackThread::DIRECT) {
4026 MixerThread *srcThread = (MixerThread *)thread;
4027 SortedVector < sp<MixerThread::Track> > tracks;
4028 SortedVector < wp<MixerThread::Track> > activeTracks;
4029 srcThread->getTracks(tracks, activeTracks, stream);
4030 if (tracks.size()) {
4031 dstThread->putTracks(tracks, activeTracks);
Eric Laurent9d91ad52009-07-17 12:17:14 -07004032 }
4033 }
4034 }
4035
Eric Laurent06437712009-09-01 05:56:26 -07004036 dstThread->sendConfigEvent(AudioSystem::STREAM_CONFIG_CHANGED, stream);
4037
Eric Laurent9d91ad52009-07-17 12:17:14 -07004038 return NO_ERROR;
4039}
4040
4041// checkPlaybackThread_l() must be called with AudioFlinger::mLock held
Eric Laurente0e9ecc2009-07-28 08:44:33 -07004042AudioFlinger::PlaybackThread *AudioFlinger::checkPlaybackThread_l(int output) const
Eric Laurent9d91ad52009-07-17 12:17:14 -07004043{
4044 PlaybackThread *thread = NULL;
Eric Laurente0e9ecc2009-07-28 08:44:33 -07004045 if (mPlaybackThreads.indexOfKey(output) >= 0) {
4046 thread = (PlaybackThread *)mPlaybackThreads.valueFor(output).get();
Eric Laurent9d91ad52009-07-17 12:17:14 -07004047 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07004048 return thread;
4049}
4050
4051// checkMixerThread_l() must be called with AudioFlinger::mLock held
Eric Laurente0e9ecc2009-07-28 08:44:33 -07004052AudioFlinger::MixerThread *AudioFlinger::checkMixerThread_l(int output) const
Eric Laurent9d91ad52009-07-17 12:17:14 -07004053{
4054 PlaybackThread *thread = checkPlaybackThread_l(output);
4055 if (thread != NULL) {
4056 if (thread->type() == PlaybackThread::DIRECT) {
4057 thread = NULL;
4058 }
4059 }
4060 return (MixerThread *)thread;
4061}
4062
4063// checkRecordThread_l() must be called with AudioFlinger::mLock held
Eric Laurente0e9ecc2009-07-28 08:44:33 -07004064AudioFlinger::RecordThread *AudioFlinger::checkRecordThread_l(int input) const
Eric Laurent9d91ad52009-07-17 12:17:14 -07004065{
4066 RecordThread *thread = NULL;
Eric Laurente0e9ecc2009-07-28 08:44:33 -07004067 if (mRecordThreads.indexOfKey(input) >= 0) {
4068 thread = (RecordThread *)mRecordThreads.valueFor(input).get();
Eric Laurent9d91ad52009-07-17 12:17:14 -07004069 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07004070 return thread;
4071}
4072
4073// ----------------------------------------------------------------------------
4074
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07004075status_t AudioFlinger::onTransact(
4076 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
4077{
4078 return BnAudioFlinger::onTransact(code, data, reply, flags);
4079}
4080
4081// ----------------------------------------------------------------------------
Eric Laurent9d91ad52009-07-17 12:17:14 -07004082
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07004083void AudioFlinger::instantiate() {
4084 defaultServiceManager()->addService(
4085 String16("media.audio_flinger"), new AudioFlinger());
4086}
4087
4088}; // namespace android