blob: 3b38d838481188c44e3ed9a26042a397808a352e [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 Laurent4edfe752010-05-14 03:26:45 -0700876 // release mLock before locking AudioFlinger mLock: lock order is always
877 // AudioFlinger then ThreadBase to avoid cross deadlock
Eric Laurent9d91ad52009-07-17 12:17:14 -0700878 mLock.unlock();
Eric Laurent4edfe752010-05-14 03:26:45 -0700879 mAudioFlinger->mLock.lock();
880 audioConfigChanged_l(configEvent->mEvent, configEvent->mParam);
881 mAudioFlinger->mLock.unlock();
Eric Laurent9d91ad52009-07-17 12:17:14 -0700882 delete configEvent;
883 mLock.lock();
884 }
885 mLock.unlock();
886}
887
Eric Laurentee47d432009-11-07 00:01:32 -0800888status_t AudioFlinger::ThreadBase::dumpBase(int fd, const Vector<String16>& args)
889{
890 const size_t SIZE = 256;
891 char buffer[SIZE];
892 String8 result;
893
894 bool locked = tryLock(mLock);
895 if (!locked) {
896 snprintf(buffer, SIZE, "thread %p maybe dead locked\n", this);
897 write(fd, buffer, strlen(buffer));
898 }
899
900 snprintf(buffer, SIZE, "standby: %d\n", mStandby);
901 result.append(buffer);
902 snprintf(buffer, SIZE, "Sample rate: %d\n", mSampleRate);
903 result.append(buffer);
904 snprintf(buffer, SIZE, "Frame count: %d\n", mFrameCount);
905 result.append(buffer);
906 snprintf(buffer, SIZE, "Channel Count: %d\n", mChannelCount);
907 result.append(buffer);
908 snprintf(buffer, SIZE, "Format: %d\n", mFormat);
909 result.append(buffer);
910 snprintf(buffer, SIZE, "Frame size: %d\n", mFrameSize);
911 result.append(buffer);
912
913 snprintf(buffer, SIZE, "\nPending setParameters commands: \n");
914 result.append(buffer);
915 result.append(" Index Command");
916 for (size_t i = 0; i < mNewParameters.size(); ++i) {
917 snprintf(buffer, SIZE, "\n %02d ", i);
918 result.append(buffer);
919 result.append(mNewParameters[i]);
920 }
921
922 snprintf(buffer, SIZE, "\n\nPending config events: \n");
923 result.append(buffer);
924 snprintf(buffer, SIZE, " Index event param\n");
925 result.append(buffer);
926 for (size_t i = 0; i < mConfigEvents.size(); i++) {
927 snprintf(buffer, SIZE, " %02d %02d %d\n", i, mConfigEvents[i]->mEvent, mConfigEvents[i]->mParam);
928 result.append(buffer);
929 }
930 result.append("\n");
931
932 write(fd, result.string(), result.size());
933
934 if (locked) {
935 mLock.unlock();
936 }
937 return NO_ERROR;
938}
939
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800940
941// ----------------------------------------------------------------------------
942
Eric Laurent09b4ba82009-11-19 09:00:56 -0800943AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id)
944 : ThreadBase(audioFlinger, id),
Eric Laurentf9df2492009-08-06 08:49:39 -0700945 mMixBuffer(0), mSuspended(0), mBytesWritten(0), mOutput(output),
Eric Laurent9395d9b2009-07-23 13:17:39 -0700946 mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800947{
Eric Laurent9d91ad52009-07-17 12:17:14 -0700948 readOutputParameters();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800949
Eric Laurent9d91ad52009-07-17 12:17:14 -0700950 mMasterVolume = mAudioFlinger->masterVolume();
951 mMasterMute = mAudioFlinger->masterMute();
952
953 for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
954 mStreamTypes[stream].volume = mAudioFlinger->streamVolumeInternal(stream);
955 mStreamTypes[stream].mute = mAudioFlinger->streamMute(stream);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800956 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800957}
958
Eric Laurent9d91ad52009-07-17 12:17:14 -0700959AudioFlinger::PlaybackThread::~PlaybackThread()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800960{
961 delete [] mMixBuffer;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800962}
963
Eric Laurent9d91ad52009-07-17 12:17:14 -0700964status_t AudioFlinger::PlaybackThread::dump(int fd, const Vector<String16>& args)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800965{
966 dumpInternals(fd, args);
967 dumpTracks(fd, args);
968 return NO_ERROR;
969}
970
Eric Laurent9d91ad52009-07-17 12:17:14 -0700971status_t AudioFlinger::PlaybackThread::dumpTracks(int fd, const Vector<String16>& args)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800972{
973 const size_t SIZE = 256;
974 char buffer[SIZE];
975 String8 result;
976
Eric Laurent9d91ad52009-07-17 12:17:14 -0700977 snprintf(buffer, SIZE, "Output thread %p tracks\n", this);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800978 result.append(buffer);
Eric Laurentee47d432009-11-07 00:01:32 -0800979 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 -0800980 for (size_t i = 0; i < mTracks.size(); ++i) {
Eric Laurentc828f6a2009-03-31 14:34:35 -0700981 sp<Track> track = mTracks[i];
982 if (track != 0) {
983 track->dump(buffer, SIZE);
984 result.append(buffer);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800985 }
986 }
987
Eric Laurent9d91ad52009-07-17 12:17:14 -0700988 snprintf(buffer, SIZE, "Output thread %p active tracks\n", this);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800989 result.append(buffer);
Eric Laurentee47d432009-11-07 00:01:32 -0800990 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 -0800991 for (size_t i = 0; i < mActiveTracks.size(); ++i) {
Eric Laurentc828f6a2009-03-31 14:34:35 -0700992 wp<Track> wTrack = mActiveTracks[i];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800993 if (wTrack != 0) {
994 sp<Track> track = wTrack.promote();
995 if (track != 0) {
996 track->dump(buffer, SIZE);
997 result.append(buffer);
998 }
999 }
1000 }
1001 write(fd, result.string(), result.size());
1002 return NO_ERROR;
1003}
1004
Eric Laurent9d91ad52009-07-17 12:17:14 -07001005status_t AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String16>& args)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001006{
1007 const size_t SIZE = 256;
1008 char buffer[SIZE];
1009 String8 result;
1010
Eric Laurentee47d432009-11-07 00:01:32 -08001011 snprintf(buffer, SIZE, "\nOutput thread %p internals\n", this);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001012 result.append(buffer);
1013 snprintf(buffer, SIZE, "last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime));
1014 result.append(buffer);
1015 snprintf(buffer, SIZE, "total writes: %d\n", mNumWrites);
1016 result.append(buffer);
1017 snprintf(buffer, SIZE, "delayed writes: %d\n", mNumDelayedWrites);
1018 result.append(buffer);
1019 snprintf(buffer, SIZE, "blocked in write: %d\n", mInWrite);
1020 result.append(buffer);
Eric Laurent7e2aad12009-12-18 05:47:48 -08001021 snprintf(buffer, SIZE, "suspend count: %d\n", mSuspended);
1022 result.append(buffer);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001023 write(fd, result.string(), result.size());
Eric Laurentee47d432009-11-07 00:01:32 -08001024
1025 dumpBase(fd, args);
1026
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001027 return NO_ERROR;
1028}
1029
1030// Thread virtuals
Eric Laurent9d91ad52009-07-17 12:17:14 -07001031status_t AudioFlinger::PlaybackThread::readyToRun()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001032{
1033 if (mSampleRate == 0) {
1034 LOGE("No working audio driver found.");
1035 return NO_INIT;
1036 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07001037 LOGI("AudioFlinger's thread %p ready to run", this);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001038 return NO_ERROR;
1039}
1040
Eric Laurent9d91ad52009-07-17 12:17:14 -07001041void AudioFlinger::PlaybackThread::onFirstRef()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001042{
1043 const size_t SIZE = 256;
1044 char buffer[SIZE];
1045
Eric Laurent9d91ad52009-07-17 12:17:14 -07001046 snprintf(buffer, SIZE, "Playback Thread %p", this);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001047
1048 run(buffer, ANDROID_PRIORITY_URGENT_AUDIO);
1049}
1050
Eric Laurent9d91ad52009-07-17 12:17:14 -07001051// PlaybackThread::createTrack_l() must be called with AudioFlinger::mLock held
1052sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrack_l(
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001053 const sp<AudioFlinger::Client>& client,
1054 int streamType,
1055 uint32_t sampleRate,
1056 int format,
1057 int channelCount,
1058 int frameCount,
1059 const sp<IMemory>& sharedBuffer,
1060 status_t *status)
1061{
1062 sp<Track> track;
1063 status_t lStatus;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001064
1065 if (mType == DIRECT) {
Eric Laurente1512162010-05-14 05:45:46 -07001066 if (sampleRate != mSampleRate || format != mFormat || channelCount != (int)mChannelCount) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07001067 LOGE("createTrack_l() Bad parameter: sampleRate %d format %d, channelCount %d for output %p",
1068 sampleRate, format, channelCount, mOutput);
1069 lStatus = BAD_VALUE;
1070 goto Exit;
1071 }
1072 } else {
1073 // Resampler implementation limits input sampling rate to 2 x output sampling rate.
1074 if (sampleRate > mSampleRate*2) {
1075 LOGE("Sample rate out of range: %d mSampleRate %d", sampleRate, mSampleRate);
1076 lStatus = BAD_VALUE;
1077 goto Exit;
1078 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001079 }
1080
Eric Laurent9d91ad52009-07-17 12:17:14 -07001081 if (mOutput == 0) {
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001082 LOGE("Audio driver not initialized.");
1083 lStatus = NO_INIT;
1084 goto Exit;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001085 }
1086
Eric Laurent9d91ad52009-07-17 12:17:14 -07001087 { // scope for mLock
1088 Mutex::Autolock _l(mLock);
1089 track = new Track(this, client, streamType, sampleRate, format,
1090 channelCount, frameCount, sharedBuffer);
Eric Laurent7b570852009-11-09 04:45:39 -08001091 if (track->getCblk() == NULL || track->name() < 0) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07001092 lStatus = NO_MEMORY;
1093 goto Exit;
1094 }
1095 mTracks.add(track);
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001096 }
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001097 lStatus = NO_ERROR;
1098
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001099Exit:
1100 if(status) {
1101 *status = lStatus;
1102 }
1103 return track;
1104}
1105
Eric Laurent9d91ad52009-07-17 12:17:14 -07001106uint32_t AudioFlinger::PlaybackThread::latency() const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001107{
1108 if (mOutput) {
1109 return mOutput->latency();
1110 }
1111 else {
1112 return 0;
1113 }
1114}
1115
Eric Laurent9d91ad52009-07-17 12:17:14 -07001116status_t AudioFlinger::PlaybackThread::setMasterVolume(float value)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001117{
Glenn Kastend5ea9692010-03-05 12:18:01 -08001118#ifdef LVMX
1119 int audioOutputType = LifeVibes::getMixerType(mId, mType);
1120 if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) {
1121 LifeVibes::setMasterVolume(audioOutputType, value);
1122 }
1123#endif
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001124 mMasterVolume = value;
1125 return NO_ERROR;
1126}
1127
Eric Laurent9d91ad52009-07-17 12:17:14 -07001128status_t AudioFlinger::PlaybackThread::setMasterMute(bool muted)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001129{
Glenn Kastend5ea9692010-03-05 12:18:01 -08001130#ifdef LVMX
1131 int audioOutputType = LifeVibes::getMixerType(mId, mType);
1132 if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) {
1133 LifeVibes::setMasterMute(audioOutputType, muted);
1134 }
1135#endif
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001136 mMasterMute = muted;
1137 return NO_ERROR;
1138}
1139
Eric Laurent9d91ad52009-07-17 12:17:14 -07001140float AudioFlinger::PlaybackThread::masterVolume() const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001141{
1142 return mMasterVolume;
1143}
1144
Eric Laurent9d91ad52009-07-17 12:17:14 -07001145bool AudioFlinger::PlaybackThread::masterMute() const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001146{
1147 return mMasterMute;
1148}
1149
Eric Laurent9d91ad52009-07-17 12:17:14 -07001150status_t AudioFlinger::PlaybackThread::setStreamVolume(int stream, float value)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001151{
Glenn Kastend5ea9692010-03-05 12:18:01 -08001152#ifdef LVMX
1153 int audioOutputType = LifeVibes::getMixerType(mId, mType);
1154 if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) {
1155 LifeVibes::setStreamVolume(audioOutputType, stream, value);
1156 }
1157#endif
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001158 mStreamTypes[stream].volume = value;
1159 return NO_ERROR;
1160}
1161
Eric Laurent9d91ad52009-07-17 12:17:14 -07001162status_t AudioFlinger::PlaybackThread::setStreamMute(int stream, bool muted)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001163{
Glenn Kastend5ea9692010-03-05 12:18:01 -08001164#ifdef LVMX
1165 int audioOutputType = LifeVibes::getMixerType(mId, mType);
1166 if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) {
1167 LifeVibes::setStreamMute(audioOutputType, stream, muted);
1168 }
1169#endif
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001170 mStreamTypes[stream].mute = muted;
1171 return NO_ERROR;
1172}
1173
Eric Laurent9d91ad52009-07-17 12:17:14 -07001174float AudioFlinger::PlaybackThread::streamVolume(int stream) const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001175{
1176 return mStreamTypes[stream].volume;
1177}
1178
Eric Laurent9d91ad52009-07-17 12:17:14 -07001179bool AudioFlinger::PlaybackThread::streamMute(int stream) const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001180{
1181 return mStreamTypes[stream].mute;
1182}
1183
Eric Laurent43c0b0a2010-01-25 08:49:09 -08001184bool AudioFlinger::PlaybackThread::isStreamActive(int stream) const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001185{
Eric Laurent9d91ad52009-07-17 12:17:14 -07001186 Mutex::Autolock _l(mLock);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001187 size_t count = mActiveTracks.size();
1188 for (size_t i = 0 ; i < count ; ++i) {
1189 sp<Track> t = mActiveTracks[i].promote();
1190 if (t == 0) continue;
1191 Track* const track = t.get();
Eric Laurent43c0b0a2010-01-25 08:49:09 -08001192 if (t->type() == stream)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001193 return true;
1194 }
1195 return false;
1196}
1197
Eric Laurent9d91ad52009-07-17 12:17:14 -07001198// addTrack_l() must be called with ThreadBase::mLock held
1199status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001200{
1201 status_t status = ALREADY_EXISTS;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001202
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001203 // set retry count for buffer fill
1204 track->mRetryCount = kMaxTrackStartupRetries;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001205 if (mActiveTracks.indexOf(track) < 0) {
1206 // the track is newly added, make sure it fills up all its
1207 // buffers before playing. This is to ensure the client will
1208 // effectively get the latency it requested.
1209 track->mFillingUpStatus = Track::FS_FILLING;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001210 track->mResetDone = false;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001211 mActiveTracks.add(track);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001212 status = NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001213 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07001214
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001215 LOGV("mWaitWorkCV.broadcast");
Eric Laurent9d91ad52009-07-17 12:17:14 -07001216 mWaitWorkCV.broadcast();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001217
1218 return status;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001219}
1220
Eric Laurent9d91ad52009-07-17 12:17:14 -07001221// destroyTrack_l() must be called with ThreadBase::mLock held
1222void AudioFlinger::PlaybackThread::destroyTrack_l(const sp<Track>& track)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001223{
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001224 track->mState = TrackBase::TERMINATED;
1225 if (mActiveTracks.indexOf(track) < 0) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001226 mTracks.remove(track);
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001227 deleteTrackName_l(track->name());
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001228 }
1229}
1230
Eric Laurent9d91ad52009-07-17 12:17:14 -07001231String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys)
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001232{
Eric Laurent9d91ad52009-07-17 12:17:14 -07001233 return mOutput->getParameters(keys);
1234}
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001235
Eric Laurent4edfe752010-05-14 03:26:45 -07001236// destroyTrack_l() must be called with AudioFlinger::mLock held
1237void AudioFlinger::PlaybackThread::audioConfigChanged_l(int event, int param) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07001238 AudioSystem::OutputDescriptor desc;
1239 void *param2 = 0;
1240
Eric Laurent4edfe752010-05-14 03:26:45 -07001241 LOGV("PlaybackThread::audioConfigChanged_l, thread %p, event %d, param %d", this, event, param);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001242
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 Laurent09b4ba82009-11-19 09:00:56 -08001260 mAudioFlinger->audioConfigChanged_l(event, mId, param2);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001261}
1262
1263void AudioFlinger::PlaybackThread::readOutputParameters()
1264{
1265 mSampleRate = mOutput->sampleRate();
Eric Laurente1512162010-05-14 05:45:46 -07001266 mChannels = mOutput->channels();
1267 mChannelCount = (uint16_t)AudioSystem::popCount(mChannels);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001268 mFormat = mOutput->format();
Eric Laurente1512162010-05-14 05:45:46 -07001269 mFrameSize = (uint16_t)mOutput->frameSize();
Eric Laurent9d91ad52009-07-17 12:17:14 -07001270 mFrameCount = mOutput->bufferSize() / mFrameSize;
1271
Eric Laurent9d91ad52009-07-17 12:17:14 -07001272 // FIXME - Current mixer implementation only supports stereo output: Always
1273 // Allocate a stereo buffer even if HW output is mono.
1274 if (mMixBuffer != NULL) delete mMixBuffer;
1275 mMixBuffer = new int16_t[mFrameCount * 2];
1276 memset(mMixBuffer, 0, mFrameCount * 2 * sizeof(int16_t));
1277}
1278
Eric Laurente9ed2722010-01-19 17:37:09 -08001279status_t AudioFlinger::PlaybackThread::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames)
1280{
1281 if (halFrames == 0 || dspFrames == 0) {
1282 return BAD_VALUE;
1283 }
1284 if (mOutput == 0) {
1285 return INVALID_OPERATION;
1286 }
1287 *halFrames = mBytesWritten/mOutput->frameSize();
1288
1289 return mOutput->getRenderPosition(dspFrames);
1290}
1291
Eric Laurent9d91ad52009-07-17 12:17:14 -07001292// ----------------------------------------------------------------------------
1293
Eric Laurent09b4ba82009-11-19 09:00:56 -08001294AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id)
1295 : PlaybackThread(audioFlinger, output, id),
Eric Laurent9d91ad52009-07-17 12:17:14 -07001296 mAudioMixer(0)
1297{
1298 mType = PlaybackThread::MIXER;
1299 mAudioMixer = new AudioMixer(mFrameCount, mSampleRate);
1300
1301 // FIXME - Current mixer implementation only supports stereo output
1302 if (mChannelCount == 1) {
1303 LOGE("Invalid audio hardware channel count");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001304 }
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001305}
1306
Eric Laurent9d91ad52009-07-17 12:17:14 -07001307AudioFlinger::MixerThread::~MixerThread()
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001308{
Eric Laurent9d91ad52009-07-17 12:17:14 -07001309 delete mAudioMixer;
1310}
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001311
Eric Laurent9d91ad52009-07-17 12:17:14 -07001312bool AudioFlinger::MixerThread::threadLoop()
1313{
Eric Laurent9d91ad52009-07-17 12:17:14 -07001314 int16_t* curBuf = mMixBuffer;
1315 Vector< sp<Track> > tracksToRemove;
Eric Laurent0e49d352009-11-09 23:32:22 -08001316 uint32_t mixerStatus = MIXER_IDLE;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001317 nsecs_t standbyTime = systemTime();
1318 size_t mixBufferSize = mFrameCount * mFrameSize;
Dave Sparks8a95a452009-09-30 03:09:03 -07001319 // FIXME: Relaxed timing because of a certain device that can't meet latency
1320 // Should be reduced to 2x after the vendor fixes the driver issue
1321 nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 3;
1322 nsecs_t lastWarning = 0;
Eric Laurent0e49d352009-11-09 23:32:22 -08001323 bool longStandbyExit = false;
1324 uint32_t activeSleepTime = activeSleepTimeUs();
1325 uint32_t idleSleepTime = idleSleepTimeUs();
1326 uint32_t sleepTime = idleSleepTime;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001327
Eric Laurent9d91ad52009-07-17 12:17:14 -07001328 while (!exitPending())
1329 {
1330 processConfigEvents();
1331
Eric Laurent0e49d352009-11-09 23:32:22 -08001332 mixerStatus = MIXER_IDLE;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001333 { // scope for mLock
1334
1335 Mutex::Autolock _l(mLock);
1336
1337 if (checkForNewParameters_l()) {
1338 mixBufferSize = mFrameCount * mFrameSize;
Dave Sparks8a95a452009-09-30 03:09:03 -07001339 // FIXME: Relaxed timing because of a certain device that can't meet latency
1340 // Should be reduced to 2x after the vendor fixes the driver issue
1341 maxPeriod = seconds(mFrameCount) / mSampleRate * 3;
Eric Laurent0e49d352009-11-09 23:32:22 -08001342 activeSleepTime = activeSleepTimeUs();
1343 idleSleepTime = idleSleepTimeUs();
Eric Laurent9d91ad52009-07-17 12:17:14 -07001344 }
1345
1346 const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
1347
1348 // put audio hardware into standby after short delay
1349 if UNLIKELY((!activeTracks.size() && systemTime() > standbyTime) ||
1350 mSuspended) {
1351 if (!mStandby) {
1352 LOGV("Audio hardware entering standby, mixer %p, mSuspended %d\n", this, mSuspended);
1353 mOutput->standby();
1354 mStandby = true;
1355 mBytesWritten = 0;
1356 }
1357
1358 if (!activeTracks.size() && mConfigEvents.isEmpty()) {
1359 // we're about to wait, flush the binder command buffer
1360 IPCThreadState::self()->flushCommands();
1361
1362 if (exitPending()) break;
1363
1364 // wait until we have something to do...
1365 LOGV("MixerThread %p TID %d going to sleep\n", this, gettid());
1366 mWaitWorkCV.wait(mLock);
1367 LOGV("MixerThread %p TID %d waking up\n", this, gettid());
1368
1369 if (mMasterMute == false) {
1370 char value[PROPERTY_VALUE_MAX];
1371 property_get("ro.audio.silent", value, "0");
1372 if (atoi(value)) {
1373 LOGD("Silence is golden");
1374 setMasterMute(true);
1375 }
1376 }
1377
1378 standbyTime = systemTime() + kStandbyTimeInNsecs;
Eric Laurent0e49d352009-11-09 23:32:22 -08001379 sleepTime = idleSleepTime;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001380 continue;
1381 }
1382 }
1383
Eric Laurent0e49d352009-11-09 23:32:22 -08001384 mixerStatus = prepareTracks_l(activeTracks, &tracksToRemove);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001385 }
1386
Eric Laurent0e49d352009-11-09 23:32:22 -08001387 if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
Eric Laurentaef692f2009-09-22 00:35:48 -07001388 // mix buffers...
1389 mAudioMixer->process(curBuf);
1390 sleepTime = 0;
1391 standbyTime = systemTime() + kStandbyTimeInNsecs;
Eric Laurent3522c802009-09-07 08:38:38 -07001392 } else {
Eric Laurentf5e868b2009-10-05 20:29:18 -07001393 // If no tracks are ready, sleep once for the duration of an output
1394 // buffer size, then write 0s to the output
1395 if (sleepTime == 0) {
Eric Laurent0e49d352009-11-09 23:32:22 -08001396 if (mixerStatus == MIXER_TRACKS_ENABLED) {
1397 sleepTime = activeSleepTime;
1398 } else {
1399 sleepTime = idleSleepTime;
1400 }
1401 } else if (mBytesWritten != 0 ||
1402 (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)) {
Eric Laurentaef692f2009-09-22 00:35:48 -07001403 memset (curBuf, 0, mixBufferSize);
Eric Laurent3522c802009-09-07 08:38:38 -07001404 sleepTime = 0;
Eric Laurent0e49d352009-11-09 23:32:22 -08001405 LOGV_IF((mBytesWritten == 0 && (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)), "anticipated start");
Eric Laurent3522c802009-09-07 08:38:38 -07001406 }
Eric Laurentaef692f2009-09-22 00:35:48 -07001407 }
1408
1409 if (mSuspended) {
Eric Laurent0e49d352009-11-09 23:32:22 -08001410 sleepTime = idleSleepTime;
Eric Laurentaef692f2009-09-22 00:35:48 -07001411 }
1412 // sleepTime == 0 means we must write to audio hardware
1413 if (sleepTime == 0) {
1414 mLastWriteTime = systemTime();
1415 mInWrite = true;
Eric Laurente9ed2722010-01-19 17:37:09 -08001416 mBytesWritten += mixBufferSize;
Glenn Kastend5ea9692010-03-05 12:18:01 -08001417#ifdef LVMX
1418 int audioOutputType = LifeVibes::getMixerType(mId, mType);
1419 if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) {
1420 LifeVibes::process(audioOutputType, curBuf, mixBufferSize);
1421 }
1422#endif
Eric Laurentaef692f2009-09-22 00:35:48 -07001423 int bytesWritten = (int)mOutput->write(curBuf, mixBufferSize);
Eric Laurente9ed2722010-01-19 17:37:09 -08001424 if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
Eric Laurentaef692f2009-09-22 00:35:48 -07001425 mNumWrites++;
1426 mInWrite = false;
Dave Sparks8a95a452009-09-30 03:09:03 -07001427 nsecs_t now = systemTime();
1428 nsecs_t delta = now - mLastWriteTime;
Eric Laurentaef692f2009-09-22 00:35:48 -07001429 if (delta > maxPeriod) {
Eric Laurentaef692f2009-09-22 00:35:48 -07001430 mNumDelayedWrites++;
Dave Sparks8a95a452009-09-30 03:09:03 -07001431 if ((now - lastWarning) > kWarningThrottle) {
1432 LOGW("write blocked for %llu msecs, %d delayed writes, thread %p",
1433 ns2ms(delta), mNumDelayedWrites, this);
1434 lastWarning = now;
1435 }
Eric Laurent0e49d352009-11-09 23:32:22 -08001436 if (mStandby) {
1437 longStandbyExit = true;
1438 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07001439 }
Eric Laurent0e49d352009-11-09 23:32:22 -08001440 mStandby = false;
Eric Laurentaef692f2009-09-22 00:35:48 -07001441 } else {
1442 usleep(sleepTime);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001443 }
1444
1445 // finally let go of all our tracks, without the lock held
1446 // since we can't guarantee the destructors won't acquire that
1447 // same lock.
1448 tracksToRemove.clear();
1449 }
1450
1451 if (!mStandby) {
1452 mOutput->standby();
1453 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07001454
1455 LOGV("MixerThread %p exiting", this);
1456 return false;
1457}
1458
1459// prepareTracks_l() must be called with ThreadBase::mLock held
Eric Laurent0e49d352009-11-09 23:32:22 -08001460uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove)
Eric Laurent9d91ad52009-07-17 12:17:14 -07001461{
1462
Eric Laurent0e49d352009-11-09 23:32:22 -08001463 uint32_t mixerStatus = MIXER_IDLE;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001464 // find out which tracks need to be processed
1465 size_t count = activeTracks.size();
Glenn Kastend5ea9692010-03-05 12:18:01 -08001466
1467 float masterVolume = mMasterVolume;
1468 bool masterMute = mMasterMute;
1469
1470#ifdef LVMX
1471 bool tracksConnectedChanged = false;
1472 bool stateChanged = false;
1473
1474 int audioOutputType = LifeVibes::getMixerType(mId, mType);
1475 if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType))
1476 {
1477 int activeTypes = 0;
1478 for (size_t i=0 ; i<count ; i++) {
1479 sp<Track> t = activeTracks[i].promote();
1480 if (t == 0) continue;
1481 Track* const track = t.get();
1482 int iTracktype=track->type();
1483 activeTypes |= 1<<track->type();
1484 }
1485 LifeVibes::computeVolumes(audioOutputType, activeTypes, tracksConnectedChanged, stateChanged, masterVolume, masterMute);
1486 }
1487#endif
1488
Eric Laurent9d91ad52009-07-17 12:17:14 -07001489 for (size_t i=0 ; i<count ; i++) {
1490 sp<Track> t = activeTracks[i].promote();
1491 if (t == 0) continue;
1492
1493 Track* const track = t.get();
1494 audio_track_cblk_t* cblk = track->cblk();
1495
1496 // The first time a track is added we wait
1497 // for all its buffers to be filled before processing it
1498 mAudioMixer->setActiveTrack(track->name());
1499 if (cblk->framesReady() && (track->isReady() || track->isStopped()) &&
Eric Laurentdeea5022010-03-31 12:21:17 -07001500 !track->isPaused() && !track->isTerminated())
Eric Laurent9d91ad52009-07-17 12:17:14 -07001501 {
Eric Laurent7e2aad12009-12-18 05:47:48 -08001502 //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 -07001503
1504 // compute volume for this track
1505 int16_t left, right;
Glenn Kastend5ea9692010-03-05 12:18:01 -08001506 if (track->isMuted() || masterMute || track->isPausing() ||
Eric Laurent9d91ad52009-07-17 12:17:14 -07001507 mStreamTypes[track->type()].mute) {
1508 left = right = 0;
1509 if (track->isPausing()) {
1510 track->setPaused();
1511 }
1512 } else {
Glenn Kastend5ea9692010-03-05 12:18:01 -08001513 // read original volumes with volume control
Eric Laurent9d91ad52009-07-17 12:17:14 -07001514 float typeVolume = mStreamTypes[track->type()].volume;
Glenn Kastend5ea9692010-03-05 12:18:01 -08001515#ifdef LVMX
1516 bool streamMute=false;
1517 // read the volume from the LivesVibes audio engine.
1518 if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType))
1519 {
1520 LifeVibes::getStreamVolumes(audioOutputType, track->type(), &typeVolume, &streamMute);
1521 if (streamMute) {
1522 typeVolume = 0;
1523 }
1524 }
1525#endif
1526 float v = masterVolume * typeVolume;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001527 float v_clamped = v * cblk->volume[0];
1528 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
1529 left = int16_t(v_clamped);
1530 v_clamped = v * cblk->volume[1];
1531 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
1532 right = int16_t(v_clamped);
1533 }
1534
1535 // XXX: these things DON'T need to be done each time
1536 mAudioMixer->setBufferProvider(track);
1537 mAudioMixer->enable(AudioMixer::MIXING);
1538
Eric Laurent08d3d1d2009-09-03 03:45:52 -07001539 int param = AudioMixer::VOLUME;
1540 if (track->mFillingUpStatus == Track::FS_FILLED) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07001541 // no ramp for the first volume setting
1542 track->mFillingUpStatus = Track::FS_ACTIVE;
1543 if (track->mState == TrackBase::RESUMING) {
1544 track->mState = TrackBase::ACTIVE;
1545 param = AudioMixer::RAMP_VOLUME;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001546 }
Eric Laurent08d3d1d2009-09-03 03:45:52 -07001547 } else if (cblk->server != 0) {
1548 // If the track is stopped before the first frame was mixed,
1549 // do not apply ramp
Eric Laurent9d91ad52009-07-17 12:17:14 -07001550 param = AudioMixer::RAMP_VOLUME;
1551 }
Glenn Kastend5ea9692010-03-05 12:18:01 -08001552#ifdef LVMX
1553 if ( tracksConnectedChanged || stateChanged )
1554 {
1555 // only do the ramp when the volume is changed by the user / application
1556 param = AudioMixer::VOLUME;
1557 }
1558#endif
Eric Laurent9d91ad52009-07-17 12:17:14 -07001559 mAudioMixer->setParameter(param, AudioMixer::VOLUME0, left);
1560 mAudioMixer->setParameter(param, AudioMixer::VOLUME1, right);
1561 mAudioMixer->setParameter(
1562 AudioMixer::TRACK,
1563 AudioMixer::FORMAT, track->format());
1564 mAudioMixer->setParameter(
1565 AudioMixer::TRACK,
1566 AudioMixer::CHANNEL_COUNT, track->channelCount());
1567 mAudioMixer->setParameter(
1568 AudioMixer::RESAMPLE,
1569 AudioMixer::SAMPLE_RATE,
1570 int(cblk->sampleRate));
1571
1572 // reset retry count
1573 track->mRetryCount = kMaxTrackRetries;
Eric Laurent0e49d352009-11-09 23:32:22 -08001574 mixerStatus = MIXER_TRACKS_READY;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001575 } else {
Eric Laurent7e2aad12009-12-18 05:47:48 -08001576 //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 -07001577 if (track->isStopped()) {
1578 track->reset();
1579 }
1580 if (track->isTerminated() || track->isStopped() || track->isPaused()) {
1581 // We have consumed all the buffers of this track.
1582 // Remove it from the list of active tracks.
1583 tracksToRemove->add(track);
1584 mAudioMixer->disable(AudioMixer::MIXING);
1585 } else {
1586 // No buffers for this track. Give it a few chances to
1587 // fill a buffer, then remove it from active list.
1588 if (--(track->mRetryCount) <= 0) {
Eric Laurentf5e868b2009-10-05 20:29:18 -07001589 LOGV("BUFFER TIMEOUT: remove(%d) from active list on thread %p", track->name(), this);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001590 tracksToRemove->add(track);
Eric Laurent0e49d352009-11-09 23:32:22 -08001591 } else if (mixerStatus != MIXER_TRACKS_READY) {
1592 mixerStatus = MIXER_TRACKS_ENABLED;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001593 }
Eric Laurent0e49d352009-11-09 23:32:22 -08001594
1595 mAudioMixer->disable(AudioMixer::MIXING);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001596 }
1597 }
1598 }
1599
1600 // remove all the tracks that need to be...
1601 count = tracksToRemove->size();
1602 if (UNLIKELY(count)) {
1603 for (size_t i=0 ; i<count ; i++) {
1604 const sp<Track>& track = tracksToRemove->itemAt(i);
1605 mActiveTracks.remove(track);
1606 if (track->isTerminated()) {
1607 mTracks.remove(track);
1608 deleteTrackName_l(track->mName);
1609 }
1610 }
1611 }
1612
Eric Laurent0e49d352009-11-09 23:32:22 -08001613 return mixerStatus;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001614}
1615
Eric Laurent4edfe752010-05-14 03:26:45 -07001616void AudioFlinger::MixerThread::invalidateTracks(int streamType)
Eric Laurent9d91ad52009-07-17 12:17:14 -07001617{
Eric Laurent4edfe752010-05-14 03:26:45 -07001618 LOGV ("MixerThread::invalidateTracks() mixer %p, streamType %d, mTracks.size %d", this, streamType, mTracks.size());
Eric Laurent9d91ad52009-07-17 12:17:14 -07001619 Mutex::Autolock _l(mLock);
1620 size_t size = mTracks.size();
1621 for (size_t i = 0; i < size; i++) {
1622 sp<Track> t = mTracks[i];
1623 if (t->type() == streamType) {
Eric Laurent4edfe752010-05-14 03:26:45 -07001624 t->mCblk->lock.lock();
1625 t->mCblk->flags |= CBLK_INVALID_ON;
1626 t->mCblk->cv.signal();
1627 t->mCblk->lock.unlock();
Eric Laurent9d91ad52009-07-17 12:17:14 -07001628 }
1629 }
1630 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07001631
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001632
Eric Laurent9d91ad52009-07-17 12:17:14 -07001633// getTrackName_l() must be called with ThreadBase::mLock held
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001634int AudioFlinger::MixerThread::getTrackName_l()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001635{
1636 return mAudioMixer->getTrackName();
1637}
1638
Eric Laurent9d91ad52009-07-17 12:17:14 -07001639// deleteTrackName_l() must be called with ThreadBase::mLock held
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001640void AudioFlinger::MixerThread::deleteTrackName_l(int name)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001641{
Eric Laurentfed93822009-12-07 10:53:10 -08001642 LOGV("remove track (%d) and delete from mixer", name);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001643 mAudioMixer->deleteTrackName(name);
1644}
1645
Eric Laurent9d91ad52009-07-17 12:17:14 -07001646// checkForNewParameters_l() must be called with ThreadBase::mLock held
1647bool AudioFlinger::MixerThread::checkForNewParameters_l()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001648{
Eric Laurent9d91ad52009-07-17 12:17:14 -07001649 bool reconfig = false;
1650
Eric Laurent3464c012009-08-04 09:45:33 -07001651 while (!mNewParameters.isEmpty()) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07001652 status_t status = NO_ERROR;
Eric Laurent3464c012009-08-04 09:45:33 -07001653 String8 keyValuePair = mNewParameters[0];
1654 AudioParameter param = AudioParameter(keyValuePair);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001655 int value;
Eric Laurent3464c012009-08-04 09:45:33 -07001656
Eric Laurent9d91ad52009-07-17 12:17:14 -07001657 if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
1658 reconfig = true;
1659 }
1660 if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
1661 if (value != AudioSystem::PCM_16_BIT) {
1662 status = BAD_VALUE;
1663 } else {
1664 reconfig = true;
1665 }
1666 }
1667 if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
1668 if (value != AudioSystem::CHANNEL_OUT_STEREO) {
1669 status = BAD_VALUE;
1670 } else {
1671 reconfig = true;
1672 }
1673 }
1674 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
1675 // do not accept frame count changes if tracks are open as the track buffer
1676 // size depends on frame count and correct behavior would not be garantied
1677 // if frame count is changed after track creation
1678 if (!mTracks.isEmpty()) {
1679 status = INVALID_OPERATION;
1680 } else {
1681 reconfig = true;
1682 }
1683 }
1684 if (status == NO_ERROR) {
Eric Laurent3464c012009-08-04 09:45:33 -07001685 status = mOutput->setParameters(keyValuePair);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001686 if (!mStandby && status == INVALID_OPERATION) {
1687 mOutput->standby();
1688 mStandby = true;
1689 mBytesWritten = 0;
Eric Laurent3464c012009-08-04 09:45:33 -07001690 status = mOutput->setParameters(keyValuePair);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001691 }
1692 if (status == NO_ERROR && reconfig) {
1693 delete mAudioMixer;
1694 readOutputParameters();
1695 mAudioMixer = new AudioMixer(mFrameCount, mSampleRate);
1696 for (size_t i = 0; i < mTracks.size() ; i++) {
1697 int name = getTrackName_l();
1698 if (name < 0) break;
1699 mTracks[i]->mName = name;
Eric Laurent878c0e12009-08-10 08:15:12 -07001700 // limit track sample rate to 2 x new output sample rate
1701 if (mTracks[i]->mCblk->sampleRate > 2 * sampleRate()) {
1702 mTracks[i]->mCblk->sampleRate = 2 * sampleRate();
1703 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07001704 }
Eric Laurent3464c012009-08-04 09:45:33 -07001705 sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001706 }
1707 }
Eric Laurentee47d432009-11-07 00:01:32 -08001708
1709 mNewParameters.removeAt(0);
1710
Eric Laurent9d91ad52009-07-17 12:17:14 -07001711 mParamStatus = status;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001712 mParamCond.signal();
Eric Laurent3464c012009-08-04 09:45:33 -07001713 mWaitWorkCV.wait(mLock);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001714 }
1715 return reconfig;
1716}
1717
1718status_t AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>& args)
1719{
1720 const size_t SIZE = 256;
1721 char buffer[SIZE];
1722 String8 result;
1723
1724 PlaybackThread::dumpInternals(fd, args);
1725
1726 snprintf(buffer, SIZE, "AudioMixer tracks: %08x\n", mAudioMixer->trackNames());
1727 result.append(buffer);
1728 write(fd, result.string(), result.size());
1729 return NO_ERROR;
1730}
1731
Eric Laurent0e49d352009-11-09 23:32:22 -08001732uint32_t AudioFlinger::MixerThread::activeSleepTimeUs()
Eric Laurentf5e868b2009-10-05 20:29:18 -07001733{
Eric Laurent0e49d352009-11-09 23:32:22 -08001734 return (uint32_t)(mOutput->latency() * 1000) / 2;
1735}
1736
1737uint32_t AudioFlinger::MixerThread::idleSleepTimeUs()
1738{
1739 return (uint32_t)((mFrameCount * 1000) / mSampleRate) * 1000;
Eric Laurentf5e868b2009-10-05 20:29:18 -07001740}
1741
Eric Laurent9d91ad52009-07-17 12:17:14 -07001742// ----------------------------------------------------------------------------
Eric Laurent09b4ba82009-11-19 09:00:56 -08001743AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id)
1744 : PlaybackThread(audioFlinger, output, id),
Eric Laurent9d91ad52009-07-17 12:17:14 -07001745 mLeftVolume (1.0), mRightVolume(1.0)
1746{
1747 mType = PlaybackThread::DIRECT;
1748}
1749
1750AudioFlinger::DirectOutputThread::~DirectOutputThread()
1751{
1752}
1753
1754
1755bool AudioFlinger::DirectOutputThread::threadLoop()
1756{
Eric Laurent0e49d352009-11-09 23:32:22 -08001757 uint32_t mixerStatus = MIXER_IDLE;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001758 sp<Track> trackToRemove;
1759 sp<Track> activeTrack;
1760 nsecs_t standbyTime = systemTime();
1761 int8_t *curBuf;
1762 size_t mixBufferSize = mFrameCount*mFrameSize;
Eric Laurent0e49d352009-11-09 23:32:22 -08001763 uint32_t activeSleepTime = activeSleepTimeUs();
1764 uint32_t idleSleepTime = idleSleepTimeUs();
1765 uint32_t sleepTime = idleSleepTime;
Eric Laurent101e77a2010-03-11 14:47:00 -08001766 // use shorter standby delay as on normal output to release
1767 // hardware resources as soon as possible
1768 nsecs_t standbyDelay = microseconds(activeSleepTime*2);
Eric Laurent0e49d352009-11-09 23:32:22 -08001769
Eric Laurent9d91ad52009-07-17 12:17:14 -07001770
1771 while (!exitPending())
1772 {
1773 processConfigEvents();
1774
Eric Laurent0e49d352009-11-09 23:32:22 -08001775 mixerStatus = MIXER_IDLE;
1776
Eric Laurent9d91ad52009-07-17 12:17:14 -07001777 { // scope for the mLock
1778
1779 Mutex::Autolock _l(mLock);
1780
1781 if (checkForNewParameters_l()) {
1782 mixBufferSize = mFrameCount*mFrameSize;
Eric Laurent0e49d352009-11-09 23:32:22 -08001783 activeSleepTime = activeSleepTimeUs();
1784 idleSleepTime = idleSleepTimeUs();
Eric Laurent101e77a2010-03-11 14:47:00 -08001785 standbyDelay = microseconds(activeSleepTime*2);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001786 }
1787
1788 // put audio hardware into standby after short delay
1789 if UNLIKELY((!mActiveTracks.size() && systemTime() > standbyTime) ||
1790 mSuspended) {
1791 // wait until we have something to do...
1792 if (!mStandby) {
1793 LOGV("Audio hardware entering standby, mixer %p\n", this);
1794 mOutput->standby();
1795 mStandby = true;
1796 mBytesWritten = 0;
1797 }
1798
1799 if (!mActiveTracks.size() && mConfigEvents.isEmpty()) {
1800 // we're about to wait, flush the binder command buffer
1801 IPCThreadState::self()->flushCommands();
1802
1803 if (exitPending()) break;
1804
1805 LOGV("DirectOutputThread %p TID %d going to sleep\n", this, gettid());
1806 mWaitWorkCV.wait(mLock);
1807 LOGV("DirectOutputThread %p TID %d waking up in active mode\n", this, gettid());
1808
1809 if (mMasterMute == false) {
1810 char value[PROPERTY_VALUE_MAX];
1811 property_get("ro.audio.silent", value, "0");
1812 if (atoi(value)) {
1813 LOGD("Silence is golden");
1814 setMasterMute(true);
1815 }
1816 }
1817
Eric Laurent101e77a2010-03-11 14:47:00 -08001818 standbyTime = systemTime() + standbyDelay;
Eric Laurent0e49d352009-11-09 23:32:22 -08001819 sleepTime = idleSleepTime;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001820 continue;
1821 }
1822 }
1823
1824 // find out which tracks need to be processed
1825 if (mActiveTracks.size() != 0) {
1826 sp<Track> t = mActiveTracks[0].promote();
1827 if (t == 0) continue;
1828
1829 Track* const track = t.get();
1830 audio_track_cblk_t* cblk = track->cblk();
1831
1832 // The first time a track is added we wait
1833 // for all its buffers to be filled before processing it
1834 if (cblk->framesReady() && (track->isReady() || track->isStopped()) &&
Eric Laurent775fa3c2010-04-09 06:11:48 -07001835 !track->isPaused() && !track->isTerminated())
Eric Laurent9d91ad52009-07-17 12:17:14 -07001836 {
1837 //LOGV("track %d u=%08x, s=%08x [OK]", track->name(), cblk->user, cblk->server);
1838
1839 // compute volume for this track
1840 float left, right;
1841 if (track->isMuted() || mMasterMute || track->isPausing() ||
1842 mStreamTypes[track->type()].mute) {
1843 left = right = 0;
1844 if (track->isPausing()) {
1845 track->setPaused();
1846 }
1847 } else {
1848 float typeVolume = mStreamTypes[track->type()].volume;
1849 float v = mMasterVolume * typeVolume;
1850 float v_clamped = v * cblk->volume[0];
1851 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
1852 left = v_clamped/MAX_GAIN;
1853 v_clamped = v * cblk->volume[1];
1854 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
1855 right = v_clamped/MAX_GAIN;
1856 }
1857
1858 if (left != mLeftVolume || right != mRightVolume) {
1859 mOutput->setVolume(left, right);
1860 left = mLeftVolume;
1861 right = mRightVolume;
1862 }
1863
1864 if (track->mFillingUpStatus == Track::FS_FILLED) {
1865 track->mFillingUpStatus = Track::FS_ACTIVE;
1866 if (track->mState == TrackBase::RESUMING) {
1867 track->mState = TrackBase::ACTIVE;
1868 }
1869 }
1870
1871 // reset retry count
Eric Laurent101e77a2010-03-11 14:47:00 -08001872 track->mRetryCount = kMaxTrackRetriesDirect;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001873 activeTrack = t;
Eric Laurent0e49d352009-11-09 23:32:22 -08001874 mixerStatus = MIXER_TRACKS_READY;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001875 } else {
1876 //LOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
1877 if (track->isStopped()) {
1878 track->reset();
1879 }
1880 if (track->isTerminated() || track->isStopped() || track->isPaused()) {
1881 // We have consumed all the buffers of this track.
1882 // Remove it from the list of active tracks.
1883 trackToRemove = track;
1884 } else {
1885 // No buffers for this track. Give it a few chances to
1886 // fill a buffer, then remove it from active list.
1887 if (--(track->mRetryCount) <= 0) {
1888 LOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
1889 trackToRemove = track;
Eric Laurent0e49d352009-11-09 23:32:22 -08001890 } else {
1891 mixerStatus = MIXER_TRACKS_ENABLED;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001892 }
Eric Laurent0e49d352009-11-09 23:32:22 -08001893 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07001894 }
1895 }
1896
1897 // remove all the tracks that need to be...
1898 if (UNLIKELY(trackToRemove != 0)) {
1899 mActiveTracks.remove(trackToRemove);
1900 if (trackToRemove->isTerminated()) {
1901 mTracks.remove(trackToRemove);
1902 deleteTrackName_l(trackToRemove->mName);
1903 }
1904 }
1905 }
1906
Eric Laurent0e49d352009-11-09 23:32:22 -08001907 if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
Eric Laurentaef692f2009-09-22 00:35:48 -07001908 AudioBufferProvider::Buffer buffer;
1909 size_t frameCount = mFrameCount;
1910 curBuf = (int8_t *)mMixBuffer;
1911 // output audio to hardware
1912 while(frameCount) {
1913 buffer.frameCount = frameCount;
1914 activeTrack->getNextBuffer(&buffer);
1915 if (UNLIKELY(buffer.raw == 0)) {
1916 memset(curBuf, 0, frameCount * mFrameSize);
1917 break;
1918 }
1919 memcpy(curBuf, buffer.raw, buffer.frameCount * mFrameSize);
1920 frameCount -= buffer.frameCount;
1921 curBuf += buffer.frameCount * mFrameSize;
1922 activeTrack->releaseBuffer(&buffer);
1923 }
1924 sleepTime = 0;
Eric Laurent101e77a2010-03-11 14:47:00 -08001925 standbyTime = systemTime() + standbyDelay;
Eric Laurent3522c802009-09-07 08:38:38 -07001926 } else {
Eric Laurentf5e868b2009-10-05 20:29:18 -07001927 if (sleepTime == 0) {
Eric Laurent0e49d352009-11-09 23:32:22 -08001928 if (mixerStatus == MIXER_TRACKS_ENABLED) {
1929 sleepTime = activeSleepTime;
1930 } else {
1931 sleepTime = idleSleepTime;
1932 }
Eric Laurentf5e868b2009-10-05 20:29:18 -07001933 } else if (mBytesWritten != 0 && AudioSystem::isLinearPCM(mFormat)) {
Eric Laurentaef692f2009-09-22 00:35:48 -07001934 memset (mMixBuffer, 0, mFrameCount * mFrameSize);
Eric Laurent3522c802009-09-07 08:38:38 -07001935 sleepTime = 0;
Eric Laurent3522c802009-09-07 08:38:38 -07001936 }
Eric Laurentaef692f2009-09-22 00:35:48 -07001937 }
Eric Laurent3522c802009-09-07 08:38:38 -07001938
Eric Laurentaef692f2009-09-22 00:35:48 -07001939 if (mSuspended) {
Eric Laurent0e49d352009-11-09 23:32:22 -08001940 sleepTime = idleSleepTime;
Eric Laurentaef692f2009-09-22 00:35:48 -07001941 }
1942 // sleepTime == 0 means we must write to audio hardware
1943 if (sleepTime == 0) {
1944 mLastWriteTime = systemTime();
1945 mInWrite = true;
Eric Laurente9ed2722010-01-19 17:37:09 -08001946 mBytesWritten += mixBufferSize;
Eric Laurentaef692f2009-09-22 00:35:48 -07001947 int bytesWritten = (int)mOutput->write(mMixBuffer, mixBufferSize);
Eric Laurente9ed2722010-01-19 17:37:09 -08001948 if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
Eric Laurentaef692f2009-09-22 00:35:48 -07001949 mNumWrites++;
1950 mInWrite = false;
1951 mStandby = false;
1952 } else {
1953 usleep(sleepTime);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001954 }
1955
1956 // finally let go of removed track, without the lock held
1957 // since we can't guarantee the destructors won't acquire that
1958 // same lock.
1959 trackToRemove.clear();
1960 activeTrack.clear();
1961 }
1962
1963 if (!mStandby) {
1964 mOutput->standby();
1965 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07001966
1967 LOGV("DirectOutputThread %p exiting", this);
1968 return false;
1969}
1970
1971// getTrackName_l() must be called with ThreadBase::mLock held
1972int AudioFlinger::DirectOutputThread::getTrackName_l()
1973{
1974 return 0;
1975}
1976
1977// deleteTrackName_l() must be called with ThreadBase::mLock held
1978void AudioFlinger::DirectOutputThread::deleteTrackName_l(int name)
1979{
1980}
1981
1982// checkForNewParameters_l() must be called with ThreadBase::mLock held
1983bool AudioFlinger::DirectOutputThread::checkForNewParameters_l()
1984{
1985 bool reconfig = false;
1986
Eric Laurent3464c012009-08-04 09:45:33 -07001987 while (!mNewParameters.isEmpty()) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07001988 status_t status = NO_ERROR;
Eric Laurent3464c012009-08-04 09:45:33 -07001989 String8 keyValuePair = mNewParameters[0];
1990 AudioParameter param = AudioParameter(keyValuePair);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001991 int value;
Eric Laurent3464c012009-08-04 09:45:33 -07001992
Eric Laurent9d91ad52009-07-17 12:17:14 -07001993 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
1994 // do not accept frame count changes if tracks are open as the track buffer
1995 // size depends on frame count and correct behavior would not be garantied
1996 // if frame count is changed after track creation
1997 if (!mTracks.isEmpty()) {
1998 status = INVALID_OPERATION;
1999 } else {
2000 reconfig = true;
2001 }
2002 }
2003 if (status == NO_ERROR) {
Eric Laurent3464c012009-08-04 09:45:33 -07002004 status = mOutput->setParameters(keyValuePair);
Eric Laurent9d91ad52009-07-17 12:17:14 -07002005 if (!mStandby && status == INVALID_OPERATION) {
2006 mOutput->standby();
2007 mStandby = true;
2008 mBytesWritten = 0;
Eric Laurent3464c012009-08-04 09:45:33 -07002009 status = mOutput->setParameters(keyValuePair);
Eric Laurent9d91ad52009-07-17 12:17:14 -07002010 }
2011 if (status == NO_ERROR && reconfig) {
2012 readOutputParameters();
Eric Laurent3464c012009-08-04 09:45:33 -07002013 sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
Eric Laurent9d91ad52009-07-17 12:17:14 -07002014 }
2015 }
Eric Laurentee47d432009-11-07 00:01:32 -08002016
2017 mNewParameters.removeAt(0);
2018
Eric Laurent9d91ad52009-07-17 12:17:14 -07002019 mParamStatus = status;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002020 mParamCond.signal();
Eric Laurent3464c012009-08-04 09:45:33 -07002021 mWaitWorkCV.wait(mLock);
Eric Laurent9d91ad52009-07-17 12:17:14 -07002022 }
2023 return reconfig;
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08002024}
2025
Eric Laurent0e49d352009-11-09 23:32:22 -08002026uint32_t AudioFlinger::DirectOutputThread::activeSleepTimeUs()
Eric Laurentf5e868b2009-10-05 20:29:18 -07002027{
2028 uint32_t time;
2029 if (AudioSystem::isLinearPCM(mFormat)) {
Eric Laurent0e49d352009-11-09 23:32:22 -08002030 time = (uint32_t)(mOutput->latency() * 1000) / 2;
2031 } else {
2032 time = 10000;
2033 }
2034 return time;
2035}
2036
2037uint32_t AudioFlinger::DirectOutputThread::idleSleepTimeUs()
2038{
2039 uint32_t time;
2040 if (AudioSystem::isLinearPCM(mFormat)) {
2041 time = (uint32_t)((mFrameCount * 1000) / mSampleRate) * 1000;
Eric Laurentf5e868b2009-10-05 20:29:18 -07002042 } else {
2043 time = 10000;
2044 }
2045 return time;
2046}
2047
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002048// ----------------------------------------------------------------------------
2049
Eric Laurent09b4ba82009-11-19 09:00:56 -08002050AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger, AudioFlinger::MixerThread* mainThread, int id)
Eric Laurent7e2aad12009-12-18 05:47:48 -08002051 : MixerThread(audioFlinger, mainThread->getOutput(), id), mWaitTimeMs(UINT_MAX)
Eric Laurent9d91ad52009-07-17 12:17:14 -07002052{
2053 mType = PlaybackThread::DUPLICATING;
2054 addOutputTrack(mainThread);
2055}
2056
2057AudioFlinger::DuplicatingThread::~DuplicatingThread()
2058{
Eric Laurentfed93822009-12-07 10:53:10 -08002059 for (size_t i = 0; i < mOutputTracks.size(); i++) {
2060 mOutputTracks[i]->destroy();
2061 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002062 mOutputTracks.clear();
2063}
2064
2065bool AudioFlinger::DuplicatingThread::threadLoop()
2066{
Eric Laurent9d91ad52009-07-17 12:17:14 -07002067 int16_t* curBuf = mMixBuffer;
2068 Vector< sp<Track> > tracksToRemove;
Eric Laurent0e49d352009-11-09 23:32:22 -08002069 uint32_t mixerStatus = MIXER_IDLE;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002070 nsecs_t standbyTime = systemTime();
2071 size_t mixBufferSize = mFrameCount*mFrameSize;
2072 SortedVector< sp<OutputTrack> > outputTracks;
Eric Laurentf5e868b2009-10-05 20:29:18 -07002073 uint32_t writeFrames = 0;
Eric Laurent0e49d352009-11-09 23:32:22 -08002074 uint32_t activeSleepTime = activeSleepTimeUs();
2075 uint32_t idleSleepTime = idleSleepTimeUs();
2076 uint32_t sleepTime = idleSleepTime;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002077
2078 while (!exitPending())
2079 {
2080 processConfigEvents();
2081
Eric Laurent0e49d352009-11-09 23:32:22 -08002082 mixerStatus = MIXER_IDLE;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002083 { // scope for the mLock
2084
2085 Mutex::Autolock _l(mLock);
2086
2087 if (checkForNewParameters_l()) {
2088 mixBufferSize = mFrameCount*mFrameSize;
Eric Laurent7e2aad12009-12-18 05:47:48 -08002089 updateWaitTime();
Eric Laurent0e49d352009-11-09 23:32:22 -08002090 activeSleepTime = activeSleepTimeUs();
2091 idleSleepTime = idleSleepTimeUs();
Eric Laurent9d91ad52009-07-17 12:17:14 -07002092 }
2093
2094 const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
2095
2096 for (size_t i = 0; i < mOutputTracks.size(); i++) {
2097 outputTracks.add(mOutputTracks[i]);
2098 }
2099
2100 // put audio hardware into standby after short delay
2101 if UNLIKELY((!activeTracks.size() && systemTime() > standbyTime) ||
2102 mSuspended) {
2103 if (!mStandby) {
2104 for (size_t i = 0; i < outputTracks.size(); i++) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07002105 outputTracks[i]->stop();
Eric Laurent9d91ad52009-07-17 12:17:14 -07002106 }
2107 mStandby = true;
2108 mBytesWritten = 0;
2109 }
2110
2111 if (!activeTracks.size() && mConfigEvents.isEmpty()) {
2112 // we're about to wait, flush the binder command buffer
2113 IPCThreadState::self()->flushCommands();
2114 outputTracks.clear();
2115
2116 if (exitPending()) break;
2117
2118 LOGV("DuplicatingThread %p TID %d going to sleep\n", this, gettid());
2119 mWaitWorkCV.wait(mLock);
2120 LOGV("DuplicatingThread %p TID %d waking up\n", this, gettid());
2121 if (mMasterMute == false) {
2122 char value[PROPERTY_VALUE_MAX];
2123 property_get("ro.audio.silent", value, "0");
2124 if (atoi(value)) {
2125 LOGD("Silence is golden");
2126 setMasterMute(true);
2127 }
2128 }
2129
2130 standbyTime = systemTime() + kStandbyTimeInNsecs;
Eric Laurent0e49d352009-11-09 23:32:22 -08002131 sleepTime = idleSleepTime;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002132 continue;
2133 }
2134 }
2135
Eric Laurent0e49d352009-11-09 23:32:22 -08002136 mixerStatus = prepareTracks_l(activeTracks, &tracksToRemove);
Eric Laurentaef692f2009-09-22 00:35:48 -07002137 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002138
Eric Laurent0e49d352009-11-09 23:32:22 -08002139 if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07002140 // mix buffers...
Eric Laurent7e2aad12009-12-18 05:47:48 -08002141 if (outputsReady(outputTracks)) {
2142 mAudioMixer->process(curBuf);
2143 } else {
2144 memset(curBuf, 0, mixBufferSize);
2145 }
Eric Laurentaef692f2009-09-22 00:35:48 -07002146 sleepTime = 0;
Eric Laurentf5e868b2009-10-05 20:29:18 -07002147 writeFrames = mFrameCount;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002148 } else {
Eric Laurentf5e868b2009-10-05 20:29:18 -07002149 if (sleepTime == 0) {
Eric Laurent0e49d352009-11-09 23:32:22 -08002150 if (mixerStatus == MIXER_TRACKS_ENABLED) {
2151 sleepTime = activeSleepTime;
2152 } else {
2153 sleepTime = idleSleepTime;
2154 }
Eric Laurentf5e868b2009-10-05 20:29:18 -07002155 } else if (mBytesWritten != 0) {
2156 // flush remaining overflow buffers in output tracks
2157 for (size_t i = 0; i < outputTracks.size(); i++) {
2158 if (outputTracks[i]->isActive()) {
2159 sleepTime = 0;
2160 writeFrames = 0;
2161 break;
2162 }
2163 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002164 }
2165 }
Eric Laurentaef692f2009-09-22 00:35:48 -07002166
2167 if (mSuspended) {
Eric Laurent0e49d352009-11-09 23:32:22 -08002168 sleepTime = idleSleepTime;
Eric Laurentaef692f2009-09-22 00:35:48 -07002169 }
2170 // sleepTime == 0 means we must write to audio hardware
2171 if (sleepTime == 0) {
Eric Laurentf5e868b2009-10-05 20:29:18 -07002172 standbyTime = systemTime() + kStandbyTimeInNsecs;
Eric Laurentaef692f2009-09-22 00:35:48 -07002173 for (size_t i = 0; i < outputTracks.size(); i++) {
Eric Laurentf5e868b2009-10-05 20:29:18 -07002174 outputTracks[i]->write(curBuf, writeFrames);
Eric Laurent9d91ad52009-07-17 12:17:14 -07002175 }
Eric Laurentaef692f2009-09-22 00:35:48 -07002176 mStandby = false;
2177 mBytesWritten += mixBufferSize;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002178 } else {
Eric Laurentaef692f2009-09-22 00:35:48 -07002179 usleep(sleepTime);
Eric Laurent9d91ad52009-07-17 12:17:14 -07002180 }
2181
2182 // finally let go of all our tracks, without the lock held
2183 // since we can't guarantee the destructors won't acquire that
2184 // same lock.
2185 tracksToRemove.clear();
2186 outputTracks.clear();
2187 }
2188
Eric Laurent9d91ad52009-07-17 12:17:14 -07002189 return false;
2190}
2191
2192void AudioFlinger::DuplicatingThread::addOutputTrack(MixerThread *thread)
2193{
2194 int frameCount = (3 * mFrameCount * mSampleRate) / thread->sampleRate();
2195 OutputTrack *outputTrack = new OutputTrack((ThreadBase *)thread,
Eric Laurent7e2aad12009-12-18 05:47:48 -08002196 this,
Eric Laurent9d91ad52009-07-17 12:17:14 -07002197 mSampleRate,
2198 mFormat,
2199 mChannelCount,
2200 frameCount);
Eric Laurentf5aba822009-08-10 23:22:32 -07002201 if (outputTrack->cblk() != NULL) {
2202 thread->setStreamVolume(AudioSystem::NUM_STREAM_TYPES, 1.0f);
2203 mOutputTracks.add(outputTrack);
2204 LOGV("addOutputTrack() track %p, on thread %p", outputTrack, thread);
Eric Laurent7e2aad12009-12-18 05:47:48 -08002205 updateWaitTime();
Eric Laurentf5aba822009-08-10 23:22:32 -07002206 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002207}
2208
2209void AudioFlinger::DuplicatingThread::removeOutputTrack(MixerThread *thread)
2210{
2211 Mutex::Autolock _l(mLock);
2212 for (size_t i = 0; i < mOutputTracks.size(); i++) {
2213 if (mOutputTracks[i]->thread() == (ThreadBase *)thread) {
Eric Laurentf5aba822009-08-10 23:22:32 -07002214 mOutputTracks[i]->destroy();
Eric Laurent9d91ad52009-07-17 12:17:14 -07002215 mOutputTracks.removeAt(i);
Eric Laurent7e2aad12009-12-18 05:47:48 -08002216 updateWaitTime();
Eric Laurent9d91ad52009-07-17 12:17:14 -07002217 return;
2218 }
2219 }
2220 LOGV("removeOutputTrack(): unkonwn thread: %p", thread);
2221}
2222
Eric Laurent7e2aad12009-12-18 05:47:48 -08002223void AudioFlinger::DuplicatingThread::updateWaitTime()
2224{
2225 mWaitTimeMs = UINT_MAX;
2226 for (size_t i = 0; i < mOutputTracks.size(); i++) {
2227 sp<ThreadBase> strong = mOutputTracks[i]->thread().promote();
2228 if (strong != NULL) {
2229 uint32_t waitTimeMs = (strong->frameCount() * 2 * 1000) / strong->sampleRate();
2230 if (waitTimeMs < mWaitTimeMs) {
2231 mWaitTimeMs = waitTimeMs;
2232 }
2233 }
2234 }
2235}
2236
2237
2238bool AudioFlinger::DuplicatingThread::outputsReady(SortedVector< sp<OutputTrack> > &outputTracks)
2239{
2240 for (size_t i = 0; i < outputTracks.size(); i++) {
2241 sp <ThreadBase> thread = outputTracks[i]->thread().promote();
2242 if (thread == 0) {
2243 LOGW("DuplicatingThread::outputsReady() could not promote thread on output track %p", outputTracks[i].get());
2244 return false;
2245 }
2246 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
2247 if (playbackThread->standby() && !playbackThread->isSuspended()) {
2248 LOGV("DuplicatingThread output track %p on thread %p Not Ready", outputTracks[i].get(), thread.get());
2249 return false;
2250 }
2251 }
2252 return true;
2253}
2254
2255uint32_t AudioFlinger::DuplicatingThread::activeSleepTimeUs()
2256{
2257 return (mWaitTimeMs * 1000) / 2;
2258}
2259
Eric Laurent9d91ad52009-07-17 12:17:14 -07002260// ----------------------------------------------------------------------------
2261
The Android Open Source Project22f8def2009-03-09 11:52:12 -07002262// TrackBase constructor must be called with AudioFlinger::mLock held
Eric Laurent9d91ad52009-07-17 12:17:14 -07002263AudioFlinger::ThreadBase::TrackBase::TrackBase(
2264 const wp<ThreadBase>& thread,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002265 const sp<Client>& client,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002266 uint32_t sampleRate,
2267 int format,
2268 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002269 int frameCount,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002270 uint32_t flags,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002271 const sp<IMemory>& sharedBuffer)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002272 : RefBase(),
Eric Laurent9d91ad52009-07-17 12:17:14 -07002273 mThread(thread),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002274 mClient(client),
Eric Laurent6ad8c642009-09-09 05:16:08 -07002275 mCblk(0),
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002276 mFrameCount(0),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002277 mState(IDLE),
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002278 mClientTid(-1),
2279 mFormat(format),
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002280 mFlags(flags & ~SYSTEM_FLAGS_MASK)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002281{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002282 LOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size());
2283
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002284 // LOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002285 size_t size = sizeof(audio_track_cblk_t);
2286 size_t bufferSize = frameCount*channelCount*sizeof(int16_t);
2287 if (sharedBuffer == 0) {
2288 size += bufferSize;
2289 }
2290
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002291 if (client != NULL) {
2292 mCblkMemory = client->heap()->allocate(size);
2293 if (mCblkMemory != 0) {
2294 mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer());
2295 if (mCblk) { // construct the shared structure in-place.
2296 new(mCblk) audio_track_cblk_t();
2297 // clear all buffers
2298 mCblk->frameCount = frameCount;
Eric Laurent0bac5382009-07-07 07:10:45 -07002299 mCblk->sampleRate = sampleRate;
Eric Laurente1512162010-05-14 05:45:46 -07002300 mCblk->channelCount = (uint8_t)channelCount;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002301 if (sharedBuffer == 0) {
2302 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
2303 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
2304 // Force underrun condition to avoid false underrun callback until first data is
2305 // written to buffer
Eric Laurent4edfe752010-05-14 03:26:45 -07002306 mCblk->flags = CBLK_UNDERRUN_ON;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002307 } else {
2308 mBuffer = sharedBuffer->pointer();
2309 }
2310 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002311 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002312 } else {
2313 LOGE("not enough memory for AudioTrack size=%u", size);
2314 client->heap()->dump("AudioTrack");
2315 return;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002316 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002317 } else {
2318 mCblk = (audio_track_cblk_t *)(new uint8_t[size]);
2319 if (mCblk) { // construct the shared structure in-place.
2320 new(mCblk) audio_track_cblk_t();
2321 // clear all buffers
2322 mCblk->frameCount = frameCount;
Eric Laurent0bac5382009-07-07 07:10:45 -07002323 mCblk->sampleRate = sampleRate;
Eric Laurente1512162010-05-14 05:45:46 -07002324 mCblk->channelCount = (uint8_t)channelCount;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002325 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
2326 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
2327 // Force underrun condition to avoid false underrun callback until first data is
2328 // written to buffer
Eric Laurent4edfe752010-05-14 03:26:45 -07002329 mCblk->flags = CBLK_UNDERRUN_ON;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002330 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
2331 }
2332 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002333}
2334
Eric Laurentbdc0f842009-09-16 06:02:45 -07002335AudioFlinger::ThreadBase::TrackBase::~TrackBase()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002336{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002337 if (mCblk) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07002338 mCblk->~audio_track_cblk_t(); // destroy our shared-structure.
2339 if (mClient == NULL) {
2340 delete mCblk;
2341 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002342 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002343 mCblkMemory.clear(); // and free the shared memory
Eric Laurent0f8ab672009-09-17 05:12:56 -07002344 if (mClient != NULL) {
2345 Mutex::Autolock _l(mClient->audioFlinger()->mLock);
2346 mClient.clear();
2347 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002348}
2349
Eric Laurentbdc0f842009-09-16 06:02:45 -07002350void AudioFlinger::ThreadBase::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002351{
2352 buffer->raw = 0;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002353 mFrameCount = buffer->frameCount;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002354 step();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002355 buffer->frameCount = 0;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002356}
2357
Eric Laurentbdc0f842009-09-16 06:02:45 -07002358bool AudioFlinger::ThreadBase::TrackBase::step() {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002359 bool result;
2360 audio_track_cblk_t* cblk = this->cblk();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002361
2362 result = cblk->stepServer(mFrameCount);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002363 if (!result) {
2364 LOGV("stepServer failed acquiring cblk mutex");
2365 mFlags |= STEPSERVER_FAILED;
2366 }
2367 return result;
2368}
2369
Eric Laurentbdc0f842009-09-16 06:02:45 -07002370void AudioFlinger::ThreadBase::TrackBase::reset() {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002371 audio_track_cblk_t* cblk = this->cblk();
2372
2373 cblk->user = 0;
2374 cblk->server = 0;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002375 cblk->userBase = 0;
2376 cblk->serverBase = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002377 mFlags &= (uint32_t)(~SYSTEM_FLAGS_MASK);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002378 LOGV("TrackBase::reset");
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002379}
2380
Eric Laurentbdc0f842009-09-16 06:02:45 -07002381sp<IMemory> AudioFlinger::ThreadBase::TrackBase::getCblk() const
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002382{
2383 return mCblkMemory;
2384}
2385
Eric Laurentbdc0f842009-09-16 06:02:45 -07002386int AudioFlinger::ThreadBase::TrackBase::sampleRate() const {
The Android Open Source Project4f68be12009-03-18 17:39:46 -07002387 return (int)mCblk->sampleRate;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002388}
2389
Eric Laurentbdc0f842009-09-16 06:02:45 -07002390int AudioFlinger::ThreadBase::TrackBase::channelCount() const {
Eric Laurente1512162010-05-14 05:45:46 -07002391 return (int)mCblk->channelCount;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002392}
2393
Eric Laurentbdc0f842009-09-16 06:02:45 -07002394void* AudioFlinger::ThreadBase::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002395 audio_track_cblk_t* cblk = this->cblk();
Eric Laurent9d91ad52009-07-17 12:17:14 -07002396 int8_t *bufferStart = (int8_t *)mBuffer + (offset-cblk->serverBase)*cblk->frameSize;
2397 int8_t *bufferEnd = bufferStart + frames * cblk->frameSize;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002398
2399 // Check validity of returned pointer in case the track control block would have been corrupted.
Eric Laurent9d91ad52009-07-17 12:17:14 -07002400 if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd ||
2401 ((unsigned long)bufferStart & (unsigned long)(cblk->frameSize - 1))) {
The Android Open Source Project4f68be12009-03-18 17:39:46 -07002402 LOGE("TrackBase::getBuffer buffer out of range:\n start: %p, end %p , mBuffer %p mBufferEnd %p\n \
Eric Laurente1512162010-05-14 05:45:46 -07002403 server %d, serverBase %d, user %d, userBase %d, channelCount %d",
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002404 bufferStart, bufferEnd, mBuffer, mBufferEnd,
Eric Laurente1512162010-05-14 05:45:46 -07002405 cblk->server, cblk->serverBase, cblk->user, cblk->userBase, cblk->channelCount);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002406 return 0;
2407 }
2408
2409 return bufferStart;
2410}
2411
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002412// ----------------------------------------------------------------------------
2413
Eric Laurent9d91ad52009-07-17 12:17:14 -07002414// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
2415AudioFlinger::PlaybackThread::Track::Track(
2416 const wp<ThreadBase>& thread,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002417 const sp<Client>& client,
2418 int streamType,
2419 uint32_t sampleRate,
2420 int format,
2421 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002422 int frameCount,
2423 const sp<IMemory>& sharedBuffer)
Eric Laurent9d91ad52009-07-17 12:17:14 -07002424 : TrackBase(thread, client, sampleRate, format, channelCount, frameCount, 0, sharedBuffer),
2425 mMute(false), mSharedBuffer(sharedBuffer), mName(-1)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002426{
Eric Laurent6ad8c642009-09-09 05:16:08 -07002427 if (mCblk != NULL) {
2428 sp<ThreadBase> baseThread = thread.promote();
2429 if (baseThread != 0) {
2430 PlaybackThread *playbackThread = (PlaybackThread *)baseThread.get();
2431 mName = playbackThread->getTrackName_l();
2432 }
2433 LOGV("Track constructor name %d, calling thread %d", mName, IPCThreadState::self()->getCallingPid());
2434 if (mName < 0) {
2435 LOGE("no more track names available");
2436 }
2437 mVolume[0] = 1.0f;
2438 mVolume[1] = 1.0f;
2439 mStreamType = streamType;
2440 // NOTE: audio_track_cblk_t::frameSize for 8 bit PCM data is based on a sample size of
2441 // 16 bit because data is converted to 16 bit before being stored in buffer by AudioTrack
2442 mCblk->frameSize = AudioSystem::isLinearPCM(format) ? channelCount * sizeof(int16_t) : sizeof(int8_t);
Eric Laurent9d91ad52009-07-17 12:17:14 -07002443 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002444}
2445
Eric Laurent9d91ad52009-07-17 12:17:14 -07002446AudioFlinger::PlaybackThread::Track::~Track()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002447{
Eric Laurent9d91ad52009-07-17 12:17:14 -07002448 LOGV("PlaybackThread::Track destructor");
2449 sp<ThreadBase> thread = mThread.promote();
2450 if (thread != 0) {
Eric Laurentd3fc8ac2009-12-01 02:17:41 -08002451 Mutex::Autolock _l(thread->mLock);
Eric Laurent9d91ad52009-07-17 12:17:14 -07002452 mState = TERMINATED;
The Android Open Source Project22f8def2009-03-09 11:52:12 -07002453 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002454}
2455
Eric Laurent9d91ad52009-07-17 12:17:14 -07002456void AudioFlinger::PlaybackThread::Track::destroy()
2457{
2458 // NOTE: destroyTrack_l() can remove a strong reference to this Track
2459 // by removing it from mTracks vector, so there is a risk that this Tracks's
2460 // desctructor is called. As the destructor needs to lock mLock,
2461 // we must acquire a strong reference on this Track before locking mLock
2462 // here so that the destructor is called only when exiting this function.
2463 // On the other hand, as long as Track::destroy() is only called by
2464 // TrackHandle destructor, the TrackHandle still holds a strong ref on
2465 // this Track with its member mTrack.
2466 sp<Track> keep(this);
2467 { // scope for mLock
2468 sp<ThreadBase> thread = mThread.promote();
2469 if (thread != 0) {
Eric Laurentd3fc8ac2009-12-01 02:17:41 -08002470 if (!isOutputTrack()) {
2471 if (mState == ACTIVE || mState == RESUMING) {
2472 AudioSystem::stopOutput(thread->id(), (AudioSystem::stream_type)mStreamType);
2473 }
2474 AudioSystem::releaseOutput(thread->id());
Eric Laurent09b4ba82009-11-19 09:00:56 -08002475 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002476 Mutex::Autolock _l(thread->mLock);
2477 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
2478 playbackThread->destroyTrack_l(this);
2479 }
2480 }
2481}
2482
2483void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002484{
Eric Laurentee47d432009-11-07 00:01:32 -08002485 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 -07002486 mName - AudioMixer::TRACK0,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002487 (mClient == NULL) ? getpid() : mClient->pid(),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002488 mStreamType,
2489 mFormat,
Eric Laurente1512162010-05-14 05:45:46 -07002490 mCblk->channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002491 mFrameCount,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002492 mState,
2493 mMute,
2494 mFillingUpStatus,
2495 mCblk->sampleRate,
2496 mCblk->volume[0],
2497 mCblk->volume[1],
2498 mCblk->server,
2499 mCblk->user);
2500}
2501
Eric Laurent9d91ad52009-07-17 12:17:14 -07002502status_t AudioFlinger::PlaybackThread::Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002503{
2504 audio_track_cblk_t* cblk = this->cblk();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002505 uint32_t framesReady;
2506 uint32_t framesReq = buffer->frameCount;
2507
2508 // Check if last stepServer failed, try to step now
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002509 if (mFlags & TrackBase::STEPSERVER_FAILED) {
2510 if (!step()) goto getNextBuffer_exit;
2511 LOGV("stepServer recovered");
2512 mFlags &= ~TrackBase::STEPSERVER_FAILED;
2513 }
2514
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002515 framesReady = cblk->framesReady();
2516
2517 if (LIKELY(framesReady)) {
2518 uint32_t s = cblk->server;
2519 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
2520
2521 bufferEnd = (cblk->loopEnd < bufferEnd) ? cblk->loopEnd : bufferEnd;
2522 if (framesReq > framesReady) {
2523 framesReq = framesReady;
2524 }
2525 if (s + framesReq > bufferEnd) {
2526 framesReq = bufferEnd - s;
2527 }
2528
2529 buffer->raw = getBuffer(s, framesReq);
2530 if (buffer->raw == 0) goto getNextBuffer_exit;
2531
2532 buffer->frameCount = framesReq;
2533 return NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002534 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002535
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002536getNextBuffer_exit:
2537 buffer->raw = 0;
2538 buffer->frameCount = 0;
Eric Laurentf5e868b2009-10-05 20:29:18 -07002539 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 -07002540 return NOT_ENOUGH_DATA;
2541}
2542
Eric Laurent9d91ad52009-07-17 12:17:14 -07002543bool AudioFlinger::PlaybackThread::Track::isReady() const {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002544 if (mFillingUpStatus != FS_FILLING) return true;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002545
2546 if (mCblk->framesReady() >= mCblk->frameCount ||
Eric Laurent4edfe752010-05-14 03:26:45 -07002547 (mCblk->flags & CBLK_FORCEREADY_MSK)) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002548 mFillingUpStatus = FS_FILLED;
Eric Laurent4edfe752010-05-14 03:26:45 -07002549 mCblk->flags &= ~CBLK_FORCEREADY_MSK;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002550 return true;
2551 }
2552 return false;
2553}
2554
Eric Laurent9d91ad52009-07-17 12:17:14 -07002555status_t AudioFlinger::PlaybackThread::Track::start()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002556{
Eric Laurent09b4ba82009-11-19 09:00:56 -08002557 status_t status = NO_ERROR;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002558 LOGV("start(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
2559 sp<ThreadBase> thread = mThread.promote();
2560 if (thread != 0) {
2561 Mutex::Autolock _l(thread->mLock);
Eric Laurent09b4ba82009-11-19 09:00:56 -08002562 int state = mState;
2563 // here the track could be either new, or restarted
2564 // in both cases "unstop" the track
2565 if (mState == PAUSED) {
2566 mState = TrackBase::RESUMING;
2567 LOGV("PAUSED => RESUMING (%d) on thread %p", mName, this);
2568 } else {
2569 mState = TrackBase::ACTIVE;
2570 LOGV("? => ACTIVE (%d) on thread %p", mName, this);
2571 }
2572
2573 if (!isOutputTrack() && state != ACTIVE && state != RESUMING) {
2574 thread->mLock.unlock();
2575 status = AudioSystem::startOutput(thread->id(), (AudioSystem::stream_type)mStreamType);
2576 thread->mLock.lock();
2577 }
2578 if (status == NO_ERROR) {
2579 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
2580 playbackThread->addTrack_l(this);
2581 } else {
2582 mState = state;
2583 }
2584 } else {
2585 status = BAD_VALUE;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002586 }
Eric Laurent09b4ba82009-11-19 09:00:56 -08002587 return status;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002588}
2589
Eric Laurent9d91ad52009-07-17 12:17:14 -07002590void AudioFlinger::PlaybackThread::Track::stop()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002591{
Eric Laurent9d91ad52009-07-17 12:17:14 -07002592 LOGV("stop(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
2593 sp<ThreadBase> thread = mThread.promote();
2594 if (thread != 0) {
2595 Mutex::Autolock _l(thread->mLock);
Eric Laurent09b4ba82009-11-19 09:00:56 -08002596 int state = mState;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002597 if (mState > STOPPED) {
2598 mState = STOPPED;
2599 // If the track is not active (PAUSED and buffers full), flush buffers
2600 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
2601 if (playbackThread->mActiveTracks.indexOf(this) < 0) {
2602 reset();
2603 }
Eric Laurentf5e868b2009-10-05 20:29:18 -07002604 LOGV("(> STOPPED) => STOPPED (%d) on thread %p", mName, playbackThread);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002605 }
Eric Laurent09b4ba82009-11-19 09:00:56 -08002606 if (!isOutputTrack() && (state == ACTIVE || state == RESUMING)) {
2607 thread->mLock.unlock();
2608 AudioSystem::stopOutput(thread->id(), (AudioSystem::stream_type)mStreamType);
2609 thread->mLock.lock();
2610 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002611 }
2612}
2613
Eric Laurent9d91ad52009-07-17 12:17:14 -07002614void AudioFlinger::PlaybackThread::Track::pause()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002615{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002616 LOGV("pause(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
Eric Laurent9d91ad52009-07-17 12:17:14 -07002617 sp<ThreadBase> thread = mThread.promote();
2618 if (thread != 0) {
2619 Mutex::Autolock _l(thread->mLock);
2620 if (mState == ACTIVE || mState == RESUMING) {
2621 mState = PAUSING;
Eric Laurentf5e868b2009-10-05 20:29:18 -07002622 LOGV("ACTIVE/RESUMING => PAUSING (%d) on thread %p", mName, thread.get());
Eric Laurent09b4ba82009-11-19 09:00:56 -08002623 if (!isOutputTrack()) {
2624 thread->mLock.unlock();
2625 AudioSystem::stopOutput(thread->id(), (AudioSystem::stream_type)mStreamType);
2626 thread->mLock.lock();
2627 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002628 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002629 }
2630}
2631
Eric Laurent9d91ad52009-07-17 12:17:14 -07002632void AudioFlinger::PlaybackThread::Track::flush()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002633{
2634 LOGV("flush(%d)", mName);
Eric Laurent9d91ad52009-07-17 12:17:14 -07002635 sp<ThreadBase> thread = mThread.promote();
2636 if (thread != 0) {
2637 Mutex::Autolock _l(thread->mLock);
2638 if (mState != STOPPED && mState != PAUSED && mState != PAUSING) {
2639 return;
2640 }
2641 // No point remaining in PAUSED state after a flush => go to
2642 // STOPPED state
2643 mState = STOPPED;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002644
Eric Laurent9d91ad52009-07-17 12:17:14 -07002645 mCblk->lock.lock();
2646 // NOTE: reset() will reset cblk->user and cblk->server with
2647 // the risk that at the same time, the AudioMixer is trying to read
2648 // data. In this case, getNextBuffer() would return a NULL pointer
2649 // as audio buffer => the AudioMixer code MUST always test that pointer
2650 // returned by getNextBuffer() is not NULL!
2651 reset();
2652 mCblk->lock.unlock();
2653 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002654}
2655
Eric Laurent9d91ad52009-07-17 12:17:14 -07002656void AudioFlinger::PlaybackThread::Track::reset()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002657{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002658 // Do not reset twice to avoid discarding data written just after a flush and before
2659 // the audioflinger thread detects the track is stopped.
2660 if (!mResetDone) {
2661 TrackBase::reset();
2662 // Force underrun condition to avoid false underrun callback until first data is
2663 // written to buffer
Eric Laurent4edfe752010-05-14 03:26:45 -07002664 mCblk->flags |= CBLK_UNDERRUN_ON;
2665 mCblk->flags &= ~CBLK_FORCEREADY_MSK;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002666 mFillingUpStatus = FS_FILLING;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002667 mResetDone = true;
2668 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002669}
2670
Eric Laurent9d91ad52009-07-17 12:17:14 -07002671void AudioFlinger::PlaybackThread::Track::mute(bool muted)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002672{
2673 mMute = muted;
2674}
2675
Eric Laurent9d91ad52009-07-17 12:17:14 -07002676void AudioFlinger::PlaybackThread::Track::setVolume(float left, float right)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002677{
2678 mVolume[0] = left;
2679 mVolume[1] = right;
2680}
2681
2682// ----------------------------------------------------------------------------
2683
The Android Open Source Project22f8def2009-03-09 11:52:12 -07002684// RecordTrack constructor must be called with AudioFlinger::mLock held
Eric Laurent9d91ad52009-07-17 12:17:14 -07002685AudioFlinger::RecordThread::RecordTrack::RecordTrack(
2686 const wp<ThreadBase>& thread,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002687 const sp<Client>& client,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002688 uint32_t sampleRate,
2689 int format,
2690 int channelCount,
2691 int frameCount,
2692 uint32_t flags)
Eric Laurent9d91ad52009-07-17 12:17:14 -07002693 : TrackBase(thread, client, sampleRate, format,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002694 channelCount, frameCount, flags, 0),
Eric Laurent9d91ad52009-07-17 12:17:14 -07002695 mOverflow(false)
2696{
Eric Laurent6ad8c642009-09-09 05:16:08 -07002697 if (mCblk != NULL) {
2698 LOGV("RecordTrack constructor, size %d", (int)mBufferEnd - (int)mBuffer);
2699 if (format == AudioSystem::PCM_16_BIT) {
2700 mCblk->frameSize = channelCount * sizeof(int16_t);
2701 } else if (format == AudioSystem::PCM_8_BIT) {
2702 mCblk->frameSize = channelCount * sizeof(int8_t);
2703 } else {
2704 mCblk->frameSize = sizeof(int8_t);
2705 }
2706 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002707}
2708
2709AudioFlinger::RecordThread::RecordTrack::~RecordTrack()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002710{
Eric Laurent09b4ba82009-11-19 09:00:56 -08002711 sp<ThreadBase> thread = mThread.promote();
2712 if (thread != 0) {
2713 AudioSystem::releaseInput(thread->id());
2714 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002715}
2716
Eric Laurent9d91ad52009-07-17 12:17:14 -07002717status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002718{
2719 audio_track_cblk_t* cblk = this->cblk();
2720 uint32_t framesAvail;
2721 uint32_t framesReq = buffer->frameCount;
2722
2723 // Check if last stepServer failed, try to step now
2724 if (mFlags & TrackBase::STEPSERVER_FAILED) {
2725 if (!step()) goto getNextBuffer_exit;
2726 LOGV("stepServer recovered");
2727 mFlags &= ~TrackBase::STEPSERVER_FAILED;
2728 }
2729
2730 framesAvail = cblk->framesAvailable_l();
2731
2732 if (LIKELY(framesAvail)) {
2733 uint32_t s = cblk->server;
2734 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
2735
2736 if (framesReq > framesAvail) {
2737 framesReq = framesAvail;
2738 }
2739 if (s + framesReq > bufferEnd) {
2740 framesReq = bufferEnd - s;
2741 }
2742
2743 buffer->raw = getBuffer(s, framesReq);
2744 if (buffer->raw == 0) goto getNextBuffer_exit;
2745
2746 buffer->frameCount = framesReq;
2747 return NO_ERROR;
2748 }
2749
2750getNextBuffer_exit:
2751 buffer->raw = 0;
2752 buffer->frameCount = 0;
2753 return NOT_ENOUGH_DATA;
2754}
2755
Eric Laurent9d91ad52009-07-17 12:17:14 -07002756status_t AudioFlinger::RecordThread::RecordTrack::start()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002757{
Eric Laurent9d91ad52009-07-17 12:17:14 -07002758 sp<ThreadBase> thread = mThread.promote();
2759 if (thread != 0) {
2760 RecordThread *recordThread = (RecordThread *)thread.get();
2761 return recordThread->start(this);
Eric Laurent09b4ba82009-11-19 09:00:56 -08002762 } else {
2763 return BAD_VALUE;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002764 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002765}
2766
Eric Laurent9d91ad52009-07-17 12:17:14 -07002767void AudioFlinger::RecordThread::RecordTrack::stop()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002768{
Eric Laurent9d91ad52009-07-17 12:17:14 -07002769 sp<ThreadBase> thread = mThread.promote();
2770 if (thread != 0) {
2771 RecordThread *recordThread = (RecordThread *)thread.get();
2772 recordThread->stop(this);
2773 TrackBase::reset();
2774 // Force overerrun condition to avoid false overrun callback until first data is
2775 // read from buffer
Eric Laurent4edfe752010-05-14 03:26:45 -07002776 mCblk->flags |= CBLK_UNDERRUN_ON;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002777 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002778}
2779
Eric Laurentee47d432009-11-07 00:01:32 -08002780void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size)
2781{
2782 snprintf(buffer, size, " %05d %03u %03u %04u %01d %05u %08x %08x\n",
2783 (mClient == NULL) ? getpid() : mClient->pid(),
2784 mFormat,
Eric Laurente1512162010-05-14 05:45:46 -07002785 mCblk->channelCount,
Eric Laurentee47d432009-11-07 00:01:32 -08002786 mFrameCount,
2787 mState,
2788 mCblk->sampleRate,
2789 mCblk->server,
2790 mCblk->user);
2791}
2792
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002793
2794// ----------------------------------------------------------------------------
2795
Eric Laurent9d91ad52009-07-17 12:17:14 -07002796AudioFlinger::PlaybackThread::OutputTrack::OutputTrack(
2797 const wp<ThreadBase>& thread,
Eric Laurent7e2aad12009-12-18 05:47:48 -08002798 DuplicatingThread *sourceThread,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002799 uint32_t sampleRate,
2800 int format,
2801 int channelCount,
2802 int frameCount)
Eric Laurent9d91ad52009-07-17 12:17:14 -07002803 : Track(thread, NULL, AudioSystem::NUM_STREAM_TYPES, sampleRate, format, channelCount, frameCount, NULL),
Eric Laurent7e2aad12009-12-18 05:47:48 -08002804 mActive(false), mSourceThread(sourceThread)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002805{
Eric Laurent9d91ad52009-07-17 12:17:14 -07002806
2807 PlaybackThread *playbackThread = (PlaybackThread *)thread.unsafe_get();
Eric Laurentf5aba822009-08-10 23:22:32 -07002808 if (mCblk != NULL) {
Eric Laurent4edfe752010-05-14 03:26:45 -07002809 mCblk->flags |= CBLK_DIRECTION_OUT;
Eric Laurentf5aba822009-08-10 23:22:32 -07002810 mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
2811 mCblk->volume[0] = mCblk->volume[1] = 0x1000;
2812 mOutBuffer.frameCount = 0;
Eric Laurentf5aba822009-08-10 23:22:32 -07002813 playbackThread->mTracks.add(this);
Eric Laurente1512162010-05-14 05:45:46 -07002814 LOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, mCblk->frameCount %d, mCblk->sampleRate %d, mCblk->channelCount %d mBufferEnd %p",
2815 mCblk, mBuffer, mCblk->buffers, mCblk->frameCount, mCblk->sampleRate, mCblk->channelCount, mBufferEnd);
Eric Laurentf5aba822009-08-10 23:22:32 -07002816 } else {
2817 LOGW("Error creating output track on thread %p", playbackThread);
2818 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002819}
2820
Eric Laurent9d91ad52009-07-17 12:17:14 -07002821AudioFlinger::PlaybackThread::OutputTrack::~OutputTrack()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002822{
Eric Laurentf5aba822009-08-10 23:22:32 -07002823 clearBufferQueue();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002824}
2825
Eric Laurent9d91ad52009-07-17 12:17:14 -07002826status_t AudioFlinger::PlaybackThread::OutputTrack::start()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002827{
2828 status_t status = Track::start();
Eric Laurent9d91ad52009-07-17 12:17:14 -07002829 if (status != NO_ERROR) {
2830 return status;
2831 }
2832
2833 mActive = true;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002834 mRetryCount = 127;
2835 return status;
2836}
2837
Eric Laurent9d91ad52009-07-17 12:17:14 -07002838void AudioFlinger::PlaybackThread::OutputTrack::stop()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002839{
2840 Track::stop();
2841 clearBufferQueue();
2842 mOutBuffer.frameCount = 0;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002843 mActive = false;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002844}
2845
Eric Laurent9d91ad52009-07-17 12:17:14 -07002846bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t frames)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002847{
2848 Buffer *pInBuffer;
2849 Buffer inBuffer;
Eric Laurente1512162010-05-14 05:45:46 -07002850 uint32_t channelCount = mCblk->channelCount;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002851 bool outputBufferFull = false;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002852 inBuffer.frameCount = frames;
2853 inBuffer.i16 = data;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002854
Eric Laurent7e2aad12009-12-18 05:47:48 -08002855 uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
Eric Laurent9d91ad52009-07-17 12:17:14 -07002856
Eric Laurentf5e868b2009-10-05 20:29:18 -07002857 if (!mActive && frames != 0) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07002858 start();
2859 sp<ThreadBase> thread = mThread.promote();
2860 if (thread != 0) {
2861 MixerThread *mixerThread = (MixerThread *)thread.get();
2862 if (mCblk->frameCount > frames){
2863 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
2864 uint32_t startFrames = (mCblk->frameCount - frames);
2865 pInBuffer = new Buffer;
Eric Laurente1512162010-05-14 05:45:46 -07002866 pInBuffer->mBuffer = new int16_t[startFrames * channelCount];
Eric Laurent9d91ad52009-07-17 12:17:14 -07002867 pInBuffer->frameCount = startFrames;
2868 pInBuffer->i16 = pInBuffer->mBuffer;
Eric Laurente1512162010-05-14 05:45:46 -07002869 memset(pInBuffer->raw, 0, startFrames * channelCount * sizeof(int16_t));
Eric Laurent9d91ad52009-07-17 12:17:14 -07002870 mBufferQueue.add(pInBuffer);
2871 } else {
2872 LOGW ("OutputTrack::write() %p no more buffers in queue", this);
2873 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002874 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002875 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002876 }
2877
Eric Laurent9d91ad52009-07-17 12:17:14 -07002878 while (waitTimeLeftMs) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002879 // First write pending buffers, then new data
2880 if (mBufferQueue.size()) {
2881 pInBuffer = mBufferQueue.itemAt(0);
2882 } else {
2883 pInBuffer = &inBuffer;
2884 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002885
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002886 if (pInBuffer->frameCount == 0) {
2887 break;
2888 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002889
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002890 if (mOutBuffer.frameCount == 0) {
2891 mOutBuffer.frameCount = pInBuffer->frameCount;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002892 nsecs_t startTime = systemTime();
2893 if (obtainBuffer(&mOutBuffer, waitTimeLeftMs) == (status_t)AudioTrack::NO_MORE_BUFFERS) {
Eric Laurent7e2aad12009-12-18 05:47:48 -08002894 LOGV ("OutputTrack::write() %p thread %p no more output buffers", this, mThread.unsafe_get());
Eric Laurent9d91ad52009-07-17 12:17:14 -07002895 outputBufferFull = true;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002896 break;
2897 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002898 uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
Eric Laurent9d91ad52009-07-17 12:17:14 -07002899 if (waitTimeLeftMs >= waitTimeMs) {
2900 waitTimeLeftMs -= waitTimeMs;
2901 } else {
2902 waitTimeLeftMs = 0;
2903 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002904 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002905
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002906 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount : pInBuffer->frameCount;
Eric Laurente1512162010-05-14 05:45:46 -07002907 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * channelCount * sizeof(int16_t));
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002908 mCblk->stepUser(outFrames);
2909 pInBuffer->frameCount -= outFrames;
Eric Laurente1512162010-05-14 05:45:46 -07002910 pInBuffer->i16 += outFrames * channelCount;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002911 mOutBuffer.frameCount -= outFrames;
Eric Laurente1512162010-05-14 05:45:46 -07002912 mOutBuffer.i16 += outFrames * channelCount;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002913
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002914 if (pInBuffer->frameCount == 0) {
2915 if (mBufferQueue.size()) {
2916 mBufferQueue.removeAt(0);
2917 delete [] pInBuffer->mBuffer;
2918 delete pInBuffer;
Eric Laurent7e2aad12009-12-18 05:47:48 -08002919 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 -08002920 } else {
2921 break;
2922 }
2923 }
2924 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002925
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002926 // If we could not write all frames, allocate a buffer and queue it for next time.
2927 if (inBuffer.frameCount) {
Eric Laurent7e2aad12009-12-18 05:47:48 -08002928 sp<ThreadBase> thread = mThread.promote();
2929 if (thread != 0 && !thread->standby()) {
2930 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
2931 pInBuffer = new Buffer;
Eric Laurente1512162010-05-14 05:45:46 -07002932 pInBuffer->mBuffer = new int16_t[inBuffer.frameCount * channelCount];
Eric Laurent7e2aad12009-12-18 05:47:48 -08002933 pInBuffer->frameCount = inBuffer.frameCount;
2934 pInBuffer->i16 = pInBuffer->mBuffer;
Eric Laurente1512162010-05-14 05:45:46 -07002935 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * channelCount * sizeof(int16_t));
Eric Laurent7e2aad12009-12-18 05:47:48 -08002936 mBufferQueue.add(pInBuffer);
2937 LOGV("OutputTrack::write() %p thread %p adding overflow buffer %d", this, mThread.unsafe_get(), mBufferQueue.size());
2938 } else {
2939 LOGW("OutputTrack::write() %p thread %p no more overflow buffers", mThread.unsafe_get(), this);
2940 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002941 }
2942 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002943
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002944 // Calling write() with a 0 length buffer, means that no more data will be written:
Eric Laurent9d91ad52009-07-17 12:17:14 -07002945 // 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 -08002946 // by output mixer.
Eric Laurent9d91ad52009-07-17 12:17:14 -07002947 if (frames == 0 && mBufferQueue.size() == 0) {
2948 if (mCblk->user < mCblk->frameCount) {
2949 frames = mCblk->frameCount - mCblk->user;
2950 pInBuffer = new Buffer;
Eric Laurente1512162010-05-14 05:45:46 -07002951 pInBuffer->mBuffer = new int16_t[frames * channelCount];
Eric Laurent9d91ad52009-07-17 12:17:14 -07002952 pInBuffer->frameCount = frames;
2953 pInBuffer->i16 = pInBuffer->mBuffer;
Eric Laurente1512162010-05-14 05:45:46 -07002954 memset(pInBuffer->raw, 0, frames * channelCount * sizeof(int16_t));
Eric Laurent9d91ad52009-07-17 12:17:14 -07002955 mBufferQueue.add(pInBuffer);
Eric Laurentf5e868b2009-10-05 20:29:18 -07002956 } else if (mActive) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07002957 stop();
2958 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002959 }
2960
Eric Laurent9d91ad52009-07-17 12:17:14 -07002961 return outputBufferFull;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002962}
2963
Eric Laurent9d91ad52009-07-17 12:17:14 -07002964status_t AudioFlinger::PlaybackThread::OutputTrack::obtainBuffer(AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002965{
2966 int active;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002967 status_t result;
2968 audio_track_cblk_t* cblk = mCblk;
2969 uint32_t framesReq = buffer->frameCount;
2970
Eric Laurent9d91ad52009-07-17 12:17:14 -07002971// LOGV("OutputTrack::obtainBuffer user %d, server %d", cblk->user, cblk->server);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002972 buffer->frameCount = 0;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002973
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002974 uint32_t framesAvail = cblk->framesAvailable();
2975
Eric Laurent9d91ad52009-07-17 12:17:14 -07002976
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002977 if (framesAvail == 0) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07002978 Mutex::Autolock _l(cblk->lock);
2979 goto start_loop_here;
2980 while (framesAvail == 0) {
2981 active = mActive;
2982 if (UNLIKELY(!active)) {
2983 LOGV("Not active and NO_MORE_BUFFERS");
2984 return AudioTrack::NO_MORE_BUFFERS;
2985 }
2986 result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
2987 if (result != NO_ERROR) {
2988 return AudioTrack::NO_MORE_BUFFERS;
2989 }
2990 // read the server count again
2991 start_loop_here:
2992 framesAvail = cblk->framesAvailable_l();
2993 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002994 }
2995
Eric Laurent9d91ad52009-07-17 12:17:14 -07002996// if (framesAvail < framesReq) {
2997// return AudioTrack::NO_MORE_BUFFERS;
2998// }
2999
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08003000 if (framesReq > framesAvail) {
3001 framesReq = framesAvail;
3002 }
3003
3004 uint32_t u = cblk->user;
3005 uint32_t bufferEnd = cblk->userBase + cblk->frameCount;
3006
3007 if (u + framesReq > bufferEnd) {
3008 framesReq = bufferEnd - u;
3009 }
3010
3011 buffer->frameCount = framesReq;
3012 buffer->raw = (void *)cblk->buffer(u);
3013 return NO_ERROR;
3014}
3015
3016
Eric Laurent9d91ad52009-07-17 12:17:14 -07003017void AudioFlinger::PlaybackThread::OutputTrack::clearBufferQueue()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08003018{
3019 size_t size = mBufferQueue.size();
3020 Buffer *pBuffer;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003021
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08003022 for (size_t i = 0; i < size; i++) {
3023 pBuffer = mBufferQueue.itemAt(i);
3024 delete [] pBuffer->mBuffer;
3025 delete pBuffer;
3026 }
3027 mBufferQueue.clear();
3028}
3029
3030// ----------------------------------------------------------------------------
3031
3032AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
3033 : RefBase(),
3034 mAudioFlinger(audioFlinger),
Mathias Agopian0dd0d292010-01-25 19:00:00 -08003035 mMemoryDealer(new MemoryDealer(1024*1024, "AudioFlinger::Client")),
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08003036 mPid(pid)
3037{
3038 // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
3039}
3040
Eric Laurent0f8ab672009-09-17 05:12:56 -07003041// Client destructor must be called with AudioFlinger::mLock held
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08003042AudioFlinger::Client::~Client()
3043{
Eric Laurent0f8ab672009-09-17 05:12:56 -07003044 mAudioFlinger->removeClient_l(mPid);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08003045}
3046
3047const sp<MemoryDealer>& AudioFlinger::Client::heap() const
3048{
3049 return mMemoryDealer;
3050}
3051
3052// ----------------------------------------------------------------------------
3053
Eric Laurentd878cd82010-05-12 02:05:53 -07003054AudioFlinger::NotificationClient::NotificationClient(const sp<AudioFlinger>& audioFlinger,
3055 const sp<IAudioFlingerClient>& client,
3056 pid_t pid)
3057 : mAudioFlinger(audioFlinger), mPid(pid), mClient(client)
3058{
3059}
3060
3061AudioFlinger::NotificationClient::~NotificationClient()
3062{
3063 mClient.clear();
3064}
3065
3066void AudioFlinger::NotificationClient::binderDied(const wp<IBinder>& who)
3067{
3068 sp<NotificationClient> keep(this);
3069 {
3070 mAudioFlinger->removeNotificationClient(mPid);
3071 }
3072}
3073
3074// ----------------------------------------------------------------------------
3075
Eric Laurent9d91ad52009-07-17 12:17:14 -07003076AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::PlaybackThread::Track>& track)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003077 : BnAudioTrack(),
3078 mTrack(track)
3079{
3080}
3081
3082AudioFlinger::TrackHandle::~TrackHandle() {
3083 // just stop the track on deletion, associated resources
3084 // will be freed from the main thread once all pending buffers have
3085 // been played. Unless it's not in the active track list, in which
3086 // case we free everything now...
3087 mTrack->destroy();
3088}
3089
3090status_t AudioFlinger::TrackHandle::start() {
3091 return mTrack->start();
3092}
3093
3094void AudioFlinger::TrackHandle::stop() {
3095 mTrack->stop();
3096}
3097
3098void AudioFlinger::TrackHandle::flush() {
3099 mTrack->flush();
3100}
3101
3102void AudioFlinger::TrackHandle::mute(bool e) {
3103 mTrack->mute(e);
3104}
3105
3106void AudioFlinger::TrackHandle::pause() {
3107 mTrack->pause();
3108}
3109
3110void AudioFlinger::TrackHandle::setVolume(float left, float right) {
3111 mTrack->setVolume(left, right);
3112}
3113
3114sp<IMemory> AudioFlinger::TrackHandle::getCblk() const {
3115 return mTrack->getCblk();
3116}
3117
3118status_t AudioFlinger::TrackHandle::onTransact(
3119 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
3120{
3121 return BnAudioTrack::onTransact(code, data, reply, flags);
3122}
3123
3124// ----------------------------------------------------------------------------
3125
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003126sp<IAudioRecord> AudioFlinger::openRecord(
3127 pid_t pid,
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003128 int input,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003129 uint32_t sampleRate,
3130 int format,
3131 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08003132 int frameCount,
3133 uint32_t flags,
3134 status_t *status)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003135{
Eric Laurent9d91ad52009-07-17 12:17:14 -07003136 sp<RecordThread::RecordTrack> recordTrack;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003137 sp<RecordHandle> recordHandle;
3138 sp<Client> client;
3139 wp<Client> wclient;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08003140 status_t lStatus;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003141 RecordThread *thread;
3142 size_t inFrameCount;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003143
3144 // check calling permissions
3145 if (!recordingAllowed()) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08003146 lStatus = PERMISSION_DENIED;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003147 goto Exit;
3148 }
3149
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003150 // add client to list
The Android Open Source Project22f8def2009-03-09 11:52:12 -07003151 { // scope for mLock
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003152 Mutex::Autolock _l(mLock);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003153 thread = checkRecordThread_l(input);
3154 if (thread == NULL) {
3155 lStatus = BAD_VALUE;
3156 goto Exit;
3157 }
3158
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003159 wclient = mClients.valueFor(pid);
3160 if (wclient != NULL) {
3161 client = wclient.promote();
3162 } else {
3163 client = new Client(this, pid);
3164 mClients.add(pid, client);
3165 }
The Android Open Source Project22f8def2009-03-09 11:52:12 -07003166
The Android Open Source Project22f8def2009-03-09 11:52:12 -07003167 // create new record track. The record track uses one track in mHardwareMixerThread by convention.
Eric Laurent9d91ad52009-07-17 12:17:14 -07003168 recordTrack = new RecordThread::RecordTrack(thread, client, sampleRate,
The Android Open Source Project22f8def2009-03-09 11:52:12 -07003169 format, channelCount, frameCount, flags);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003170 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08003171 if (recordTrack->getCblk() == NULL) {
Eric Laurent0f8ab672009-09-17 05:12:56 -07003172 // remove local strong reference to Client before deleting the RecordTrack so that the Client
3173 // destructor is called by the TrackBase destructor with mLock held
3174 client.clear();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08003175 recordTrack.clear();
3176 lStatus = NO_MEMORY;
3177 goto Exit;
3178 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003179
3180 // return to handle to client
3181 recordHandle = new RecordHandle(recordTrack);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08003182 lStatus = NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003183
3184Exit:
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08003185 if (status) {
3186 *status = lStatus;
3187 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003188 return recordHandle;
3189}
3190
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003191// ----------------------------------------------------------------------------
3192
Eric Laurent9d91ad52009-07-17 12:17:14 -07003193AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::RecordThread::RecordTrack>& recordTrack)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003194 : BnAudioRecord(),
3195 mRecordTrack(recordTrack)
3196{
3197}
3198
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08003199AudioFlinger::RecordHandle::~RecordHandle() {
3200 stop();
3201}
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003202
3203status_t AudioFlinger::RecordHandle::start() {
3204 LOGV("RecordHandle::start()");
3205 return mRecordTrack->start();
3206}
3207
3208void AudioFlinger::RecordHandle::stop() {
3209 LOGV("RecordHandle::stop()");
3210 mRecordTrack->stop();
3211}
3212
3213sp<IMemory> AudioFlinger::RecordHandle::getCblk() const {
3214 return mRecordTrack->getCblk();
3215}
3216
3217status_t AudioFlinger::RecordHandle::onTransact(
3218 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
3219{
3220 return BnAudioRecord::onTransact(code, data, reply, flags);
3221}
3222
3223// ----------------------------------------------------------------------------
3224
Eric Laurent09b4ba82009-11-19 09:00:56 -08003225AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, AudioStreamIn *input, uint32_t sampleRate, uint32_t channels, int id) :
3226 ThreadBase(audioFlinger, id),
Eric Laurent9d91ad52009-07-17 12:17:14 -07003227 mInput(input), mResampler(0), mRsmpOutBuffer(0), mRsmpInBuffer(0)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003228{
Eric Laurent9d91ad52009-07-17 12:17:14 -07003229 mReqChannelCount = AudioSystem::popCount(channels);
3230 mReqSampleRate = sampleRate;
3231 readInputParameters();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003232}
3233
Eric Laurent9d91ad52009-07-17 12:17:14 -07003234
3235AudioFlinger::RecordThread::~RecordThread()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003236{
Eric Laurent9d91ad52009-07-17 12:17:14 -07003237 delete[] mRsmpInBuffer;
3238 if (mResampler != 0) {
3239 delete mResampler;
3240 delete[] mRsmpOutBuffer;
3241 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003242}
3243
Eric Laurent9d91ad52009-07-17 12:17:14 -07003244void AudioFlinger::RecordThread::onFirstRef()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003245{
Eric Laurent9d91ad52009-07-17 12:17:14 -07003246 const size_t SIZE = 256;
3247 char buffer[SIZE];
3248
3249 snprintf(buffer, SIZE, "Record Thread %p", this);
3250
3251 run(buffer, PRIORITY_URGENT_AUDIO);
3252}
Eric Laurent09b4ba82009-11-19 09:00:56 -08003253
Eric Laurent9d91ad52009-07-17 12:17:14 -07003254bool AudioFlinger::RecordThread::threadLoop()
3255{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08003256 AudioBufferProvider::Buffer buffer;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003257 sp<RecordTrack> activeTrack;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003258
3259 // start recording
3260 while (!exitPending()) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08003261
Eric Laurent9d91ad52009-07-17 12:17:14 -07003262 processConfigEvents();
3263
3264 { // scope for mLock
3265 Mutex::Autolock _l(mLock);
3266 checkForNewParameters_l();
3267 if (mActiveTrack == 0 && mConfigEvents.isEmpty()) {
3268 if (!mStandby) {
3269 mInput->standby();
3270 mStandby = true;
3271 }
3272
3273 if (exitPending()) break;
3274
3275 LOGV("RecordThread: loop stopping");
3276 // go to sleep
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003277 mWaitWorkCV.wait(mLock);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003278 LOGV("RecordThread: loop starting");
3279 continue;
3280 }
3281 if (mActiveTrack != 0) {
3282 if (mActiveTrack->mState == TrackBase::PAUSING) {
Eric Laurent52910952009-12-05 05:20:01 -08003283 if (!mStandby) {
3284 mInput->standby();
3285 mStandby = true;
3286 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07003287 mActiveTrack.clear();
3288 mStartStopCond.broadcast();
3289 } else if (mActiveTrack->mState == TrackBase::RESUMING) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07003290 if (mReqChannelCount != mActiveTrack->channelCount()) {
3291 mActiveTrack.clear();
Eric Laurent52910952009-12-05 05:20:01 -08003292 mStartStopCond.broadcast();
3293 } else if (mBytesRead != 0) {
3294 // record start succeeds only if first read from audio input
3295 // succeeds
3296 if (mBytesRead > 0) {
3297 mActiveTrack->mState = TrackBase::ACTIVE;
3298 } else {
3299 mActiveTrack.clear();
3300 }
3301 mStartStopCond.broadcast();
Eric Laurent9d91ad52009-07-17 12:17:14 -07003302 }
Eric Laurent52910952009-12-05 05:20:01 -08003303 mStandby = false;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003304 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07003305 }
3306 }
3307
3308 if (mActiveTrack != 0) {
Eric Laurent52910952009-12-05 05:20:01 -08003309 if (mActiveTrack->mState != TrackBase::ACTIVE &&
3310 mActiveTrack->mState != TrackBase::RESUMING) {
Eric Laurent09b4ba82009-11-19 09:00:56 -08003311 usleep(5000);
3312 continue;
3313 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07003314 buffer.frameCount = mFrameCount;
3315 if (LIKELY(mActiveTrack->getNextBuffer(&buffer) == NO_ERROR)) {
3316 size_t framesOut = buffer.frameCount;
3317 if (mResampler == 0) {
3318 // no resampling
3319 while (framesOut) {
3320 size_t framesIn = mFrameCount - mRsmpInIndex;
3321 if (framesIn) {
3322 int8_t *src = (int8_t *)mRsmpInBuffer + mRsmpInIndex * mFrameSize;
3323 int8_t *dst = buffer.i8 + (buffer.frameCount - framesOut) * mActiveTrack->mCblk->frameSize;
3324 if (framesIn > framesOut)
3325 framesIn = framesOut;
3326 mRsmpInIndex += framesIn;
3327 framesOut -= framesIn;
Eric Laurente1512162010-05-14 05:45:46 -07003328 if ((int)mChannelCount == mReqChannelCount ||
Eric Laurent9d91ad52009-07-17 12:17:14 -07003329 mFormat != AudioSystem::PCM_16_BIT) {
3330 memcpy(dst, src, framesIn * mFrameSize);
3331 } else {
3332 int16_t *src16 = (int16_t *)src;
3333 int16_t *dst16 = (int16_t *)dst;
3334 if (mChannelCount == 1) {
3335 while (framesIn--) {
3336 *dst16++ = *src16;
3337 *dst16++ = *src16++;
3338 }
3339 } else {
3340 while (framesIn--) {
3341 *dst16++ = (int16_t)(((int32_t)*src16 + (int32_t)*(src16 + 1)) >> 1);
3342 src16 += 2;
3343 }
3344 }
3345 }
3346 }
3347 if (framesOut && mFrameCount == mRsmpInIndex) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07003348 if (framesOut == mFrameCount &&
Eric Laurente1512162010-05-14 05:45:46 -07003349 ((int)mChannelCount == mReqChannelCount || mFormat != AudioSystem::PCM_16_BIT)) {
Eric Laurent52910952009-12-05 05:20:01 -08003350 mBytesRead = mInput->read(buffer.raw, mInputBytes);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003351 framesOut = 0;
3352 } else {
Eric Laurent52910952009-12-05 05:20:01 -08003353 mBytesRead = mInput->read(mRsmpInBuffer, mInputBytes);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003354 mRsmpInIndex = 0;
3355 }
Eric Laurent52910952009-12-05 05:20:01 -08003356 if (mBytesRead < 0) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07003357 LOGE("Error reading audio input");
Eric Laurent52910952009-12-05 05:20:01 -08003358 if (mActiveTrack->mState == TrackBase::ACTIVE) {
Eric Laurent4f1fcc22010-03-02 18:38:06 -08003359 // Force input into standby so that it tries to
3360 // recover at next read attempt
3361 mInput->standby();
3362 usleep(5000);
Eric Laurent52910952009-12-05 05:20:01 -08003363 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07003364 mRsmpInIndex = mFrameCount;
3365 framesOut = 0;
3366 buffer.frameCount = 0;
3367 }
3368 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08003369 }
3370 } else {
Eric Laurent9d91ad52009-07-17 12:17:14 -07003371 // resampling
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003372
Eric Laurent9d91ad52009-07-17 12:17:14 -07003373 memset(mRsmpOutBuffer, 0, framesOut * 2 * sizeof(int32_t));
3374 // alter output frame count as if we were expecting stereo samples
3375 if (mChannelCount == 1 && mReqChannelCount == 1) {
3376 framesOut >>= 1;
3377 }
3378 mResampler->resample(mRsmpOutBuffer, framesOut, this);
3379 // ditherAndClamp() works as long as all buffers returned by mActiveTrack->getNextBuffer()
3380 // are 32 bit aligned which should be always true.
3381 if (mChannelCount == 2 && mReqChannelCount == 1) {
3382 AudioMixer::ditherAndClamp(mRsmpOutBuffer, mRsmpOutBuffer, framesOut);
3383 // the resampler always outputs stereo samples: do post stereo to mono conversion
3384 int16_t *src = (int16_t *)mRsmpOutBuffer;
3385 int16_t *dst = buffer.i16;
3386 while (framesOut--) {
3387 *dst++ = (int16_t)(((int32_t)*src + (int32_t)*(src + 1)) >> 1);
3388 src += 2;
3389 }
3390 } else {
3391 AudioMixer::ditherAndClamp((int32_t *)buffer.raw, mRsmpOutBuffer, framesOut);
3392 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003393
Eric Laurent9d91ad52009-07-17 12:17:14 -07003394 }
3395 mActiveTrack->releaseBuffer(&buffer);
3396 mActiveTrack->overflow();
3397 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003398 // client isn't retrieving buffers fast enough
3399 else {
Eric Laurent9d91ad52009-07-17 12:17:14 -07003400 if (!mActiveTrack->setOverflow())
3401 LOGW("RecordThread: buffer overflow");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08003402 // Release the processor for a while before asking for a new buffer.
3403 // This will give the application more chance to read from the buffer and
3404 // clear the overflow.
3405 usleep(5000);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003406 }
3407 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08003408 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003409
Eric Laurent9d91ad52009-07-17 12:17:14 -07003410 if (!mStandby) {
3411 mInput->standby();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08003412 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07003413 mActiveTrack.clear();
3414
Eric Laurent09b4ba82009-11-19 09:00:56 -08003415 mStartStopCond.broadcast();
3416
Eric Laurent9d91ad52009-07-17 12:17:14 -07003417 LOGV("RecordThread %p exiting", this);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003418 return false;
3419}
3420
Eric Laurent9d91ad52009-07-17 12:17:14 -07003421status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003422{
Eric Laurent9d91ad52009-07-17 12:17:14 -07003423 LOGV("RecordThread::start");
Eric Laurent09b4ba82009-11-19 09:00:56 -08003424 sp <ThreadBase> strongMe = this;
3425 status_t status = NO_ERROR;
3426 {
3427 AutoMutex lock(&mLock);
3428 if (mActiveTrack != 0) {
3429 if (recordTrack != mActiveTrack.get()) {
3430 status = -EBUSY;
3431 } else if (mActiveTrack->mState == TrackBase::PAUSING) {
Eric Laurent52910952009-12-05 05:20:01 -08003432 mActiveTrack->mState = TrackBase::ACTIVE;
Eric Laurent09b4ba82009-11-19 09:00:56 -08003433 }
3434 return status;
3435 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003436
Eric Laurent09b4ba82009-11-19 09:00:56 -08003437 recordTrack->mState = TrackBase::IDLE;
3438 mActiveTrack = recordTrack;
3439 mLock.unlock();
3440 status_t status = AudioSystem::startInput(mId);
3441 mLock.lock();
3442 if (status != NO_ERROR) {
3443 mActiveTrack.clear();
3444 return status;
3445 }
3446 mActiveTrack->mState = TrackBase::RESUMING;
Eric Laurent52910952009-12-05 05:20:01 -08003447 mRsmpInIndex = mFrameCount;
3448 mBytesRead = 0;
Eric Laurent09b4ba82009-11-19 09:00:56 -08003449 // signal thread to start
3450 LOGV("Signal record thread");
3451 mWaitWorkCV.signal();
3452 // do not wait for mStartStopCond if exiting
3453 if (mExiting) {
3454 mActiveTrack.clear();
3455 status = INVALID_OPERATION;
3456 goto startError;
3457 }
3458 mStartStopCond.wait(mLock);
3459 if (mActiveTrack == 0) {
3460 LOGV("Record failed to start");
3461 status = BAD_VALUE;
3462 goto startError;
3463 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07003464 LOGV("Record started OK");
Eric Laurent09b4ba82009-11-19 09:00:56 -08003465 return status;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003466 }
Eric Laurent09b4ba82009-11-19 09:00:56 -08003467startError:
3468 AudioSystem::stopInput(mId);
3469 return status;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003470}
3471
Eric Laurent9d91ad52009-07-17 12:17:14 -07003472void AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) {
3473 LOGV("RecordThread::stop");
Eric Laurent09b4ba82009-11-19 09:00:56 -08003474 sp <ThreadBase> strongMe = this;
3475 {
3476 AutoMutex lock(&mLock);
3477 if (mActiveTrack != 0 && recordTrack == mActiveTrack.get()) {
3478 mActiveTrack->mState = TrackBase::PAUSING;
3479 // do not wait for mStartStopCond if exiting
3480 if (mExiting) {
3481 return;
3482 }
3483 mStartStopCond.wait(mLock);
3484 // if we have been restarted, recordTrack == mActiveTrack.get() here
3485 if (mActiveTrack == 0 || recordTrack != mActiveTrack.get()) {
3486 mLock.unlock();
3487 AudioSystem::stopInput(mId);
3488 mLock.lock();
Eric Laurent52910952009-12-05 05:20:01 -08003489 LOGV("Record stopped OK");
Eric Laurent09b4ba82009-11-19 09:00:56 -08003490 }
3491 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003492 }
3493}
3494
Eric Laurent9d91ad52009-07-17 12:17:14 -07003495status_t AudioFlinger::RecordThread::dump(int fd, const Vector<String16>& args)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08003496{
3497 const size_t SIZE = 256;
3498 char buffer[SIZE];
3499 String8 result;
3500 pid_t pid = 0;
3501
Eric Laurentee47d432009-11-07 00:01:32 -08003502 snprintf(buffer, SIZE, "\nInput thread %p internals\n", this);
3503 result.append(buffer);
3504
3505 if (mActiveTrack != 0) {
3506 result.append("Active Track:\n");
3507 result.append(" Clien Fmt Chn Buf S SRate Serv User\n");
3508 mActiveTrack->dump(buffer, SIZE);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08003509 result.append(buffer);
Eric Laurentee47d432009-11-07 00:01:32 -08003510
3511 snprintf(buffer, SIZE, "In index: %d\n", mRsmpInIndex);
3512 result.append(buffer);
3513 snprintf(buffer, SIZE, "In size: %d\n", mInputBytes);
3514 result.append(buffer);
3515 snprintf(buffer, SIZE, "Resampling: %d\n", (mResampler != 0));
3516 result.append(buffer);
3517 snprintf(buffer, SIZE, "Out channel count: %d\n", mReqChannelCount);
3518 result.append(buffer);
3519 snprintf(buffer, SIZE, "Out sample rate: %d\n", mReqSampleRate);
3520 result.append(buffer);
3521
3522
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08003523 } else {
3524 result.append("No record client\n");
3525 }
3526 write(fd, result.string(), result.size());
Eric Laurentee47d432009-11-07 00:01:32 -08003527
3528 dumpBase(fd, args);
3529
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08003530 return NO_ERROR;
3531}
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003532
Eric Laurent9d91ad52009-07-17 12:17:14 -07003533status_t AudioFlinger::RecordThread::getNextBuffer(AudioBufferProvider::Buffer* buffer)
3534{
3535 size_t framesReq = buffer->frameCount;
3536 size_t framesReady = mFrameCount - mRsmpInIndex;
3537 int channelCount;
3538
3539 if (framesReady == 0) {
Eric Laurent52910952009-12-05 05:20:01 -08003540 mBytesRead = mInput->read(mRsmpInBuffer, mInputBytes);
3541 if (mBytesRead < 0) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07003542 LOGE("RecordThread::getNextBuffer() Error reading audio input");
Eric Laurent52910952009-12-05 05:20:01 -08003543 if (mActiveTrack->mState == TrackBase::ACTIVE) {
Eric Laurent4f1fcc22010-03-02 18:38:06 -08003544 // Force input into standby so that it tries to
3545 // recover at next read attempt
3546 mInput->standby();
3547 usleep(5000);
Eric Laurent52910952009-12-05 05:20:01 -08003548 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07003549 buffer->raw = 0;
3550 buffer->frameCount = 0;
3551 return NOT_ENOUGH_DATA;
3552 }
3553 mRsmpInIndex = 0;
3554 framesReady = mFrameCount;
3555 }
3556
3557 if (framesReq > framesReady) {
3558 framesReq = framesReady;
3559 }
3560
3561 if (mChannelCount == 1 && mReqChannelCount == 2) {
3562 channelCount = 1;
3563 } else {
3564 channelCount = 2;
3565 }
3566 buffer->raw = mRsmpInBuffer + mRsmpInIndex * channelCount;
3567 buffer->frameCount = framesReq;
3568 return NO_ERROR;
3569}
3570
3571void AudioFlinger::RecordThread::releaseBuffer(AudioBufferProvider::Buffer* buffer)
3572{
3573 mRsmpInIndex += buffer->frameCount;
3574 buffer->frameCount = 0;
3575}
3576
3577bool AudioFlinger::RecordThread::checkForNewParameters_l()
3578{
3579 bool reconfig = false;
3580
Eric Laurent3464c012009-08-04 09:45:33 -07003581 while (!mNewParameters.isEmpty()) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07003582 status_t status = NO_ERROR;
Eric Laurent3464c012009-08-04 09:45:33 -07003583 String8 keyValuePair = mNewParameters[0];
3584 AudioParameter param = AudioParameter(keyValuePair);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003585 int value;
3586 int reqFormat = mFormat;
3587 int reqSamplingRate = mReqSampleRate;
3588 int reqChannelCount = mReqChannelCount;
Eric Laurent3464c012009-08-04 09:45:33 -07003589
Eric Laurent9d91ad52009-07-17 12:17:14 -07003590 if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
3591 reqSamplingRate = value;
3592 reconfig = true;
3593 }
3594 if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
3595 reqFormat = value;
3596 reconfig = true;
3597 }
3598 if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
3599 reqChannelCount = AudioSystem::popCount(value);
3600 reconfig = true;
3601 }
3602 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
3603 // do not accept frame count changes if tracks are open as the track buffer
3604 // size depends on frame count and correct behavior would not be garantied
3605 // if frame count is changed after track creation
3606 if (mActiveTrack != 0) {
3607 status = INVALID_OPERATION;
3608 } else {
3609 reconfig = true;
3610 }
3611 }
3612 if (status == NO_ERROR) {
Eric Laurent3464c012009-08-04 09:45:33 -07003613 status = mInput->setParameters(keyValuePair);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003614 if (status == INVALID_OPERATION) {
3615 mInput->standby();
Eric Laurent3464c012009-08-04 09:45:33 -07003616 status = mInput->setParameters(keyValuePair);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003617 }
3618 if (reconfig) {
3619 if (status == BAD_VALUE &&
3620 reqFormat == mInput->format() && reqFormat == AudioSystem::PCM_16_BIT &&
3621 ((int)mInput->sampleRate() <= 2 * reqSamplingRate) &&
3622 (AudioSystem::popCount(mInput->channels()) < 3) && (reqChannelCount < 3)) {
3623 status = NO_ERROR;
3624 }
3625 if (status == NO_ERROR) {
3626 readInputParameters();
Eric Laurent3464c012009-08-04 09:45:33 -07003627 sendConfigEvent_l(AudioSystem::INPUT_CONFIG_CHANGED);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003628 }
3629 }
3630 }
Eric Laurentee47d432009-11-07 00:01:32 -08003631
3632 mNewParameters.removeAt(0);
3633
Eric Laurent9d91ad52009-07-17 12:17:14 -07003634 mParamStatus = status;
3635 mParamCond.signal();
Eric Laurent3464c012009-08-04 09:45:33 -07003636 mWaitWorkCV.wait(mLock);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003637 }
3638 return reconfig;
3639}
3640
3641String8 AudioFlinger::RecordThread::getParameters(const String8& keys)
3642{
3643 return mInput->getParameters(keys);
3644}
3645
Eric Laurent4edfe752010-05-14 03:26:45 -07003646void AudioFlinger::RecordThread::audioConfigChanged_l(int event, int param) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07003647 AudioSystem::OutputDescriptor desc;
3648 void *param2 = 0;
3649
3650 switch (event) {
3651 case AudioSystem::INPUT_OPENED:
3652 case AudioSystem::INPUT_CONFIG_CHANGED:
Eric Laurente1512162010-05-14 05:45:46 -07003653 desc.channels = mChannels;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003654 desc.samplingRate = mSampleRate;
3655 desc.format = mFormat;
3656 desc.frameCount = mFrameCount;
3657 desc.latency = 0;
3658 param2 = &desc;
3659 break;
3660
3661 case AudioSystem::INPUT_CLOSED:
3662 default:
3663 break;
3664 }
Eric Laurent09b4ba82009-11-19 09:00:56 -08003665 mAudioFlinger->audioConfigChanged_l(event, mId, param2);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003666}
3667
3668void AudioFlinger::RecordThread::readInputParameters()
3669{
3670 if (mRsmpInBuffer) delete mRsmpInBuffer;
3671 if (mRsmpOutBuffer) delete mRsmpOutBuffer;
3672 if (mResampler) delete mResampler;
3673 mResampler = 0;
3674
3675 mSampleRate = mInput->sampleRate();
Eric Laurente1512162010-05-14 05:45:46 -07003676 mChannels = mInput->channels();
3677 mChannelCount = (uint16_t)AudioSystem::popCount(mChannels);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003678 mFormat = mInput->format();
Eric Laurente1512162010-05-14 05:45:46 -07003679 mFrameSize = (uint16_t)mInput->frameSize();
Eric Laurent9d91ad52009-07-17 12:17:14 -07003680 mInputBytes = mInput->bufferSize();
3681 mFrameCount = mInputBytes / mFrameSize;
3682 mRsmpInBuffer = new int16_t[mFrameCount * mChannelCount];
3683
3684 if (mSampleRate != mReqSampleRate && mChannelCount < 3 && mReqChannelCount < 3)
3685 {
3686 int channelCount;
3687 // optmization: if mono to mono, use the resampler in stereo to stereo mode to avoid
3688 // stereo to mono post process as the resampler always outputs stereo.
3689 if (mChannelCount == 1 && mReqChannelCount == 2) {
3690 channelCount = 1;
3691 } else {
3692 channelCount = 2;
3693 }
3694 mResampler = AudioResampler::create(16, channelCount, mReqSampleRate);
3695 mResampler->setSampleRate(mSampleRate);
3696 mResampler->setVolume(AudioMixer::UNITY_GAIN, AudioMixer::UNITY_GAIN);
3697 mRsmpOutBuffer = new int32_t[mFrameCount * 2];
3698
3699 // optmization: if mono to mono, alter input frame count as if we were inputing stereo samples
3700 if (mChannelCount == 1 && mReqChannelCount == 1) {
3701 mFrameCount >>= 1;
3702 }
3703
3704 }
3705 mRsmpInIndex = mFrameCount;
3706}
3707
Eric Laurent134ccbd2010-02-26 02:47:27 -08003708unsigned int AudioFlinger::RecordThread::getInputFramesLost()
3709{
3710 return mInput->getInputFramesLost();
3711}
3712
Eric Laurent9d91ad52009-07-17 12:17:14 -07003713// ----------------------------------------------------------------------------
3714
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003715int AudioFlinger::openOutput(uint32_t *pDevices,
Eric Laurent9d91ad52009-07-17 12:17:14 -07003716 uint32_t *pSamplingRate,
3717 uint32_t *pFormat,
3718 uint32_t *pChannels,
3719 uint32_t *pLatencyMs,
3720 uint32_t flags)
3721{
3722 status_t status;
3723 PlaybackThread *thread = NULL;
3724 mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
3725 uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
3726 uint32_t format = pFormat ? *pFormat : 0;
3727 uint32_t channels = pChannels ? *pChannels : 0;
3728 uint32_t latency = pLatencyMs ? *pLatencyMs : 0;
3729
3730 LOGV("openOutput(), Device %x, SamplingRate %d, Format %d, Channels %x, flags %x",
3731 pDevices ? *pDevices : 0,
3732 samplingRate,
3733 format,
3734 channels,
3735 flags);
3736
3737 if (pDevices == NULL || *pDevices == 0) {
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003738 return 0;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003739 }
3740 Mutex::Autolock _l(mLock);
3741
3742 AudioStreamOut *output = mAudioHardware->openOutputStream(*pDevices,
3743 (int *)&format,
3744 &channels,
3745 &samplingRate,
3746 &status);
3747 LOGV("openOutput() openOutputStream returned output %p, SamplingRate %d, Format %d, Channels %x, status %d",
3748 output,
3749 samplingRate,
3750 format,
3751 channels,
3752 status);
3753
3754 mHardwareStatus = AUDIO_HW_IDLE;
3755 if (output != 0) {
3756 if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) ||
3757 (format != AudioSystem::PCM_16_BIT) ||
3758 (channels != AudioSystem::CHANNEL_OUT_STEREO)) {
Eric Laurent09b4ba82009-11-19 09:00:56 -08003759 thread = new DirectOutputThread(this, output, ++mNextThreadId);
3760 LOGV("openOutput() created direct output: ID %d thread %p", mNextThreadId, thread);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003761 } else {
Eric Laurent09b4ba82009-11-19 09:00:56 -08003762 thread = new MixerThread(this, output, ++mNextThreadId);
3763 LOGV("openOutput() created mixer output: ID %d thread %p", mNextThreadId, thread);
Glenn Kastend5ea9692010-03-05 12:18:01 -08003764
3765#ifdef LVMX
3766 unsigned bitsPerSample =
3767 (format == AudioSystem::PCM_16_BIT) ? 16 :
3768 ((format == AudioSystem::PCM_8_BIT) ? 8 : 0);
3769 unsigned channelCount = (channels == AudioSystem::CHANNEL_OUT_STEREO) ? 2 : 1;
3770 int audioOutputType = LifeVibes::threadIdToAudioOutputType(thread->id());
3771
3772 LifeVibes::init_aot(audioOutputType, samplingRate, bitsPerSample, channelCount);
3773 LifeVibes::setDevice(audioOutputType, *pDevices);
3774#endif
3775
Eric Laurent9d91ad52009-07-17 12:17:14 -07003776 }
Eric Laurent09b4ba82009-11-19 09:00:56 -08003777 mPlaybackThreads.add(mNextThreadId, thread);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003778
3779 if (pSamplingRate) *pSamplingRate = samplingRate;
3780 if (pFormat) *pFormat = format;
3781 if (pChannels) *pChannels = channels;
3782 if (pLatencyMs) *pLatencyMs = thread->latency();
Eric Laurent52910952009-12-05 05:20:01 -08003783
Eric Laurent4edfe752010-05-14 03:26:45 -07003784 // notify client processes of the new output creation
3785 thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
Eric Laurent52910952009-12-05 05:20:01 -08003786 return mNextThreadId;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003787 }
3788
Eric Laurent52910952009-12-05 05:20:01 -08003789 return 0;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003790}
3791
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003792int AudioFlinger::openDuplicateOutput(int output1, int output2)
Eric Laurent9d91ad52009-07-17 12:17:14 -07003793{
3794 Mutex::Autolock _l(mLock);
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003795 MixerThread *thread1 = checkMixerThread_l(output1);
3796 MixerThread *thread2 = checkMixerThread_l(output2);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003797
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003798 if (thread1 == NULL || thread2 == NULL) {
3799 LOGW("openDuplicateOutput() wrong output mixer type for output %d or %d", output1, output2);
3800 return 0;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003801 }
3802
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003803
Eric Laurent09b4ba82009-11-19 09:00:56 -08003804 DuplicatingThread *thread = new DuplicatingThread(this, thread1, ++mNextThreadId);
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003805 thread->addOutputTrack(thread2);
Eric Laurent09b4ba82009-11-19 09:00:56 -08003806 mPlaybackThreads.add(mNextThreadId, thread);
Eric Laurent4edfe752010-05-14 03:26:45 -07003807 // notify client processes of the new output creation
3808 thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003809 return mNextThreadId;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003810}
3811
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003812status_t AudioFlinger::closeOutput(int output)
Eric Laurent9d91ad52009-07-17 12:17:14 -07003813{
Eric Laurentdae20d92009-08-04 08:37:05 -07003814 // keep strong reference on the playback thread so that
3815 // it is not destroyed while exit() is executed
3816 sp <PlaybackThread> thread;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003817 {
3818 Mutex::Autolock _l(mLock);
3819 thread = checkPlaybackThread_l(output);
3820 if (thread == NULL) {
3821 return BAD_VALUE;
3822 }
3823
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003824 LOGV("closeOutput() %d", output);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003825
3826 if (thread->type() == PlaybackThread::MIXER) {
3827 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003828 if (mPlaybackThreads.valueAt(i)->type() == PlaybackThread::DUPLICATING) {
3829 DuplicatingThread *dupThread = (DuplicatingThread *)mPlaybackThreads.valueAt(i).get();
Eric Laurentdae20d92009-08-04 08:37:05 -07003830 dupThread->removeOutputTrack((MixerThread *)thread.get());
Eric Laurent9d91ad52009-07-17 12:17:14 -07003831 }
3832 }
3833 }
Eric Laurentb3687ae2009-09-15 07:10:12 -07003834 void *param2 = 0;
Eric Laurent09b4ba82009-11-19 09:00:56 -08003835 audioConfigChanged_l(AudioSystem::OUTPUT_CLOSED, output, param2);
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003836 mPlaybackThreads.removeItem(output);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003837 }
3838 thread->exit();
3839
Eric Laurentdae20d92009-08-04 08:37:05 -07003840 if (thread->type() != PlaybackThread::DUPLICATING) {
3841 mAudioHardware->closeOutputStream(thread->getOutput());
3842 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07003843 return NO_ERROR;
3844}
3845
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003846status_t AudioFlinger::suspendOutput(int output)
Eric Laurent9d91ad52009-07-17 12:17:14 -07003847{
3848 Mutex::Autolock _l(mLock);
3849 PlaybackThread *thread = checkPlaybackThread_l(output);
3850
3851 if (thread == NULL) {
3852 return BAD_VALUE;
3853 }
3854
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003855 LOGV("suspendOutput() %d", output);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003856 thread->suspend();
3857
3858 return NO_ERROR;
3859}
3860
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003861status_t AudioFlinger::restoreOutput(int output)
Eric Laurent9d91ad52009-07-17 12:17:14 -07003862{
3863 Mutex::Autolock _l(mLock);
3864 PlaybackThread *thread = checkPlaybackThread_l(output);
3865
3866 if (thread == NULL) {
3867 return BAD_VALUE;
3868 }
3869
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003870 LOGV("restoreOutput() %d", output);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003871
3872 thread->restore();
3873
3874 return NO_ERROR;
3875}
3876
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003877int AudioFlinger::openInput(uint32_t *pDevices,
Eric Laurent9d91ad52009-07-17 12:17:14 -07003878 uint32_t *pSamplingRate,
3879 uint32_t *pFormat,
3880 uint32_t *pChannels,
3881 uint32_t acoustics)
3882{
3883 status_t status;
3884 RecordThread *thread = NULL;
3885 uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
3886 uint32_t format = pFormat ? *pFormat : 0;
3887 uint32_t channels = pChannels ? *pChannels : 0;
3888 uint32_t reqSamplingRate = samplingRate;
3889 uint32_t reqFormat = format;
3890 uint32_t reqChannels = channels;
3891
3892 if (pDevices == NULL || *pDevices == 0) {
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003893 return 0;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003894 }
3895 Mutex::Autolock _l(mLock);
3896
3897 AudioStreamIn *input = mAudioHardware->openInputStream(*pDevices,
3898 (int *)&format,
3899 &channels,
3900 &samplingRate,
3901 &status,
3902 (AudioSystem::audio_in_acoustics)acoustics);
3903 LOGV("openInput() openInputStream returned input %p, SamplingRate %d, Format %d, Channels %x, acoustics %x, status %d",
3904 input,
3905 samplingRate,
3906 format,
3907 channels,
3908 acoustics,
3909 status);
3910
3911 // If the input could not be opened with the requested parameters and we can handle the conversion internally,
3912 // try to open again with the proposed parameters. The AudioFlinger can resample the input and do mono to stereo
3913 // or stereo to mono conversions on 16 bit PCM inputs.
3914 if (input == 0 && status == BAD_VALUE &&
3915 reqFormat == format && format == AudioSystem::PCM_16_BIT &&
3916 (samplingRate <= 2 * reqSamplingRate) &&
3917 (AudioSystem::popCount(channels) < 3) && (AudioSystem::popCount(reqChannels) < 3)) {
3918 LOGV("openInput() reopening with proposed sampling rate and channels");
3919 input = mAudioHardware->openInputStream(*pDevices,
3920 (int *)&format,
3921 &channels,
3922 &samplingRate,
3923 &status,
3924 (AudioSystem::audio_in_acoustics)acoustics);
3925 }
3926
3927 if (input != 0) {
3928 // Start record thread
Eric Laurent09b4ba82009-11-19 09:00:56 -08003929 thread = new RecordThread(this, input, reqSamplingRate, reqChannels, ++mNextThreadId);
3930 mRecordThreads.add(mNextThreadId, thread);
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003931 LOGV("openInput() created record thread: ID %d thread %p", mNextThreadId, thread);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003932 if (pSamplingRate) *pSamplingRate = reqSamplingRate;
3933 if (pFormat) *pFormat = format;
3934 if (pChannels) *pChannels = reqChannels;
3935
3936 input->standby();
Eric Laurent52910952009-12-05 05:20:01 -08003937
Eric Laurent4edfe752010-05-14 03:26:45 -07003938 // notify client processes of the new input creation
3939 thread->audioConfigChanged_l(AudioSystem::INPUT_OPENED);
Eric Laurent52910952009-12-05 05:20:01 -08003940 return mNextThreadId;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003941 }
3942
Eric Laurent52910952009-12-05 05:20:01 -08003943 return 0;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003944}
3945
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003946status_t AudioFlinger::closeInput(int input)
Eric Laurent9d91ad52009-07-17 12:17:14 -07003947{
Eric Laurentdae20d92009-08-04 08:37:05 -07003948 // keep strong reference on the record thread so that
3949 // it is not destroyed while exit() is executed
3950 sp <RecordThread> thread;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003951 {
3952 Mutex::Autolock _l(mLock);
3953 thread = checkRecordThread_l(input);
3954 if (thread == NULL) {
3955 return BAD_VALUE;
3956 }
3957
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003958 LOGV("closeInput() %d", input);
Eric Laurentb3687ae2009-09-15 07:10:12 -07003959 void *param2 = 0;
Eric Laurent09b4ba82009-11-19 09:00:56 -08003960 audioConfigChanged_l(AudioSystem::INPUT_CLOSED, input, param2);
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003961 mRecordThreads.removeItem(input);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003962 }
3963 thread->exit();
3964
Eric Laurentdae20d92009-08-04 08:37:05 -07003965 mAudioHardware->closeInputStream(thread->getInput());
3966
Eric Laurent9d91ad52009-07-17 12:17:14 -07003967 return NO_ERROR;
3968}
3969
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003970status_t AudioFlinger::setStreamOutput(uint32_t stream, int output)
Eric Laurent9d91ad52009-07-17 12:17:14 -07003971{
3972 Mutex::Autolock _l(mLock);
3973 MixerThread *dstThread = checkMixerThread_l(output);
3974 if (dstThread == NULL) {
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003975 LOGW("setStreamOutput() bad output id %d", output);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003976 return BAD_VALUE;
3977 }
3978
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003979 LOGV("setStreamOutput() stream %d to output %d", stream, output);
Eric Laurent4edfe752010-05-14 03:26:45 -07003980 audioConfigChanged_l(AudioSystem::STREAM_CONFIG_CHANGED, output, &stream);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003981
3982 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003983 PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
Eric Laurent9d91ad52009-07-17 12:17:14 -07003984 if (thread != dstThread &&
3985 thread->type() != PlaybackThread::DIRECT) {
3986 MixerThread *srcThread = (MixerThread *)thread;
Eric Laurent4edfe752010-05-14 03:26:45 -07003987 srcThread->invalidateTracks(stream);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003988 }
3989 }
Eric Laurent06437712009-09-01 05:56:26 -07003990
Eric Laurent9d91ad52009-07-17 12:17:14 -07003991 return NO_ERROR;
3992}
3993
3994// checkPlaybackThread_l() must be called with AudioFlinger::mLock held
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003995AudioFlinger::PlaybackThread *AudioFlinger::checkPlaybackThread_l(int output) const
Eric Laurent9d91ad52009-07-17 12:17:14 -07003996{
3997 PlaybackThread *thread = NULL;
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003998 if (mPlaybackThreads.indexOfKey(output) >= 0) {
3999 thread = (PlaybackThread *)mPlaybackThreads.valueFor(output).get();
Eric Laurent9d91ad52009-07-17 12:17:14 -07004000 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07004001 return thread;
4002}
4003
4004// checkMixerThread_l() must be called with AudioFlinger::mLock held
Eric Laurente0e9ecc2009-07-28 08:44:33 -07004005AudioFlinger::MixerThread *AudioFlinger::checkMixerThread_l(int output) const
Eric Laurent9d91ad52009-07-17 12:17:14 -07004006{
4007 PlaybackThread *thread = checkPlaybackThread_l(output);
4008 if (thread != NULL) {
4009 if (thread->type() == PlaybackThread::DIRECT) {
4010 thread = NULL;
4011 }
4012 }
4013 return (MixerThread *)thread;
4014}
4015
4016// checkRecordThread_l() must be called with AudioFlinger::mLock held
Eric Laurente0e9ecc2009-07-28 08:44:33 -07004017AudioFlinger::RecordThread *AudioFlinger::checkRecordThread_l(int input) const
Eric Laurent9d91ad52009-07-17 12:17:14 -07004018{
4019 RecordThread *thread = NULL;
Eric Laurente0e9ecc2009-07-28 08:44:33 -07004020 if (mRecordThreads.indexOfKey(input) >= 0) {
4021 thread = (RecordThread *)mRecordThreads.valueFor(input).get();
Eric Laurent9d91ad52009-07-17 12:17:14 -07004022 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07004023 return thread;
4024}
4025
4026// ----------------------------------------------------------------------------
4027
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07004028status_t AudioFlinger::onTransact(
4029 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
4030{
4031 return BnAudioFlinger::onTransact(code, data, reply, flags);
4032}
4033
4034// ----------------------------------------------------------------------------
Eric Laurent9d91ad52009-07-17 12:17:14 -07004035
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07004036void AudioFlinger::instantiate() {
4037 defaultServiceManager()->addService(
4038 String16("media.audio_flinger"), new AudioFlinger());
4039}
4040
4041}; // namespace android