blob: ba8b3222933c103d7fc6859d7e896547bfa553c9 [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
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080050// ----------------------------------------------------------------------------
51// the sim build doesn't have gettid
52
53#ifndef HAVE_GETTID
54# define gettid getpid
55#endif
56
57// ----------------------------------------------------------------------------
58
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070059namespace android {
60
The Android Open Source Project4f68be12009-03-18 17:39:46 -070061static const char* kDeadlockedString = "AudioFlinger may be deadlocked\n";
62static const char* kHardwareLockedString = "Hardware lock is taken\n";
63
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -080064//static const nsecs_t kStandbyTimeInNsecs = seconds(3);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070065static const float MAX_GAIN = 4096.0f;
66
67// retry counts for buffer fill timeout
68// 50 * ~20msecs = 1 second
69static const int8_t kMaxTrackRetries = 50;
70static const int8_t kMaxTrackStartupRetries = 50;
71
The Android Open Source Project22f8def2009-03-09 11:52:12 -070072static const int kDumpLockRetries = 50;
73static const int kDumpLockSleep = 20000;
74
Dave Sparks8a95a452009-09-30 03:09:03 -070075static const nsecs_t kWarningThrottle = seconds(5);
76
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080077
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070078#define AUDIOFLINGER_SECURITY_ENABLED 1
79
80// ----------------------------------------------------------------------------
81
82static bool recordingAllowed() {
83#ifndef HAVE_ANDROID_OS
84 return true;
85#endif
86#if AUDIOFLINGER_SECURITY_ENABLED
87 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
88 bool ok = checkCallingPermission(String16("android.permission.RECORD_AUDIO"));
89 if (!ok) LOGE("Request requires android.permission.RECORD_AUDIO");
90 return ok;
91#else
92 if (!checkCallingPermission(String16("android.permission.RECORD_AUDIO")))
93 LOGW("WARNING: Need to add android.permission.RECORD_AUDIO to manifest");
94 return true;
95#endif
96}
97
98static bool settingsAllowed() {
99#ifndef HAVE_ANDROID_OS
100 return true;
101#endif
102#if AUDIOFLINGER_SECURITY_ENABLED
103 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
104 bool ok = checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS"));
105 if (!ok) LOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS");
106 return ok;
107#else
108 if (!checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS")))
109 LOGW("WARNING: Need to add android.permission.MODIFY_AUDIO_SETTINGS to manifest");
110 return true;
111#endif
112}
113
114// ----------------------------------------------------------------------------
115
116AudioFlinger::AudioFlinger()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800117 : BnAudioFlinger(),
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700118 mAudioHardware(0), mMasterVolume(1.0f), mMasterMute(false), mNextThreadId(0)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700119{
120 mHardwareStatus = AUDIO_HW_IDLE;
Eric Laurent9d91ad52009-07-17 12:17:14 -0700121
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700122 mAudioHardware = AudioHardwareInterface::create();
Eric Laurent9d91ad52009-07-17 12:17:14 -0700123
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700124 mHardwareStatus = AUDIO_HW_INIT;
125 if (mAudioHardware->initCheck() == NO_ERROR) {
126 // open 16-bit output stream for s/w mixer
Eric Laurent9d91ad52009-07-17 12:17:14 -0700127
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800128 setMode(AudioSystem::MODE_NORMAL);
129
130 setMasterVolume(1.0f);
131 setMasterMute(false);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700132 } else {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700133 LOGE("Couldn't even initialize the stubbed audio hardware!");
134 }
135}
136
137AudioFlinger::~AudioFlinger()
138{
Eric Laurentc80b1a02009-08-28 10:39:03 -0700139 while (!mRecordThreads.isEmpty()) {
140 // closeInput() will remove first entry from mRecordThreads
141 closeInput(mRecordThreads.keyAt(0));
142 }
143 while (!mPlaybackThreads.isEmpty()) {
144 // closeOutput() will remove first entry from mPlaybackThreads
145 closeOutput(mPlaybackThreads.keyAt(0));
146 }
147 if (mAudioHardware) {
148 delete mAudioHardware;
149 }
The Android Open Source Project27629322009-01-09 17:51:23 -0800150}
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800151
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700152
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700153
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700154status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args)
155{
156 const size_t SIZE = 256;
157 char buffer[SIZE];
158 String8 result;
159
160 result.append("Clients:\n");
161 for (size_t i = 0; i < mClients.size(); ++i) {
162 wp<Client> wClient = mClients.valueAt(i);
163 if (wClient != 0) {
164 sp<Client> client = wClient.promote();
165 if (client != 0) {
166 snprintf(buffer, SIZE, " pid: %d\n", client->pid());
167 result.append(buffer);
168 }
169 }
170 }
171 write(fd, result.string(), result.size());
172 return NO_ERROR;
173}
174
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700175
176status_t AudioFlinger::dumpInternals(int fd, const Vector<String16>& args)
177{
178 const size_t SIZE = 256;
179 char buffer[SIZE];
180 String8 result;
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700181 int hardwareStatus = mHardwareStatus;
Eric Laurent9d91ad52009-07-17 12:17:14 -0700182
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700183 snprintf(buffer, SIZE, "Hardware status: %d\n", hardwareStatus);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700184 result.append(buffer);
185 write(fd, result.string(), result.size());
186 return NO_ERROR;
187}
188
189status_t AudioFlinger::dumpPermissionDenial(int fd, const Vector<String16>& args)
190{
191 const size_t SIZE = 256;
192 char buffer[SIZE];
193 String8 result;
194 snprintf(buffer, SIZE, "Permission Denial: "
195 "can't dump AudioFlinger from pid=%d, uid=%d\n",
196 IPCThreadState::self()->getCallingPid(),
197 IPCThreadState::self()->getCallingUid());
198 result.append(buffer);
199 write(fd, result.string(), result.size());
200 return NO_ERROR;
201}
202
The Android Open Source Project4f68be12009-03-18 17:39:46 -0700203static bool tryLock(Mutex& mutex)
204{
205 bool locked = false;
206 for (int i = 0; i < kDumpLockRetries; ++i) {
207 if (mutex.tryLock() == NO_ERROR) {
208 locked = true;
209 break;
210 }
211 usleep(kDumpLockSleep);
212 }
213 return locked;
214}
215
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700216status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
217{
218 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
219 dumpPermissionDenial(fd, args);
220 } else {
The Android Open Source Project4f68be12009-03-18 17:39:46 -0700221 // get state of hardware lock
222 bool hardwareLocked = tryLock(mHardwareLock);
223 if (!hardwareLocked) {
224 String8 result(kHardwareLockedString);
225 write(fd, result.string(), result.size());
226 } else {
227 mHardwareLock.unlock();
228 }
229
230 bool locked = tryLock(mLock);
231
232 // failed to lock - AudioFlinger is probably deadlocked
233 if (!locked) {
234 String8 result(kDeadlockedString);
235 write(fd, result.string(), result.size());
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700236 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700237
238 dumpClients(fd, args);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700239 dumpInternals(fd, args);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800240
Eric Laurent9d91ad52009-07-17 12:17:14 -0700241 // dump playback threads
242 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700243 mPlaybackThreads.valueAt(i)->dump(fd, args);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700244 }
245
246 // dump record threads
Eric Laurentfd558a92009-07-23 13:35:01 -0700247 for (size_t i = 0; i < mRecordThreads.size(); i++) {
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700248 mRecordThreads.valueAt(i)->dump(fd, args);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700249 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800250
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700251 if (mAudioHardware) {
252 mAudioHardware->dumpState(fd, args);
253 }
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700254 if (locked) mLock.unlock();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700255 }
256 return NO_ERROR;
257}
258
Eric Laurent9d91ad52009-07-17 12:17:14 -0700259
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700260// IAudioFlinger interface
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800261
262
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700263sp<IAudioTrack> AudioFlinger::createTrack(
264 pid_t pid,
265 int streamType,
266 uint32_t sampleRate,
267 int format,
268 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800269 int frameCount,
270 uint32_t flags,
271 const sp<IMemory>& sharedBuffer,
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700272 int output,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800273 status_t *status)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700274{
Eric Laurent9d91ad52009-07-17 12:17:14 -0700275 sp<PlaybackThread::Track> track;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700276 sp<TrackHandle> trackHandle;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700277 sp<Client> client;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800278 wp<Client> wclient;
279 status_t lStatus;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700280
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800281 if (streamType >= AudioSystem::NUM_STREAM_TYPES) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800282 LOGE("invalid stream type");
283 lStatus = BAD_VALUE;
284 goto Exit;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700285 }
286
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800287 {
288 Mutex::Autolock _l(mLock);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700289 PlaybackThread *thread = checkPlaybackThread_l(output);
290 if (thread == NULL) {
291 LOGE("unknown output thread");
292 lStatus = BAD_VALUE;
293 goto Exit;
294 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800295
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800296 wclient = mClients.valueFor(pid);
297
298 if (wclient != NULL) {
299 client = wclient.promote();
300 } else {
301 client = new Client(this, pid);
302 mClients.add(pid, client);
303 }
Eric Laurent9d91ad52009-07-17 12:17:14 -0700304 track = thread->createTrack_l(client, streamType, sampleRate, format,
305 channelCount, frameCount, sharedBuffer, &lStatus);
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700306 }
307 if (lStatus == NO_ERROR) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800308 trackHandle = new TrackHandle(track);
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700309 } else {
Eric Laurent0f8ab672009-09-17 05:12:56 -0700310 // remove local strong reference to Client before deleting the Track so that the Client
311 // destructor is called by the TrackBase destructor with mLock held
312 client.clear();
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700313 track.clear();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800314 }
315
316Exit:
317 if(status) {
318 *status = lStatus;
319 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700320 return trackHandle;
321}
322
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700323uint32_t AudioFlinger::sampleRate(int output) const
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700324{
Eric Laurent9d91ad52009-07-17 12:17:14 -0700325 Mutex::Autolock _l(mLock);
326 PlaybackThread *thread = checkPlaybackThread_l(output);
327 if (thread == NULL) {
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700328 LOGW("sampleRate() unknown thread %d", output);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700329 return 0;
330 }
331 return thread->sampleRate();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700332}
333
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700334int AudioFlinger::channelCount(int output) const
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700335{
Eric Laurent9d91ad52009-07-17 12:17:14 -0700336 Mutex::Autolock _l(mLock);
337 PlaybackThread *thread = checkPlaybackThread_l(output);
338 if (thread == NULL) {
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700339 LOGW("channelCount() unknown thread %d", output);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700340 return 0;
341 }
342 return thread->channelCount();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700343}
344
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700345int AudioFlinger::format(int output) const
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700346{
Eric Laurent9d91ad52009-07-17 12:17:14 -0700347 Mutex::Autolock _l(mLock);
348 PlaybackThread *thread = checkPlaybackThread_l(output);
349 if (thread == NULL) {
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700350 LOGW("format() unknown thread %d", output);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700351 return 0;
352 }
353 return thread->format();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700354}
355
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700356size_t AudioFlinger::frameCount(int output) const
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700357{
Eric Laurent9d91ad52009-07-17 12:17:14 -0700358 Mutex::Autolock _l(mLock);
359 PlaybackThread *thread = checkPlaybackThread_l(output);
360 if (thread == NULL) {
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700361 LOGW("frameCount() unknown thread %d", output);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700362 return 0;
363 }
364 return thread->frameCount();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700365}
366
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700367uint32_t AudioFlinger::latency(int output) const
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800368{
Eric Laurent9d91ad52009-07-17 12:17:14 -0700369 Mutex::Autolock _l(mLock);
370 PlaybackThread *thread = checkPlaybackThread_l(output);
371 if (thread == NULL) {
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700372 LOGW("latency() unknown thread %d", output);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700373 return 0;
374 }
375 return thread->latency();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800376}
377
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700378status_t AudioFlinger::setMasterVolume(float value)
379{
380 // check calling permissions
381 if (!settingsAllowed()) {
382 return PERMISSION_DENIED;
383 }
384
385 // when hw supports master volume, don't scale in sw mixer
386 AutoMutex lock(mHardwareLock);
387 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
388 if (mAudioHardware->setMasterVolume(value) == NO_ERROR) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800389 value = 1.0f;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700390 }
391 mHardwareStatus = AUDIO_HW_IDLE;
Eric Laurent9d91ad52009-07-17 12:17:14 -0700392
393 mMasterVolume = value;
394 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700395 mPlaybackThreads.valueAt(i)->setMasterVolume(value);
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700396
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700397 return NO_ERROR;
398}
399
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700400status_t AudioFlinger::setMode(int mode)
401{
402 // check calling permissions
403 if (!settingsAllowed()) {
404 return PERMISSION_DENIED;
405 }
406 if ((mode < 0) || (mode >= AudioSystem::NUM_MODES)) {
407 LOGW("Illegal value: setMode(%d)", mode);
408 return BAD_VALUE;
409 }
410
411 AutoMutex lock(mHardwareLock);
412 mHardwareStatus = AUDIO_HW_SET_MODE;
413 status_t ret = mAudioHardware->setMode(mode);
414 mHardwareStatus = AUDIO_HW_IDLE;
415 return ret;
416}
417
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700418status_t AudioFlinger::setMicMute(bool state)
419{
420 // check calling permissions
421 if (!settingsAllowed()) {
422 return PERMISSION_DENIED;
423 }
424
425 AutoMutex lock(mHardwareLock);
426 mHardwareStatus = AUDIO_HW_SET_MIC_MUTE;
427 status_t ret = mAudioHardware->setMicMute(state);
428 mHardwareStatus = AUDIO_HW_IDLE;
429 return ret;
430}
431
432bool AudioFlinger::getMicMute() const
433{
434 bool state = AudioSystem::MODE_INVALID;
435 mHardwareStatus = AUDIO_HW_GET_MIC_MUTE;
436 mAudioHardware->getMicMute(&state);
437 mHardwareStatus = AUDIO_HW_IDLE;
438 return state;
439}
440
441status_t AudioFlinger::setMasterMute(bool muted)
442{
443 // check calling permissions
444 if (!settingsAllowed()) {
445 return PERMISSION_DENIED;
446 }
Eric Laurent9d91ad52009-07-17 12:17:14 -0700447
448 mMasterMute = muted;
449 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700450 mPlaybackThreads.valueAt(i)->setMasterMute(muted);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700451
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700452 return NO_ERROR;
453}
454
455float AudioFlinger::masterVolume() const
456{
Eric Laurent9d91ad52009-07-17 12:17:14 -0700457 return mMasterVolume;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700458}
459
460bool AudioFlinger::masterMute() const
461{
Eric Laurent9d91ad52009-07-17 12:17:14 -0700462 return mMasterMute;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700463}
464
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700465status_t AudioFlinger::setStreamVolume(int stream, float value, int output)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700466{
467 // check calling permissions
468 if (!settingsAllowed()) {
469 return PERMISSION_DENIED;
470 }
471
Eric Laurent9d91ad52009-07-17 12:17:14 -0700472 if (stream < 0 || uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700473 return BAD_VALUE;
474 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800475
Eric Laurent9d91ad52009-07-17 12:17:14 -0700476 AutoMutex lock(mLock);
477 PlaybackThread *thread = NULL;
478 if (output) {
479 thread = checkPlaybackThread_l(output);
480 if (thread == NULL) {
481 return BAD_VALUE;
482 }
483 }
484
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700485 status_t ret = NO_ERROR;
Eric Laurent9d91ad52009-07-17 12:17:14 -0700486
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800487 if (stream == AudioSystem::VOICE_CALL ||
488 stream == AudioSystem::BLUETOOTH_SCO) {
Eric Laurent4dd495b2009-04-21 07:56:33 -0700489 float hwValue;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800490 if (stream == AudioSystem::VOICE_CALL) {
Jean-Baptiste Queru732ca392009-03-18 11:33:14 -0700491 hwValue = (float)AudioSystem::logToLinear(value)/100.0f;
Eric Laurent4dd495b2009-04-21 07:56:33 -0700492 // offset value to reflect actual hardware volume that never reaches 0
493 // 1% corresponds roughly to first step in VOICE_CALL stream volume setting (see AudioService.java)
494 value = 0.01 + 0.99 * value;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800495 } else { // (type == AudioSystem::BLUETOOTH_SCO)
Jean-Baptiste Queru732ca392009-03-18 11:33:14 -0700496 hwValue = 1.0f;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800497 }
498
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700499 AutoMutex lock(mHardwareLock);
500 mHardwareStatus = AUDIO_SET_VOICE_VOLUME;
Jean-Baptiste Queru732ca392009-03-18 11:33:14 -0700501 ret = mAudioHardware->setVoiceVolume(hwValue);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700502 mHardwareStatus = AUDIO_HW_IDLE;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800503
Eric Laurent9d91ad52009-07-17 12:17:14 -0700504 }
505
506 mStreamTypes[stream].volume = value;
507
508 if (thread == NULL) {
509 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700510 mPlaybackThreads.valueAt(i)->setStreamVolume(stream, value);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700511
512 } else {
513 thread->setStreamVolume(stream, value);
514 }
Eric Laurent4dd495b2009-04-21 07:56:33 -0700515
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700516 return ret;
517}
518
519status_t AudioFlinger::setStreamMute(int stream, bool muted)
520{
521 // check calling permissions
522 if (!settingsAllowed()) {
523 return PERMISSION_DENIED;
524 }
525
Eric Laurent9d91ad52009-07-17 12:17:14 -0700526 if (stream < 0 || uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES ||
Eric Laurentb1596ee2009-03-26 01:57:59 -0700527 uint32_t(stream) == AudioSystem::ENFORCED_AUDIBLE) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700528 return BAD_VALUE;
529 }
The Android Open Source Project4f68be12009-03-18 17:39:46 -0700530
Eric Laurent9d91ad52009-07-17 12:17:14 -0700531 mStreamTypes[stream].mute = muted;
532 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700533 mPlaybackThreads.valueAt(i)->setStreamMute(stream, muted);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800534
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700535 return NO_ERROR;
536}
537
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700538float AudioFlinger::streamVolume(int stream, int output) const
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700539{
Eric Laurent9d91ad52009-07-17 12:17:14 -0700540 if (stream < 0 || uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700541 return 0.0f;
542 }
Eric Laurent9d91ad52009-07-17 12:17:14 -0700543
544 AutoMutex lock(mLock);
545 float volume;
546 if (output) {
547 PlaybackThread *thread = checkPlaybackThread_l(output);
548 if (thread == NULL) {
549 return 0.0f;
550 }
551 volume = thread->streamVolume(stream);
552 } else {
553 volume = mStreamTypes[stream].volume;
554 }
555
Eric Laurent4dd495b2009-04-21 07:56:33 -0700556 // remove correction applied by setStreamVolume()
Jean-Baptiste Queru732ca392009-03-18 11:33:14 -0700557 if (stream == AudioSystem::VOICE_CALL) {
Eric Laurent4dd495b2009-04-21 07:56:33 -0700558 volume = (volume - 0.01) / 0.99 ;
James E. Blair6015dfc2009-01-17 13:30:20 -0800559 }
Eric Laurent9d91ad52009-07-17 12:17:14 -0700560
Eric Laurent4dd495b2009-04-21 07:56:33 -0700561 return volume;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700562}
563
564bool AudioFlinger::streamMute(int stream) const
565{
Eric Laurent9d91ad52009-07-17 12:17:14 -0700566 if (stream < 0 || stream >= (int)AudioSystem::NUM_STREAM_TYPES) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700567 return true;
568 }
Eric Laurent9d91ad52009-07-17 12:17:14 -0700569
570 return mStreamTypes[stream].mute;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700571}
572
573bool AudioFlinger::isMusicActive() const
574{
Eric Laurentb025ca02009-07-09 03:20:57 -0700575 Mutex::Autolock _l(mLock);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700576 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700577 if (mPlaybackThreads.valueAt(i)->isMusicActive()) {
Eric Laurent9d91ad52009-07-17 12:17:14 -0700578 return true;
579 }
580 }
581 return false;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700582}
583
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700584status_t AudioFlinger::setParameters(int ioHandle, const String8& keyValuePairs)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700585{
Eric Laurent9d91ad52009-07-17 12:17:14 -0700586 status_t result;
587
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700588 LOGV("setParameters(): io %d, keyvalue %s, tid %d, calling tid %d",
Eric Laurent9d91ad52009-07-17 12:17:14 -0700589 ioHandle, keyValuePairs.string(), gettid(), IPCThreadState::self()->getCallingPid());
590 // check calling permissions
591 if (!settingsAllowed()) {
592 return PERMISSION_DENIED;
The Android Open Source Project8a7a6752009-01-15 16:12:10 -0800593 }
Eric Laurent9d91ad52009-07-17 12:17:14 -0700594
595 // ioHandle == 0 means the parameters are global to the audio hardware interface
596 if (ioHandle == 0) {
597 AutoMutex lock(mHardwareLock);
598 mHardwareStatus = AUDIO_SET_PARAMETER;
599 result = mAudioHardware->setParameters(keyValuePairs);
600 mHardwareStatus = AUDIO_HW_IDLE;
601 return result;
602 }
603
Eric Laurent2d70c802009-09-29 11:12:57 -0700604 // hold a strong ref on thread in case closeOutput() or closeInput() is called
605 // and the thread is exited once the lock is released
606 sp<ThreadBase> thread;
607 {
608 Mutex::Autolock _l(mLock);
609 thread = checkPlaybackThread_l(ioHandle);
610 if (thread == NULL) {
611 thread = checkRecordThread_l(ioHandle);
612 }
Eric Laurent9d91ad52009-07-17 12:17:14 -0700613 }
Eric Laurent2d70c802009-09-29 11:12:57 -0700614 if (thread != NULL) {
615 return thread->setParameters(keyValuePairs);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700616 }
Eric Laurent9d91ad52009-07-17 12:17:14 -0700617 return BAD_VALUE;
618}
619
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700620String8 AudioFlinger::getParameters(int ioHandle, const String8& keys)
Eric Laurent9d91ad52009-07-17 12:17:14 -0700621{
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700622// LOGV("getParameters() io %d, keys %s, tid %d, calling tid %d",
Eric Laurent9d91ad52009-07-17 12:17:14 -0700623// ioHandle, keys.string(), gettid(), IPCThreadState::self()->getCallingPid());
624
625 if (ioHandle == 0) {
626 return mAudioHardware->getParameters(keys);
627 }
Eric Laurent2d70c802009-09-29 11:12:57 -0700628
629 Mutex::Autolock _l(mLock);
630
Eric Laurent9d91ad52009-07-17 12:17:14 -0700631 PlaybackThread *playbackThread = checkPlaybackThread_l(ioHandle);
632 if (playbackThread != NULL) {
633 return playbackThread->getParameters(keys);
634 }
635 RecordThread *recordThread = checkRecordThread_l(ioHandle);
636 if (recordThread != NULL) {
637 return recordThread->getParameters(keys);
638 }
639 return String8("");
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700640}
641
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800642size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
643{
644 return mAudioHardware->getInputBufferSize(sampleRate, format, channelCount);
645}
646
647void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
648{
Eric Laurent9d91ad52009-07-17 12:17:14 -0700649
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800650 LOGV("registerClient() %p, tid %d, calling tid %d", client.get(), gettid(), IPCThreadState::self()->getCallingPid());
651 Mutex::Autolock _l(mLock);
652
653 sp<IBinder> binder = client->asBinder();
654 if (mNotificationClients.indexOf(binder) < 0) {
655 LOGV("Adding notification client %p", binder.get());
656 binder->linkToDeath(this);
657 mNotificationClients.add(binder);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700658 }
659
660 // the config change is always sent from playback or record threads to avoid deadlock
661 // with AudioSystem::gLock
662 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700663 mPlaybackThreads.valueAt(i)->sendConfigEvent(AudioSystem::OUTPUT_OPENED);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700664 }
665
666 for (size_t i = 0; i < mRecordThreads.size(); i++) {
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700667 mRecordThreads.valueAt(i)->sendConfigEvent(AudioSystem::INPUT_OPENED);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800668 }
669}
670
671void AudioFlinger::binderDied(const wp<IBinder>& who) {
Eric Laurent9d91ad52009-07-17 12:17:14 -0700672
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800673 LOGV("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(), IPCThreadState::self()->getCallingPid());
674 Mutex::Autolock _l(mLock);
675
676 IBinder *binder = who.unsafe_get();
677
678 if (binder != NULL) {
679 int index = mNotificationClients.indexOf(binder);
680 if (index >= 0) {
681 LOGV("Removing notification client %p", binder);
682 mNotificationClients.removeAt(index);
683 }
684 }
685}
686
Eric Laurentb3687ae2009-09-15 07:10:12 -0700687// audioConfigChanged_l() must be called with AudioFlinger::mLock held
688void AudioFlinger::audioConfigChanged_l(int event, const sp<ThreadBase>& thread, void *param2) {
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700689 int ioHandle = 0;
690
691 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
692 if (mPlaybackThreads.valueAt(i) == thread) {
693 ioHandle = mPlaybackThreads.keyAt(i);
694 break;
695 }
696 }
697 if (ioHandle == 0) {
698 for (size_t i = 0; i < mRecordThreads.size(); i++) {
699 if (mRecordThreads.valueAt(i) == thread) {
700 ioHandle = mRecordThreads.keyAt(i);
701 break;
702 }
703 }
704 }
705
706 if (ioHandle != 0) {
707 size_t size = mNotificationClients.size();
708 for (size_t i = 0; i < size; i++) {
709 sp<IBinder> binder = mNotificationClients.itemAt(i);
Eric Laurentb3687ae2009-09-15 07:10:12 -0700710 LOGV("audioConfigChanged_l() Notifying change to client %p", binder.get());
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700711 sp<IAudioFlingerClient> client = interface_cast<IAudioFlingerClient> (binder);
712 client->ioConfigChanged(event, ioHandle, param2);
713 }
Eric Laurent9d91ad52009-07-17 12:17:14 -0700714 }
715}
716
Eric Laurent0f8ab672009-09-17 05:12:56 -0700717// removeClient_l() must be called with AudioFlinger::mLock held
718void AudioFlinger::removeClient_l(pid_t pid)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700719{
Eric Laurent0f8ab672009-09-17 05:12:56 -0700720 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 -0700721 mClients.removeItem(pid);
722}
723
Eric Laurent9d91ad52009-07-17 12:17:14 -0700724// ----------------------------------------------------------------------------
725
726AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger)
727 : Thread(false),
728 mAudioFlinger(audioFlinger), mSampleRate(0), mFrameCount(0), mChannelCount(0),
Eric Laurent3464c012009-08-04 09:45:33 -0700729 mFormat(0), mFrameSize(1), mStandby(false)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700730{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800731}
732
Eric Laurent9d91ad52009-07-17 12:17:14 -0700733AudioFlinger::ThreadBase::~ThreadBase()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800734{
Eric Laurent3464c012009-08-04 09:45:33 -0700735 mParamCond.broadcast();
736 mNewParameters.clear();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800737}
738
Eric Laurent9d91ad52009-07-17 12:17:14 -0700739void AudioFlinger::ThreadBase::exit()
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700740{
Eric Laurent2d70c802009-09-29 11:12:57 -0700741 // keep a strong ref on ourself so that we wont get
Eric Laurent9d91ad52009-07-17 12:17:14 -0700742 // destroyed in the middle of requestExitAndWait()
743 sp <ThreadBase> strongMe = this;
744
745 LOGV("ThreadBase::exit");
746 {
747 AutoMutex lock(&mLock);
748 requestExit();
749 mWaitWorkCV.signal();
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700750 }
Eric Laurent9d91ad52009-07-17 12:17:14 -0700751 requestExitAndWait();
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700752}
Eric Laurent9d91ad52009-07-17 12:17:14 -0700753
754uint32_t AudioFlinger::ThreadBase::sampleRate() const
755{
756 return mSampleRate;
757}
758
759int AudioFlinger::ThreadBase::channelCount() const
760{
761 return mChannelCount;
762}
763
764int AudioFlinger::ThreadBase::format() const
765{
766 return mFormat;
767}
768
769size_t AudioFlinger::ThreadBase::frameCount() const
770{
771 return mFrameCount;
772}
773
774status_t AudioFlinger::ThreadBase::setParameters(const String8& keyValuePairs)
775{
Eric Laurent3464c012009-08-04 09:45:33 -0700776 status_t status;
Eric Laurent9d91ad52009-07-17 12:17:14 -0700777
Eric Laurent3464c012009-08-04 09:45:33 -0700778 LOGV("ThreadBase::setParameters() %s", keyValuePairs.string());
Eric Laurent9d91ad52009-07-17 12:17:14 -0700779 Mutex::Autolock _l(mLock);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700780
Eric Laurent3464c012009-08-04 09:45:33 -0700781 mNewParameters.add(keyValuePairs);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700782 mWaitWorkCV.signal();
Eric Laurent2d70c802009-09-29 11:12:57 -0700783 // wait condition with timeout in case the thread loop has exited
784 // before the request could be processed
785 if (mParamCond.waitRelative(mLock, seconds(2)) == NO_ERROR) {
786 status = mParamStatus;
787 mWaitWorkCV.signal();
788 } else {
789 status = TIMED_OUT;
790 }
Eric Laurent3464c012009-08-04 09:45:33 -0700791 return status;
Eric Laurent9d91ad52009-07-17 12:17:14 -0700792}
793
794void AudioFlinger::ThreadBase::sendConfigEvent(int event, int param)
795{
796 Mutex::Autolock _l(mLock);
Eric Laurent3464c012009-08-04 09:45:33 -0700797 sendConfigEvent_l(event, param);
798}
799
800// sendConfigEvent_l() must be called with ThreadBase::mLock held
801void AudioFlinger::ThreadBase::sendConfigEvent_l(int event, int param)
802{
Eric Laurent9d91ad52009-07-17 12:17:14 -0700803 ConfigEvent *configEvent = new ConfigEvent();
804 configEvent->mEvent = event;
805 configEvent->mParam = param;
806 mConfigEvents.add(configEvent);
807 LOGV("sendConfigEvent() num events %d event %d, param %d", mConfigEvents.size(), event, param);
808 mWaitWorkCV.signal();
809}
810
811void AudioFlinger::ThreadBase::processConfigEvents()
812{
813 mLock.lock();
814 while(!mConfigEvents.isEmpty()) {
815 LOGV("processConfigEvents() remaining events %d", mConfigEvents.size());
816 ConfigEvent *configEvent = mConfigEvents[0];
817 mConfigEvents.removeAt(0);
Eric Laurentb3687ae2009-09-15 07:10:12 -0700818 // release mLock because audioConfigChanged() will lock AudioFlinger mLock
819 // before calling Audioflinger::audioConfigChanged_l() thus creating
Eric Laurent9d91ad52009-07-17 12:17:14 -0700820 // potential cross deadlock between AudioFlinger::mLock and mLock
821 mLock.unlock();
822 audioConfigChanged(configEvent->mEvent, configEvent->mParam);
823 delete configEvent;
824 mLock.lock();
825 }
826 mLock.unlock();
827}
828
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800829
830// ----------------------------------------------------------------------------
831
Eric Laurent9d91ad52009-07-17 12:17:14 -0700832AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output)
833 : ThreadBase(audioFlinger),
Eric Laurentf9df2492009-08-06 08:49:39 -0700834 mMixBuffer(0), mSuspended(0), mBytesWritten(0), mOutput(output),
Eric Laurent9395d9b2009-07-23 13:17:39 -0700835 mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800836{
Eric Laurent9d91ad52009-07-17 12:17:14 -0700837 readOutputParameters();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800838
Eric Laurent9d91ad52009-07-17 12:17:14 -0700839 mMasterVolume = mAudioFlinger->masterVolume();
840 mMasterMute = mAudioFlinger->masterMute();
841
842 for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
843 mStreamTypes[stream].volume = mAudioFlinger->streamVolumeInternal(stream);
844 mStreamTypes[stream].mute = mAudioFlinger->streamMute(stream);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800845 }
Eric Laurent9d91ad52009-07-17 12:17:14 -0700846 // notify client processes that a new input has been opened
847 sendConfigEvent(AudioSystem::OUTPUT_OPENED);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800848}
849
Eric Laurent9d91ad52009-07-17 12:17:14 -0700850AudioFlinger::PlaybackThread::~PlaybackThread()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800851{
852 delete [] mMixBuffer;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800853}
854
Eric Laurent9d91ad52009-07-17 12:17:14 -0700855status_t AudioFlinger::PlaybackThread::dump(int fd, const Vector<String16>& args)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800856{
857 dumpInternals(fd, args);
858 dumpTracks(fd, args);
859 return NO_ERROR;
860}
861
Eric Laurent9d91ad52009-07-17 12:17:14 -0700862status_t AudioFlinger::PlaybackThread::dumpTracks(int fd, const Vector<String16>& args)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800863{
864 const size_t SIZE = 256;
865 char buffer[SIZE];
866 String8 result;
867
Eric Laurent9d91ad52009-07-17 12:17:14 -0700868 snprintf(buffer, SIZE, "Output thread %p tracks\n", this);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800869 result.append(buffer);
870 result.append(" Name Clien Typ Fmt Chn Buf S M F SRate LeftV RighV Serv User\n");
871 for (size_t i = 0; i < mTracks.size(); ++i) {
Eric Laurentc828f6a2009-03-31 14:34:35 -0700872 sp<Track> track = mTracks[i];
873 if (track != 0) {
874 track->dump(buffer, SIZE);
875 result.append(buffer);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800876 }
877 }
878
Eric Laurent9d91ad52009-07-17 12:17:14 -0700879 snprintf(buffer, SIZE, "Output thread %p active tracks\n", this);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800880 result.append(buffer);
881 result.append(" Name Clien Typ Fmt Chn Buf S M F SRate LeftV RighV Serv User\n");
882 for (size_t i = 0; i < mActiveTracks.size(); ++i) {
Eric Laurentc828f6a2009-03-31 14:34:35 -0700883 wp<Track> wTrack = mActiveTracks[i];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800884 if (wTrack != 0) {
885 sp<Track> track = wTrack.promote();
886 if (track != 0) {
887 track->dump(buffer, SIZE);
888 result.append(buffer);
889 }
890 }
891 }
892 write(fd, result.string(), result.size());
893 return NO_ERROR;
894}
895
Eric Laurent9d91ad52009-07-17 12:17:14 -0700896status_t AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String16>& args)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800897{
898 const size_t SIZE = 256;
899 char buffer[SIZE];
900 String8 result;
901
Eric Laurent9d91ad52009-07-17 12:17:14 -0700902 snprintf(buffer, SIZE, "Output thread %p internals\n", this);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800903 result.append(buffer);
904 snprintf(buffer, SIZE, "last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime));
905 result.append(buffer);
906 snprintf(buffer, SIZE, "total writes: %d\n", mNumWrites);
907 result.append(buffer);
908 snprintf(buffer, SIZE, "delayed writes: %d\n", mNumDelayedWrites);
909 result.append(buffer);
910 snprintf(buffer, SIZE, "blocked in write: %d\n", mInWrite);
911 result.append(buffer);
912 snprintf(buffer, SIZE, "standby: %d\n", mStandby);
913 result.append(buffer);
914 write(fd, result.string(), result.size());
915 return NO_ERROR;
916}
917
918// Thread virtuals
Eric Laurent9d91ad52009-07-17 12:17:14 -0700919status_t AudioFlinger::PlaybackThread::readyToRun()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800920{
921 if (mSampleRate == 0) {
922 LOGE("No working audio driver found.");
923 return NO_INIT;
924 }
Eric Laurent9d91ad52009-07-17 12:17:14 -0700925 LOGI("AudioFlinger's thread %p ready to run", this);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800926 return NO_ERROR;
927}
928
Eric Laurent9d91ad52009-07-17 12:17:14 -0700929void AudioFlinger::PlaybackThread::onFirstRef()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800930{
931 const size_t SIZE = 256;
932 char buffer[SIZE];
933
Eric Laurent9d91ad52009-07-17 12:17:14 -0700934 snprintf(buffer, SIZE, "Playback Thread %p", this);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800935
936 run(buffer, ANDROID_PRIORITY_URGENT_AUDIO);
937}
938
Eric Laurent9d91ad52009-07-17 12:17:14 -0700939// PlaybackThread::createTrack_l() must be called with AudioFlinger::mLock held
940sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrack_l(
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800941 const sp<AudioFlinger::Client>& client,
942 int streamType,
943 uint32_t sampleRate,
944 int format,
945 int channelCount,
946 int frameCount,
947 const sp<IMemory>& sharedBuffer,
948 status_t *status)
949{
950 sp<Track> track;
951 status_t lStatus;
Eric Laurent9d91ad52009-07-17 12:17:14 -0700952
953 if (mType == DIRECT) {
954 if (sampleRate != mSampleRate || format != mFormat || channelCount != mChannelCount) {
955 LOGE("createTrack_l() Bad parameter: sampleRate %d format %d, channelCount %d for output %p",
956 sampleRate, format, channelCount, mOutput);
957 lStatus = BAD_VALUE;
958 goto Exit;
959 }
960 } else {
961 // Resampler implementation limits input sampling rate to 2 x output sampling rate.
962 if (sampleRate > mSampleRate*2) {
963 LOGE("Sample rate out of range: %d mSampleRate %d", sampleRate, mSampleRate);
964 lStatus = BAD_VALUE;
965 goto Exit;
966 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800967 }
968
Eric Laurent9d91ad52009-07-17 12:17:14 -0700969 if (mOutput == 0) {
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700970 LOGE("Audio driver not initialized.");
971 lStatus = NO_INIT;
972 goto Exit;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800973 }
974
Eric Laurent9d91ad52009-07-17 12:17:14 -0700975 { // scope for mLock
976 Mutex::Autolock _l(mLock);
977 track = new Track(this, client, streamType, sampleRate, format,
978 channelCount, frameCount, sharedBuffer);
979 if (track->getCblk() == NULL) {
980 lStatus = NO_MEMORY;
981 goto Exit;
982 }
983 mTracks.add(track);
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700984 }
The Android Open Source Project22f8def2009-03-09 11:52:12 -0700985 lStatus = NO_ERROR;
986
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800987Exit:
988 if(status) {
989 *status = lStatus;
990 }
991 return track;
992}
993
Eric Laurent9d91ad52009-07-17 12:17:14 -0700994uint32_t AudioFlinger::PlaybackThread::latency() const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800995{
996 if (mOutput) {
997 return mOutput->latency();
998 }
999 else {
1000 return 0;
1001 }
1002}
1003
Eric Laurent9d91ad52009-07-17 12:17:14 -07001004status_t AudioFlinger::PlaybackThread::setMasterVolume(float value)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001005{
1006 mMasterVolume = value;
1007 return NO_ERROR;
1008}
1009
Eric Laurent9d91ad52009-07-17 12:17:14 -07001010status_t AudioFlinger::PlaybackThread::setMasterMute(bool muted)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001011{
1012 mMasterMute = muted;
1013 return NO_ERROR;
1014}
1015
Eric Laurent9d91ad52009-07-17 12:17:14 -07001016float AudioFlinger::PlaybackThread::masterVolume() const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001017{
1018 return mMasterVolume;
1019}
1020
Eric Laurent9d91ad52009-07-17 12:17:14 -07001021bool AudioFlinger::PlaybackThread::masterMute() const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001022{
1023 return mMasterMute;
1024}
1025
Eric Laurent9d91ad52009-07-17 12:17:14 -07001026status_t AudioFlinger::PlaybackThread::setStreamVolume(int stream, float value)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001027{
1028 mStreamTypes[stream].volume = value;
1029 return NO_ERROR;
1030}
1031
Eric Laurent9d91ad52009-07-17 12:17:14 -07001032status_t AudioFlinger::PlaybackThread::setStreamMute(int stream, bool muted)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001033{
1034 mStreamTypes[stream].mute = muted;
1035 return NO_ERROR;
1036}
1037
Eric Laurent9d91ad52009-07-17 12:17:14 -07001038float AudioFlinger::PlaybackThread::streamVolume(int stream) const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001039{
1040 return mStreamTypes[stream].volume;
1041}
1042
Eric Laurent9d91ad52009-07-17 12:17:14 -07001043bool AudioFlinger::PlaybackThread::streamMute(int stream) const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001044{
1045 return mStreamTypes[stream].mute;
1046}
1047
Eric Laurent9d91ad52009-07-17 12:17:14 -07001048bool AudioFlinger::PlaybackThread::isMusicActive() const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001049{
Eric Laurent9d91ad52009-07-17 12:17:14 -07001050 Mutex::Autolock _l(mLock);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001051 size_t count = mActiveTracks.size();
1052 for (size_t i = 0 ; i < count ; ++i) {
1053 sp<Track> t = mActiveTracks[i].promote();
1054 if (t == 0) continue;
1055 Track* const track = t.get();
Eric Laurent9395d9b2009-07-23 13:17:39 -07001056 if (t->type() == AudioSystem::MUSIC)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001057 return true;
1058 }
1059 return false;
1060}
1061
Eric Laurent9d91ad52009-07-17 12:17:14 -07001062// addTrack_l() must be called with ThreadBase::mLock held
1063status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001064{
1065 status_t status = ALREADY_EXISTS;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001066
1067 // here the track could be either new, or restarted
1068 // in both cases "unstop" the track
1069 if (track->isPaused()) {
1070 track->mState = TrackBase::RESUMING;
Eric Laurentf5e868b2009-10-05 20:29:18 -07001071 LOGV("PAUSED => RESUMING (%d) on thread %p", track->name(), this);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001072 } else {
1073 track->mState = TrackBase::ACTIVE;
Eric Laurentf5e868b2009-10-05 20:29:18 -07001074 LOGV("? => ACTIVE (%d) on thread %p", track->name(), this);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001075 }
1076 // set retry count for buffer fill
1077 track->mRetryCount = kMaxTrackStartupRetries;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001078 if (mActiveTracks.indexOf(track) < 0) {
1079 // the track is newly added, make sure it fills up all its
1080 // buffers before playing. This is to ensure the client will
1081 // effectively get the latency it requested.
1082 track->mFillingUpStatus = Track::FS_FILLING;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001083 track->mResetDone = false;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001084 mActiveTracks.add(track);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001085 status = NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001086 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07001087
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001088 LOGV("mWaitWorkCV.broadcast");
Eric Laurent9d91ad52009-07-17 12:17:14 -07001089 mWaitWorkCV.broadcast();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001090
1091 return status;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001092}
1093
Eric Laurent9d91ad52009-07-17 12:17:14 -07001094// destroyTrack_l() must be called with ThreadBase::mLock held
1095void AudioFlinger::PlaybackThread::destroyTrack_l(const sp<Track>& track)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001096{
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001097 track->mState = TrackBase::TERMINATED;
1098 if (mActiveTracks.indexOf(track) < 0) {
1099 LOGV("remove track (%d) and delete from mixer", track->name());
1100 mTracks.remove(track);
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001101 deleteTrackName_l(track->name());
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001102 }
1103}
1104
Eric Laurent9d91ad52009-07-17 12:17:14 -07001105String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys)
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001106{
Eric Laurent9d91ad52009-07-17 12:17:14 -07001107 return mOutput->getParameters(keys);
1108}
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001109
Eric Laurent9d91ad52009-07-17 12:17:14 -07001110void AudioFlinger::PlaybackThread::audioConfigChanged(int event, int param) {
1111 AudioSystem::OutputDescriptor desc;
1112 void *param2 = 0;
1113
1114 LOGV("PlaybackThread::audioConfigChanged, thread %p, event %d, param %d", this, event, param);
1115
1116 switch (event) {
1117 case AudioSystem::OUTPUT_OPENED:
1118 case AudioSystem::OUTPUT_CONFIG_CHANGED:
1119 desc.channels = mChannelCount;
1120 desc.samplingRate = mSampleRate;
1121 desc.format = mFormat;
1122 desc.frameCount = mFrameCount;
1123 desc.latency = latency();
1124 param2 = &desc;
1125 break;
1126
1127 case AudioSystem::STREAM_CONFIG_CHANGED:
1128 param2 = &param;
1129 case AudioSystem::OUTPUT_CLOSED:
1130 default:
1131 break;
1132 }
Eric Laurentb3687ae2009-09-15 07:10:12 -07001133 Mutex::Autolock _l(mAudioFlinger->mLock);
1134 mAudioFlinger->audioConfigChanged_l(event, this, param2);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001135}
1136
1137void AudioFlinger::PlaybackThread::readOutputParameters()
1138{
1139 mSampleRate = mOutput->sampleRate();
1140 mChannelCount = AudioSystem::popCount(mOutput->channels());
1141
1142 mFormat = mOutput->format();
1143 mFrameSize = mOutput->frameSize();
1144 mFrameCount = mOutput->bufferSize() / mFrameSize;
1145
1146 mMinBytesToWrite = (mOutput->latency() * mSampleRate * mFrameSize) / 1000;
1147 // FIXME - Current mixer implementation only supports stereo output: Always
1148 // Allocate a stereo buffer even if HW output is mono.
1149 if (mMixBuffer != NULL) delete mMixBuffer;
1150 mMixBuffer = new int16_t[mFrameCount * 2];
1151 memset(mMixBuffer, 0, mFrameCount * 2 * sizeof(int16_t));
1152}
1153
1154// ----------------------------------------------------------------------------
1155
1156AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output)
1157 : PlaybackThread(audioFlinger, output),
1158 mAudioMixer(0)
1159{
1160 mType = PlaybackThread::MIXER;
1161 mAudioMixer = new AudioMixer(mFrameCount, mSampleRate);
1162
1163 // FIXME - Current mixer implementation only supports stereo output
1164 if (mChannelCount == 1) {
1165 LOGE("Invalid audio hardware channel count");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001166 }
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001167}
1168
Eric Laurent9d91ad52009-07-17 12:17:14 -07001169AudioFlinger::MixerThread::~MixerThread()
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001170{
Eric Laurent9d91ad52009-07-17 12:17:14 -07001171 delete mAudioMixer;
1172}
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001173
Eric Laurent9d91ad52009-07-17 12:17:14 -07001174bool AudioFlinger::MixerThread::threadLoop()
1175{
Eric Laurentf5e868b2009-10-05 20:29:18 -07001176 uint32_t sleepTime = 0;
1177 uint32_t maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs();
Eric Laurent9d91ad52009-07-17 12:17:14 -07001178 int16_t* curBuf = mMixBuffer;
1179 Vector< sp<Track> > tracksToRemove;
1180 size_t enabledTracks = 0;
1181 nsecs_t standbyTime = systemTime();
1182 size_t mixBufferSize = mFrameCount * mFrameSize;
Dave Sparks8a95a452009-09-30 03:09:03 -07001183 // FIXME: Relaxed timing because of a certain device that can't meet latency
1184 // Should be reduced to 2x after the vendor fixes the driver issue
1185 nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 3;
1186 nsecs_t lastWarning = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001187
Eric Laurent9d91ad52009-07-17 12:17:14 -07001188 while (!exitPending())
1189 {
1190 processConfigEvents();
1191
1192 enabledTracks = 0;
1193 { // scope for mLock
1194
1195 Mutex::Autolock _l(mLock);
1196
1197 if (checkForNewParameters_l()) {
1198 mixBufferSize = mFrameCount * mFrameSize;
Dave Sparks8a95a452009-09-30 03:09:03 -07001199 // FIXME: Relaxed timing because of a certain device that can't meet latency
1200 // Should be reduced to 2x after the vendor fixes the driver issue
1201 maxPeriod = seconds(mFrameCount) / mSampleRate * 3;
Eric Laurentf5e868b2009-10-05 20:29:18 -07001202 maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs();
Eric Laurent9d91ad52009-07-17 12:17:14 -07001203 }
1204
1205 const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
1206
1207 // put audio hardware into standby after short delay
1208 if UNLIKELY((!activeTracks.size() && systemTime() > standbyTime) ||
1209 mSuspended) {
1210 if (!mStandby) {
1211 LOGV("Audio hardware entering standby, mixer %p, mSuspended %d\n", this, mSuspended);
1212 mOutput->standby();
1213 mStandby = true;
1214 mBytesWritten = 0;
1215 }
1216
1217 if (!activeTracks.size() && mConfigEvents.isEmpty()) {
1218 // we're about to wait, flush the binder command buffer
1219 IPCThreadState::self()->flushCommands();
1220
1221 if (exitPending()) break;
1222
1223 // wait until we have something to do...
1224 LOGV("MixerThread %p TID %d going to sleep\n", this, gettid());
1225 mWaitWorkCV.wait(mLock);
1226 LOGV("MixerThread %p TID %d waking up\n", this, gettid());
1227
1228 if (mMasterMute == false) {
1229 char value[PROPERTY_VALUE_MAX];
1230 property_get("ro.audio.silent", value, "0");
1231 if (atoi(value)) {
1232 LOGD("Silence is golden");
1233 setMasterMute(true);
1234 }
1235 }
1236
1237 standbyTime = systemTime() + kStandbyTimeInNsecs;
1238 continue;
1239 }
1240 }
1241
1242 enabledTracks = prepareTracks_l(activeTracks, &tracksToRemove);
1243 }
1244
Eric Laurentaef692f2009-09-22 00:35:48 -07001245 if (LIKELY(enabledTracks)) {
1246 // mix buffers...
1247 mAudioMixer->process(curBuf);
1248 sleepTime = 0;
1249 standbyTime = systemTime() + kStandbyTimeInNsecs;
Eric Laurent3522c802009-09-07 08:38:38 -07001250 } else {
Eric Laurentf5e868b2009-10-05 20:29:18 -07001251 // If no tracks are ready, sleep once for the duration of an output
1252 // buffer size, then write 0s to the output
1253 if (sleepTime == 0) {
1254 sleepTime = maxBufferRecoveryInUsecs;
1255 } else if (mBytesWritten != 0) {
Eric Laurentaef692f2009-09-22 00:35:48 -07001256 memset (curBuf, 0, mixBufferSize);
Eric Laurent3522c802009-09-07 08:38:38 -07001257 sleepTime = 0;
Eric Laurent3522c802009-09-07 08:38:38 -07001258 }
Eric Laurentaef692f2009-09-22 00:35:48 -07001259 }
1260
1261 if (mSuspended) {
Eric Laurentf5e868b2009-10-05 20:29:18 -07001262 sleepTime = maxBufferRecoveryInUsecs;
Eric Laurentaef692f2009-09-22 00:35:48 -07001263 }
1264 // sleepTime == 0 means we must write to audio hardware
1265 if (sleepTime == 0) {
1266 mLastWriteTime = systemTime();
1267 mInWrite = true;
Eric Laurentaef692f2009-09-22 00:35:48 -07001268 int bytesWritten = (int)mOutput->write(curBuf, mixBufferSize);
1269 if (bytesWritten > 0) mBytesWritten += bytesWritten;
1270 mNumWrites++;
1271 mInWrite = false;
1272 mStandby = false;
Dave Sparks8a95a452009-09-30 03:09:03 -07001273 nsecs_t now = systemTime();
1274 nsecs_t delta = now - mLastWriteTime;
Eric Laurentaef692f2009-09-22 00:35:48 -07001275 if (delta > maxPeriod) {
Eric Laurentaef692f2009-09-22 00:35:48 -07001276 mNumDelayedWrites++;
Dave Sparks8a95a452009-09-30 03:09:03 -07001277 if ((now - lastWarning) > kWarningThrottle) {
1278 LOGW("write blocked for %llu msecs, %d delayed writes, thread %p",
1279 ns2ms(delta), mNumDelayedWrites, this);
1280 lastWarning = now;
1281 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07001282 }
Eric Laurentaef692f2009-09-22 00:35:48 -07001283 } else {
1284 usleep(sleepTime);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001285 }
1286
1287 // finally let go of all our tracks, without the lock held
1288 // since we can't guarantee the destructors won't acquire that
1289 // same lock.
1290 tracksToRemove.clear();
1291 }
1292
1293 if (!mStandby) {
1294 mOutput->standby();
1295 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07001296
1297 LOGV("MixerThread %p exiting", this);
1298 return false;
1299}
1300
1301// prepareTracks_l() must be called with ThreadBase::mLock held
1302size_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove)
1303{
1304
1305 size_t enabledTracks = 0;
1306 // find out which tracks need to be processed
1307 size_t count = activeTracks.size();
1308 for (size_t i=0 ; i<count ; i++) {
1309 sp<Track> t = activeTracks[i].promote();
1310 if (t == 0) continue;
1311
1312 Track* const track = t.get();
1313 audio_track_cblk_t* cblk = track->cblk();
1314
1315 // The first time a track is added we wait
1316 // for all its buffers to be filled before processing it
1317 mAudioMixer->setActiveTrack(track->name());
1318 if (cblk->framesReady() && (track->isReady() || track->isStopped()) &&
1319 !track->isPaused())
1320 {
1321 //LOGV("track %d u=%08x, s=%08x [OK]", track->name(), cblk->user, cblk->server);
1322
1323 // compute volume for this track
1324 int16_t left, right;
1325 if (track->isMuted() || mMasterMute || track->isPausing() ||
1326 mStreamTypes[track->type()].mute) {
1327 left = right = 0;
1328 if (track->isPausing()) {
1329 track->setPaused();
1330 }
1331 } else {
1332 float typeVolume = mStreamTypes[track->type()].volume;
1333 float v = mMasterVolume * typeVolume;
1334 float v_clamped = v * cblk->volume[0];
1335 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
1336 left = int16_t(v_clamped);
1337 v_clamped = v * cblk->volume[1];
1338 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
1339 right = int16_t(v_clamped);
1340 }
1341
1342 // XXX: these things DON'T need to be done each time
1343 mAudioMixer->setBufferProvider(track);
1344 mAudioMixer->enable(AudioMixer::MIXING);
1345
Eric Laurent08d3d1d2009-09-03 03:45:52 -07001346 int param = AudioMixer::VOLUME;
1347 if (track->mFillingUpStatus == Track::FS_FILLED) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07001348 // no ramp for the first volume setting
1349 track->mFillingUpStatus = Track::FS_ACTIVE;
1350 if (track->mState == TrackBase::RESUMING) {
1351 track->mState = TrackBase::ACTIVE;
1352 param = AudioMixer::RAMP_VOLUME;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001353 }
Eric Laurent08d3d1d2009-09-03 03:45:52 -07001354 } else if (cblk->server != 0) {
1355 // If the track is stopped before the first frame was mixed,
1356 // do not apply ramp
Eric Laurent9d91ad52009-07-17 12:17:14 -07001357 param = AudioMixer::RAMP_VOLUME;
1358 }
Eric Laurent08d3d1d2009-09-03 03:45:52 -07001359
Eric Laurent9d91ad52009-07-17 12:17:14 -07001360 mAudioMixer->setParameter(param, AudioMixer::VOLUME0, left);
1361 mAudioMixer->setParameter(param, AudioMixer::VOLUME1, right);
1362 mAudioMixer->setParameter(
1363 AudioMixer::TRACK,
1364 AudioMixer::FORMAT, track->format());
1365 mAudioMixer->setParameter(
1366 AudioMixer::TRACK,
1367 AudioMixer::CHANNEL_COUNT, track->channelCount());
1368 mAudioMixer->setParameter(
1369 AudioMixer::RESAMPLE,
1370 AudioMixer::SAMPLE_RATE,
1371 int(cblk->sampleRate));
1372
1373 // reset retry count
1374 track->mRetryCount = kMaxTrackRetries;
1375 enabledTracks++;
1376 } else {
1377 //LOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
1378 if (track->isStopped()) {
1379 track->reset();
1380 }
1381 if (track->isTerminated() || track->isStopped() || track->isPaused()) {
1382 // We have consumed all the buffers of this track.
1383 // Remove it from the list of active tracks.
1384 tracksToRemove->add(track);
1385 mAudioMixer->disable(AudioMixer::MIXING);
1386 } else {
1387 // No buffers for this track. Give it a few chances to
1388 // fill a buffer, then remove it from active list.
1389 if (--(track->mRetryCount) <= 0) {
Eric Laurentf5e868b2009-10-05 20:29:18 -07001390 LOGV("BUFFER TIMEOUT: remove(%d) from active list on thread %p", track->name(), this);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001391 tracksToRemove->add(track);
1392 }
Eric Laurent08d3d1d2009-09-03 03:45:52 -07001393 // For tracks using static shared memory buffer, make sure that we have
Eric Laurent9d91ad52009-07-17 12:17:14 -07001394 // written enough data to audio hardware before disabling the track
1395 // NOTE: this condition with arrive before track->mRetryCount <= 0 so we
1396 // don't care about code removing track from active list above.
1397 if ((track->mSharedBuffer == 0) || (mBytesWritten >= mMinBytesToWrite)) {
1398 mAudioMixer->disable(AudioMixer::MIXING);
1399 } else {
1400 enabledTracks++;
1401 }
1402 }
1403 }
1404 }
1405
1406 // remove all the tracks that need to be...
1407 count = tracksToRemove->size();
1408 if (UNLIKELY(count)) {
1409 for (size_t i=0 ; i<count ; i++) {
1410 const sp<Track>& track = tracksToRemove->itemAt(i);
1411 mActiveTracks.remove(track);
1412 if (track->isTerminated()) {
1413 mTracks.remove(track);
1414 deleteTrackName_l(track->mName);
1415 }
1416 }
1417 }
1418
1419 return enabledTracks;
1420}
1421
1422void AudioFlinger::MixerThread::getTracks(
1423 SortedVector < sp<Track> >& tracks,
1424 SortedVector < wp<Track> >& activeTracks,
1425 int streamType)
1426{
1427 LOGV ("MixerThread::getTracks() mixer %p, mTracks.size %d, mActiveTracks.size %d", this, mTracks.size(), mActiveTracks.size());
1428 Mutex::Autolock _l(mLock);
1429 size_t size = mTracks.size();
1430 for (size_t i = 0; i < size; i++) {
1431 sp<Track> t = mTracks[i];
1432 if (t->type() == streamType) {
1433 tracks.add(t);
1434 int j = mActiveTracks.indexOf(t);
1435 if (j >= 0) {
1436 t = mActiveTracks[j].promote();
1437 if (t != NULL) {
1438 activeTracks.add(t);
1439 }
1440 }
1441 }
1442 }
1443
1444 size = activeTracks.size();
1445 for (size_t i = 0; i < size; i++) {
1446 mActiveTracks.remove(activeTracks[i]);
1447 }
1448
1449 size = tracks.size();
1450 for (size_t i = 0; i < size; i++) {
1451 sp<Track> t = tracks[i];
1452 mTracks.remove(t);
1453 deleteTrackName_l(t->name());
1454 }
1455}
1456
1457void AudioFlinger::MixerThread::putTracks(
1458 SortedVector < sp<Track> >& tracks,
1459 SortedVector < wp<Track> >& activeTracks)
1460{
1461 LOGV ("MixerThread::putTracks() mixer %p, tracks.size %d, activeTracks.size %d", this, tracks.size(), activeTracks.size());
1462 Mutex::Autolock _l(mLock);
1463 size_t size = tracks.size();
1464 for (size_t i = 0; i < size ; i++) {
1465 sp<Track> t = tracks[i];
1466 int name = getTrackName_l();
1467
1468 if (name < 0) return;
1469
1470 t->mName = name;
1471 t->mThread = this;
1472 mTracks.add(t);
1473
1474 int j = activeTracks.indexOf(t);
1475 if (j >= 0) {
1476 mActiveTracks.add(t);
Eric Laurent06437712009-09-01 05:56:26 -07001477 // force buffer refilling and no ramp volume when the track is mixed for the first time
1478 t->mFillingUpStatus = Track::FS_FILLING;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001479 }
1480 }
1481}
1482
Eric Laurent9d91ad52009-07-17 12:17:14 -07001483// getTrackName_l() must be called with ThreadBase::mLock held
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001484int AudioFlinger::MixerThread::getTrackName_l()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001485{
1486 return mAudioMixer->getTrackName();
1487}
1488
Eric Laurent9d91ad52009-07-17 12:17:14 -07001489// deleteTrackName_l() must be called with ThreadBase::mLock held
The Android Open Source Project22f8def2009-03-09 11:52:12 -07001490void AudioFlinger::MixerThread::deleteTrackName_l(int name)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001491{
1492 mAudioMixer->deleteTrackName(name);
1493}
1494
Eric Laurent9d91ad52009-07-17 12:17:14 -07001495// checkForNewParameters_l() must be called with ThreadBase::mLock held
1496bool AudioFlinger::MixerThread::checkForNewParameters_l()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001497{
Eric Laurent9d91ad52009-07-17 12:17:14 -07001498 bool reconfig = false;
1499
Eric Laurent3464c012009-08-04 09:45:33 -07001500 while (!mNewParameters.isEmpty()) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07001501 status_t status = NO_ERROR;
Eric Laurent3464c012009-08-04 09:45:33 -07001502 String8 keyValuePair = mNewParameters[0];
1503 AudioParameter param = AudioParameter(keyValuePair);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001504 int value;
Eric Laurent3464c012009-08-04 09:45:33 -07001505
1506 mNewParameters.removeAt(0);
1507
Eric Laurent9d91ad52009-07-17 12:17:14 -07001508 if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
1509 reconfig = true;
1510 }
1511 if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
1512 if (value != AudioSystem::PCM_16_BIT) {
1513 status = BAD_VALUE;
1514 } else {
1515 reconfig = true;
1516 }
1517 }
1518 if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
1519 if (value != AudioSystem::CHANNEL_OUT_STEREO) {
1520 status = BAD_VALUE;
1521 } else {
1522 reconfig = true;
1523 }
1524 }
1525 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
1526 // do not accept frame count changes if tracks are open as the track buffer
1527 // size depends on frame count and correct behavior would not be garantied
1528 // if frame count is changed after track creation
1529 if (!mTracks.isEmpty()) {
1530 status = INVALID_OPERATION;
1531 } else {
1532 reconfig = true;
1533 }
1534 }
1535 if (status == NO_ERROR) {
Eric Laurent3464c012009-08-04 09:45:33 -07001536 status = mOutput->setParameters(keyValuePair);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001537 if (!mStandby && status == INVALID_OPERATION) {
1538 mOutput->standby();
1539 mStandby = true;
1540 mBytesWritten = 0;
Eric Laurent3464c012009-08-04 09:45:33 -07001541 status = mOutput->setParameters(keyValuePair);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001542 }
1543 if (status == NO_ERROR && reconfig) {
1544 delete mAudioMixer;
1545 readOutputParameters();
1546 mAudioMixer = new AudioMixer(mFrameCount, mSampleRate);
1547 for (size_t i = 0; i < mTracks.size() ; i++) {
1548 int name = getTrackName_l();
1549 if (name < 0) break;
1550 mTracks[i]->mName = name;
Eric Laurent878c0e12009-08-10 08:15:12 -07001551 // limit track sample rate to 2 x new output sample rate
1552 if (mTracks[i]->mCblk->sampleRate > 2 * sampleRate()) {
1553 mTracks[i]->mCblk->sampleRate = 2 * sampleRate();
1554 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07001555 }
Eric Laurent3464c012009-08-04 09:45:33 -07001556 sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001557 }
1558 }
1559 mParamStatus = status;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001560 mParamCond.signal();
Eric Laurent3464c012009-08-04 09:45:33 -07001561 mWaitWorkCV.wait(mLock);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001562 }
1563 return reconfig;
1564}
1565
1566status_t AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>& args)
1567{
1568 const size_t SIZE = 256;
1569 char buffer[SIZE];
1570 String8 result;
1571
1572 PlaybackThread::dumpInternals(fd, args);
1573
1574 snprintf(buffer, SIZE, "AudioMixer tracks: %08x\n", mAudioMixer->trackNames());
1575 result.append(buffer);
1576 write(fd, result.string(), result.size());
1577 return NO_ERROR;
1578}
1579
Eric Laurentf5e868b2009-10-05 20:29:18 -07001580uint32_t AudioFlinger::MixerThread::getMaxBufferRecoveryInUsecs()
1581{
1582 uint32_t time = ((mFrameCount * 1000) / mSampleRate) * 1000;
1583 // Add some margin with regard to scheduling precision
1584 if (time > 10000) {
1585 time -= 10000;
1586 }
1587 return time;
1588}
1589
Eric Laurent9d91ad52009-07-17 12:17:14 -07001590// ----------------------------------------------------------------------------
1591AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output)
1592 : PlaybackThread(audioFlinger, output),
1593 mLeftVolume (1.0), mRightVolume(1.0)
1594{
1595 mType = PlaybackThread::DIRECT;
1596}
1597
1598AudioFlinger::DirectOutputThread::~DirectOutputThread()
1599{
1600}
1601
1602
1603bool AudioFlinger::DirectOutputThread::threadLoop()
1604{
Eric Laurentf5e868b2009-10-05 20:29:18 -07001605 uint32_t sleepTime = 0;
1606 uint32_t maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs();
Eric Laurent9d91ad52009-07-17 12:17:14 -07001607 sp<Track> trackToRemove;
1608 sp<Track> activeTrack;
1609 nsecs_t standbyTime = systemTime();
1610 int8_t *curBuf;
1611 size_t mixBufferSize = mFrameCount*mFrameSize;
1612
1613 while (!exitPending())
1614 {
1615 processConfigEvents();
1616
1617 { // scope for the mLock
1618
1619 Mutex::Autolock _l(mLock);
1620
1621 if (checkForNewParameters_l()) {
1622 mixBufferSize = mFrameCount*mFrameSize;
Eric Laurentf5e868b2009-10-05 20:29:18 -07001623 maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs();
Eric Laurent9d91ad52009-07-17 12:17:14 -07001624 }
1625
1626 // put audio hardware into standby after short delay
1627 if UNLIKELY((!mActiveTracks.size() && systemTime() > standbyTime) ||
1628 mSuspended) {
1629 // wait until we have something to do...
1630 if (!mStandby) {
1631 LOGV("Audio hardware entering standby, mixer %p\n", this);
1632 mOutput->standby();
1633 mStandby = true;
1634 mBytesWritten = 0;
1635 }
1636
1637 if (!mActiveTracks.size() && mConfigEvents.isEmpty()) {
1638 // we're about to wait, flush the binder command buffer
1639 IPCThreadState::self()->flushCommands();
1640
1641 if (exitPending()) break;
1642
1643 LOGV("DirectOutputThread %p TID %d going to sleep\n", this, gettid());
1644 mWaitWorkCV.wait(mLock);
1645 LOGV("DirectOutputThread %p TID %d waking up in active mode\n", this, gettid());
1646
1647 if (mMasterMute == false) {
1648 char value[PROPERTY_VALUE_MAX];
1649 property_get("ro.audio.silent", value, "0");
1650 if (atoi(value)) {
1651 LOGD("Silence is golden");
1652 setMasterMute(true);
1653 }
1654 }
1655
1656 standbyTime = systemTime() + kStandbyTimeInNsecs;
1657 continue;
1658 }
1659 }
1660
1661 // find out which tracks need to be processed
1662 if (mActiveTracks.size() != 0) {
1663 sp<Track> t = mActiveTracks[0].promote();
1664 if (t == 0) continue;
1665
1666 Track* const track = t.get();
1667 audio_track_cblk_t* cblk = track->cblk();
1668
1669 // The first time a track is added we wait
1670 // for all its buffers to be filled before processing it
1671 if (cblk->framesReady() && (track->isReady() || track->isStopped()) &&
1672 !track->isPaused())
1673 {
1674 //LOGV("track %d u=%08x, s=%08x [OK]", track->name(), cblk->user, cblk->server);
1675
1676 // compute volume for this track
1677 float left, right;
1678 if (track->isMuted() || mMasterMute || track->isPausing() ||
1679 mStreamTypes[track->type()].mute) {
1680 left = right = 0;
1681 if (track->isPausing()) {
1682 track->setPaused();
1683 }
1684 } else {
1685 float typeVolume = mStreamTypes[track->type()].volume;
1686 float v = mMasterVolume * typeVolume;
1687 float v_clamped = v * cblk->volume[0];
1688 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
1689 left = v_clamped/MAX_GAIN;
1690 v_clamped = v * cblk->volume[1];
1691 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
1692 right = v_clamped/MAX_GAIN;
1693 }
1694
1695 if (left != mLeftVolume || right != mRightVolume) {
1696 mOutput->setVolume(left, right);
1697 left = mLeftVolume;
1698 right = mRightVolume;
1699 }
1700
1701 if (track->mFillingUpStatus == Track::FS_FILLED) {
1702 track->mFillingUpStatus = Track::FS_ACTIVE;
1703 if (track->mState == TrackBase::RESUMING) {
1704 track->mState = TrackBase::ACTIVE;
1705 }
1706 }
1707
1708 // reset retry count
1709 track->mRetryCount = kMaxTrackRetries;
1710 activeTrack = t;
1711 } else {
1712 //LOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
1713 if (track->isStopped()) {
1714 track->reset();
1715 }
1716 if (track->isTerminated() || track->isStopped() || track->isPaused()) {
1717 // We have consumed all the buffers of this track.
1718 // Remove it from the list of active tracks.
1719 trackToRemove = track;
1720 } else {
1721 // No buffers for this track. Give it a few chances to
1722 // fill a buffer, then remove it from active list.
1723 if (--(track->mRetryCount) <= 0) {
1724 LOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
1725 trackToRemove = track;
1726 }
1727
1728 // For tracks using static shared memry buffer, make sure that we have
1729 // written enough data to audio hardware before disabling the track
1730 // NOTE: this condition with arrive before track->mRetryCount <= 0 so we
1731 // don't care about code removing track from active list above.
1732 if ((track->mSharedBuffer != 0) && (mBytesWritten < mMinBytesToWrite)) {
1733 activeTrack = t;
1734 }
1735 }
1736 }
1737 }
1738
1739 // remove all the tracks that need to be...
1740 if (UNLIKELY(trackToRemove != 0)) {
1741 mActiveTracks.remove(trackToRemove);
1742 if (trackToRemove->isTerminated()) {
1743 mTracks.remove(trackToRemove);
1744 deleteTrackName_l(trackToRemove->mName);
1745 }
1746 }
1747 }
1748
Eric Laurentaef692f2009-09-22 00:35:48 -07001749 if (activeTrack != 0) {
1750 AudioBufferProvider::Buffer buffer;
1751 size_t frameCount = mFrameCount;
1752 curBuf = (int8_t *)mMixBuffer;
1753 // output audio to hardware
1754 while(frameCount) {
1755 buffer.frameCount = frameCount;
1756 activeTrack->getNextBuffer(&buffer);
1757 if (UNLIKELY(buffer.raw == 0)) {
1758 memset(curBuf, 0, frameCount * mFrameSize);
1759 break;
1760 }
1761 memcpy(curBuf, buffer.raw, buffer.frameCount * mFrameSize);
1762 frameCount -= buffer.frameCount;
1763 curBuf += buffer.frameCount * mFrameSize;
1764 activeTrack->releaseBuffer(&buffer);
1765 }
1766 sleepTime = 0;
1767 standbyTime = systemTime() + kStandbyTimeInNsecs;
Eric Laurent3522c802009-09-07 08:38:38 -07001768 } else {
Eric Laurentf5e868b2009-10-05 20:29:18 -07001769 if (sleepTime == 0) {
1770 sleepTime = maxBufferRecoveryInUsecs;
1771 } else if (mBytesWritten != 0 && AudioSystem::isLinearPCM(mFormat)) {
Eric Laurentaef692f2009-09-22 00:35:48 -07001772 memset (mMixBuffer, 0, mFrameCount * mFrameSize);
Eric Laurent3522c802009-09-07 08:38:38 -07001773 sleepTime = 0;
Eric Laurent3522c802009-09-07 08:38:38 -07001774 }
Eric Laurentaef692f2009-09-22 00:35:48 -07001775 }
Eric Laurent3522c802009-09-07 08:38:38 -07001776
Eric Laurentaef692f2009-09-22 00:35:48 -07001777 if (mSuspended) {
Eric Laurentf5e868b2009-10-05 20:29:18 -07001778 sleepTime = maxBufferRecoveryInUsecs;
Eric Laurentaef692f2009-09-22 00:35:48 -07001779 }
1780 // sleepTime == 0 means we must write to audio hardware
1781 if (sleepTime == 0) {
1782 mLastWriteTime = systemTime();
1783 mInWrite = true;
1784 int bytesWritten = (int)mOutput->write(mMixBuffer, mixBufferSize);
1785 if (bytesWritten) mBytesWritten += bytesWritten;
1786 mNumWrites++;
1787 mInWrite = false;
1788 mStandby = false;
1789 } else {
1790 usleep(sleepTime);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001791 }
1792
1793 // finally let go of removed track, without the lock held
1794 // since we can't guarantee the destructors won't acquire that
1795 // same lock.
1796 trackToRemove.clear();
1797 activeTrack.clear();
1798 }
1799
1800 if (!mStandby) {
1801 mOutput->standby();
1802 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07001803
1804 LOGV("DirectOutputThread %p exiting", this);
1805 return false;
1806}
1807
1808// getTrackName_l() must be called with ThreadBase::mLock held
1809int AudioFlinger::DirectOutputThread::getTrackName_l()
1810{
1811 return 0;
1812}
1813
1814// deleteTrackName_l() must be called with ThreadBase::mLock held
1815void AudioFlinger::DirectOutputThread::deleteTrackName_l(int name)
1816{
1817}
1818
1819// checkForNewParameters_l() must be called with ThreadBase::mLock held
1820bool AudioFlinger::DirectOutputThread::checkForNewParameters_l()
1821{
1822 bool reconfig = false;
1823
Eric Laurent3464c012009-08-04 09:45:33 -07001824 while (!mNewParameters.isEmpty()) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07001825 status_t status = NO_ERROR;
Eric Laurent3464c012009-08-04 09:45:33 -07001826 String8 keyValuePair = mNewParameters[0];
1827 AudioParameter param = AudioParameter(keyValuePair);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001828 int value;
Eric Laurent3464c012009-08-04 09:45:33 -07001829
1830 mNewParameters.removeAt(0);
1831
Eric Laurent9d91ad52009-07-17 12:17:14 -07001832 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
1833 // do not accept frame count changes if tracks are open as the track buffer
1834 // size depends on frame count and correct behavior would not be garantied
1835 // if frame count is changed after track creation
1836 if (!mTracks.isEmpty()) {
1837 status = INVALID_OPERATION;
1838 } else {
1839 reconfig = true;
1840 }
1841 }
1842 if (status == NO_ERROR) {
Eric Laurent3464c012009-08-04 09:45:33 -07001843 status = mOutput->setParameters(keyValuePair);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001844 if (!mStandby && status == INVALID_OPERATION) {
1845 mOutput->standby();
1846 mStandby = true;
1847 mBytesWritten = 0;
Eric Laurent3464c012009-08-04 09:45:33 -07001848 status = mOutput->setParameters(keyValuePair);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001849 }
1850 if (status == NO_ERROR && reconfig) {
1851 readOutputParameters();
Eric Laurent3464c012009-08-04 09:45:33 -07001852 sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001853 }
1854 }
1855 mParamStatus = status;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001856 mParamCond.signal();
Eric Laurent3464c012009-08-04 09:45:33 -07001857 mWaitWorkCV.wait(mLock);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001858 }
1859 return reconfig;
The Android Open Source Projecte41dd752009-01-22 00:13:42 -08001860}
1861
Eric Laurentf5e868b2009-10-05 20:29:18 -07001862uint32_t AudioFlinger::DirectOutputThread::getMaxBufferRecoveryInUsecs()
1863{
1864 uint32_t time;
1865 if (AudioSystem::isLinearPCM(mFormat)) {
1866 time = ((mFrameCount * 1000) / mSampleRate) * 1000;
1867 // Add some margin with regard to scheduling precision
1868 if (time > 10000) {
1869 time -= 10000;
1870 }
1871 } else {
1872 time = 10000;
1873 }
1874 return time;
1875}
1876
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001877// ----------------------------------------------------------------------------
1878
Eric Laurent9d91ad52009-07-17 12:17:14 -07001879AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger, AudioFlinger::MixerThread* mainThread)
1880 : MixerThread(audioFlinger, mainThread->getOutput())
1881{
1882 mType = PlaybackThread::DUPLICATING;
1883 addOutputTrack(mainThread);
1884}
1885
1886AudioFlinger::DuplicatingThread::~DuplicatingThread()
1887{
1888 mOutputTracks.clear();
1889}
1890
1891bool AudioFlinger::DuplicatingThread::threadLoop()
1892{
Eric Laurentf5e868b2009-10-05 20:29:18 -07001893 uint32_t sleepTime = 0;
1894 uint32_t maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs();
Eric Laurent9d91ad52009-07-17 12:17:14 -07001895 int16_t* curBuf = mMixBuffer;
1896 Vector< sp<Track> > tracksToRemove;
1897 size_t enabledTracks = 0;
1898 nsecs_t standbyTime = systemTime();
1899 size_t mixBufferSize = mFrameCount*mFrameSize;
1900 SortedVector< sp<OutputTrack> > outputTracks;
Eric Laurentf5e868b2009-10-05 20:29:18 -07001901 uint32_t writeFrames = 0;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001902
1903 while (!exitPending())
1904 {
1905 processConfigEvents();
1906
1907 enabledTracks = 0;
1908 { // scope for the mLock
1909
1910 Mutex::Autolock _l(mLock);
1911
1912 if (checkForNewParameters_l()) {
1913 mixBufferSize = mFrameCount*mFrameSize;
Eric Laurentf5e868b2009-10-05 20:29:18 -07001914 maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs();
Eric Laurent9d91ad52009-07-17 12:17:14 -07001915 }
1916
1917 const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
1918
1919 for (size_t i = 0; i < mOutputTracks.size(); i++) {
1920 outputTracks.add(mOutputTracks[i]);
1921 }
1922
1923 // put audio hardware into standby after short delay
1924 if UNLIKELY((!activeTracks.size() && systemTime() > standbyTime) ||
1925 mSuspended) {
1926 if (!mStandby) {
1927 for (size_t i = 0; i < outputTracks.size(); i++) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07001928 outputTracks[i]->stop();
Eric Laurent9d91ad52009-07-17 12:17:14 -07001929 }
1930 mStandby = true;
1931 mBytesWritten = 0;
1932 }
1933
1934 if (!activeTracks.size() && mConfigEvents.isEmpty()) {
1935 // we're about to wait, flush the binder command buffer
1936 IPCThreadState::self()->flushCommands();
1937 outputTracks.clear();
1938
1939 if (exitPending()) break;
1940
1941 LOGV("DuplicatingThread %p TID %d going to sleep\n", this, gettid());
1942 mWaitWorkCV.wait(mLock);
1943 LOGV("DuplicatingThread %p TID %d waking up\n", this, gettid());
1944 if (mMasterMute == false) {
1945 char value[PROPERTY_VALUE_MAX];
1946 property_get("ro.audio.silent", value, "0");
1947 if (atoi(value)) {
1948 LOGD("Silence is golden");
1949 setMasterMute(true);
1950 }
1951 }
1952
1953 standbyTime = systemTime() + kStandbyTimeInNsecs;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001954 continue;
1955 }
1956 }
1957
1958 enabledTracks = prepareTracks_l(activeTracks, &tracksToRemove);
Eric Laurentaef692f2009-09-22 00:35:48 -07001959 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07001960
Eric Laurent9d91ad52009-07-17 12:17:14 -07001961 if (LIKELY(enabledTracks)) {
1962 // mix buffers...
1963 mAudioMixer->process(curBuf);
Eric Laurentaef692f2009-09-22 00:35:48 -07001964 sleepTime = 0;
Eric Laurentf5e868b2009-10-05 20:29:18 -07001965 writeFrames = mFrameCount;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001966 } else {
Eric Laurentf5e868b2009-10-05 20:29:18 -07001967 if (sleepTime == 0) {
1968 sleepTime = maxBufferRecoveryInUsecs;
1969 } else if (mBytesWritten != 0) {
1970 // flush remaining overflow buffers in output tracks
1971 for (size_t i = 0; i < outputTracks.size(); i++) {
1972 if (outputTracks[i]->isActive()) {
1973 sleepTime = 0;
1974 writeFrames = 0;
1975 break;
1976 }
1977 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07001978 }
1979 }
Eric Laurentaef692f2009-09-22 00:35:48 -07001980
1981 if (mSuspended) {
Eric Laurentf5e868b2009-10-05 20:29:18 -07001982 sleepTime = maxBufferRecoveryInUsecs;
Eric Laurentaef692f2009-09-22 00:35:48 -07001983 }
1984 // sleepTime == 0 means we must write to audio hardware
1985 if (sleepTime == 0) {
Eric Laurentf5e868b2009-10-05 20:29:18 -07001986 standbyTime = systemTime() + kStandbyTimeInNsecs;
Eric Laurentaef692f2009-09-22 00:35:48 -07001987 for (size_t i = 0; i < outputTracks.size(); i++) {
Eric Laurentf5e868b2009-10-05 20:29:18 -07001988 outputTracks[i]->write(curBuf, writeFrames);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001989 }
Eric Laurentaef692f2009-09-22 00:35:48 -07001990 mStandby = false;
1991 mBytesWritten += mixBufferSize;
Eric Laurent9d91ad52009-07-17 12:17:14 -07001992 } else {
Eric Laurentaef692f2009-09-22 00:35:48 -07001993 usleep(sleepTime);
Eric Laurent9d91ad52009-07-17 12:17:14 -07001994 }
1995
1996 // finally let go of all our tracks, without the lock held
1997 // since we can't guarantee the destructors won't acquire that
1998 // same lock.
1999 tracksToRemove.clear();
2000 outputTracks.clear();
2001 }
2002
Eric Laurentf5aba822009-08-10 23:22:32 -07002003 { // scope for the mLock
2004
2005 Mutex::Autolock _l(mLock);
2006 if (!mStandby) {
2007 LOGV("DuplicatingThread() exiting out of standby");
2008 for (size_t i = 0; i < mOutputTracks.size(); i++) {
2009 mOutputTracks[i]->destroy();
2010 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002011 }
2012 }
2013
Eric Laurent9d91ad52009-07-17 12:17:14 -07002014 return false;
2015}
2016
2017void AudioFlinger::DuplicatingThread::addOutputTrack(MixerThread *thread)
2018{
2019 int frameCount = (3 * mFrameCount * mSampleRate) / thread->sampleRate();
2020 OutputTrack *outputTrack = new OutputTrack((ThreadBase *)thread,
2021 mSampleRate,
2022 mFormat,
2023 mChannelCount,
2024 frameCount);
Eric Laurentf5aba822009-08-10 23:22:32 -07002025 if (outputTrack->cblk() != NULL) {
2026 thread->setStreamVolume(AudioSystem::NUM_STREAM_TYPES, 1.0f);
2027 mOutputTracks.add(outputTrack);
2028 LOGV("addOutputTrack() track %p, on thread %p", outputTrack, thread);
2029 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002030}
2031
2032void AudioFlinger::DuplicatingThread::removeOutputTrack(MixerThread *thread)
2033{
2034 Mutex::Autolock _l(mLock);
2035 for (size_t i = 0; i < mOutputTracks.size(); i++) {
2036 if (mOutputTracks[i]->thread() == (ThreadBase *)thread) {
Eric Laurentf5aba822009-08-10 23:22:32 -07002037 mOutputTracks[i]->destroy();
Eric Laurent9d91ad52009-07-17 12:17:14 -07002038 mOutputTracks.removeAt(i);
2039 return;
2040 }
2041 }
2042 LOGV("removeOutputTrack(): unkonwn thread: %p", thread);
2043}
2044
Eric Laurent9d91ad52009-07-17 12:17:14 -07002045// ----------------------------------------------------------------------------
2046
The Android Open Source Project22f8def2009-03-09 11:52:12 -07002047// TrackBase constructor must be called with AudioFlinger::mLock held
Eric Laurent9d91ad52009-07-17 12:17:14 -07002048AudioFlinger::ThreadBase::TrackBase::TrackBase(
2049 const wp<ThreadBase>& thread,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002050 const sp<Client>& client,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002051 uint32_t sampleRate,
2052 int format,
2053 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002054 int frameCount,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002055 uint32_t flags,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002056 const sp<IMemory>& sharedBuffer)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002057 : RefBase(),
Eric Laurent9d91ad52009-07-17 12:17:14 -07002058 mThread(thread),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002059 mClient(client),
Eric Laurent6ad8c642009-09-09 05:16:08 -07002060 mCblk(0),
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002061 mFrameCount(0),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002062 mState(IDLE),
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002063 mClientTid(-1),
2064 mFormat(format),
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002065 mFlags(flags & ~SYSTEM_FLAGS_MASK)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002066{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002067 LOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size());
2068
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002069 // LOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002070 size_t size = sizeof(audio_track_cblk_t);
2071 size_t bufferSize = frameCount*channelCount*sizeof(int16_t);
2072 if (sharedBuffer == 0) {
2073 size += bufferSize;
2074 }
2075
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002076 if (client != NULL) {
2077 mCblkMemory = client->heap()->allocate(size);
2078 if (mCblkMemory != 0) {
2079 mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer());
2080 if (mCblk) { // construct the shared structure in-place.
2081 new(mCblk) audio_track_cblk_t();
2082 // clear all buffers
2083 mCblk->frameCount = frameCount;
Eric Laurent0bac5382009-07-07 07:10:45 -07002084 mCblk->sampleRate = sampleRate;
2085 mCblk->channels = (uint8_t)channelCount;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002086 if (sharedBuffer == 0) {
2087 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
2088 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
2089 // Force underrun condition to avoid false underrun callback until first data is
2090 // written to buffer
2091 mCblk->flowControlFlag = 1;
2092 } else {
2093 mBuffer = sharedBuffer->pointer();
2094 }
2095 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002096 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002097 } else {
2098 LOGE("not enough memory for AudioTrack size=%u", size);
2099 client->heap()->dump("AudioTrack");
2100 return;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002101 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002102 } else {
2103 mCblk = (audio_track_cblk_t *)(new uint8_t[size]);
2104 if (mCblk) { // construct the shared structure in-place.
2105 new(mCblk) audio_track_cblk_t();
2106 // clear all buffers
2107 mCblk->frameCount = frameCount;
Eric Laurent0bac5382009-07-07 07:10:45 -07002108 mCblk->sampleRate = sampleRate;
2109 mCblk->channels = (uint8_t)channelCount;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002110 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
2111 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
2112 // Force underrun condition to avoid false underrun callback until first data is
2113 // written to buffer
2114 mCblk->flowControlFlag = 1;
2115 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
2116 }
2117 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002118}
2119
Eric Laurentbdc0f842009-09-16 06:02:45 -07002120AudioFlinger::ThreadBase::TrackBase::~TrackBase()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002121{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002122 if (mCblk) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07002123 mCblk->~audio_track_cblk_t(); // destroy our shared-structure.
2124 if (mClient == NULL) {
2125 delete mCblk;
2126 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002127 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002128 mCblkMemory.clear(); // and free the shared memory
Eric Laurent0f8ab672009-09-17 05:12:56 -07002129 if (mClient != NULL) {
2130 Mutex::Autolock _l(mClient->audioFlinger()->mLock);
2131 mClient.clear();
2132 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002133}
2134
Eric Laurentbdc0f842009-09-16 06:02:45 -07002135void AudioFlinger::ThreadBase::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002136{
2137 buffer->raw = 0;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002138 mFrameCount = buffer->frameCount;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002139 step();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002140 buffer->frameCount = 0;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002141}
2142
Eric Laurentbdc0f842009-09-16 06:02:45 -07002143bool AudioFlinger::ThreadBase::TrackBase::step() {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002144 bool result;
2145 audio_track_cblk_t* cblk = this->cblk();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002146
2147 result = cblk->stepServer(mFrameCount);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002148 if (!result) {
2149 LOGV("stepServer failed acquiring cblk mutex");
2150 mFlags |= STEPSERVER_FAILED;
2151 }
2152 return result;
2153}
2154
Eric Laurentbdc0f842009-09-16 06:02:45 -07002155void AudioFlinger::ThreadBase::TrackBase::reset() {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002156 audio_track_cblk_t* cblk = this->cblk();
2157
2158 cblk->user = 0;
2159 cblk->server = 0;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002160 cblk->userBase = 0;
2161 cblk->serverBase = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002162 mFlags &= (uint32_t)(~SYSTEM_FLAGS_MASK);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002163 LOGV("TrackBase::reset");
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002164}
2165
Eric Laurentbdc0f842009-09-16 06:02:45 -07002166sp<IMemory> AudioFlinger::ThreadBase::TrackBase::getCblk() const
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002167{
2168 return mCblkMemory;
2169}
2170
Eric Laurentbdc0f842009-09-16 06:02:45 -07002171int AudioFlinger::ThreadBase::TrackBase::sampleRate() const {
The Android Open Source Project4f68be12009-03-18 17:39:46 -07002172 return (int)mCblk->sampleRate;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002173}
2174
Eric Laurentbdc0f842009-09-16 06:02:45 -07002175int AudioFlinger::ThreadBase::TrackBase::channelCount() const {
Eric Laurent0bac5382009-07-07 07:10:45 -07002176 return (int)mCblk->channels;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002177}
2178
Eric Laurentbdc0f842009-09-16 06:02:45 -07002179void* AudioFlinger::ThreadBase::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002180 audio_track_cblk_t* cblk = this->cblk();
Eric Laurent9d91ad52009-07-17 12:17:14 -07002181 int8_t *bufferStart = (int8_t *)mBuffer + (offset-cblk->serverBase)*cblk->frameSize;
2182 int8_t *bufferEnd = bufferStart + frames * cblk->frameSize;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002183
2184 // Check validity of returned pointer in case the track control block would have been corrupted.
Eric Laurent9d91ad52009-07-17 12:17:14 -07002185 if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd ||
2186 ((unsigned long)bufferStart & (unsigned long)(cblk->frameSize - 1))) {
The Android Open Source Project4f68be12009-03-18 17:39:46 -07002187 LOGE("TrackBase::getBuffer buffer out of range:\n start: %p, end %p , mBuffer %p mBufferEnd %p\n \
2188 server %d, serverBase %d, user %d, userBase %d, channels %d",
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002189 bufferStart, bufferEnd, mBuffer, mBufferEnd,
The Android Open Source Project4f68be12009-03-18 17:39:46 -07002190 cblk->server, cblk->serverBase, cblk->user, cblk->userBase, cblk->channels);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002191 return 0;
2192 }
2193
2194 return bufferStart;
2195}
2196
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002197// ----------------------------------------------------------------------------
2198
Eric Laurent9d91ad52009-07-17 12:17:14 -07002199// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
2200AudioFlinger::PlaybackThread::Track::Track(
2201 const wp<ThreadBase>& thread,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002202 const sp<Client>& client,
2203 int streamType,
2204 uint32_t sampleRate,
2205 int format,
2206 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002207 int frameCount,
2208 const sp<IMemory>& sharedBuffer)
Eric Laurent9d91ad52009-07-17 12:17:14 -07002209 : TrackBase(thread, client, sampleRate, format, channelCount, frameCount, 0, sharedBuffer),
2210 mMute(false), mSharedBuffer(sharedBuffer), mName(-1)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002211{
Eric Laurent6ad8c642009-09-09 05:16:08 -07002212 if (mCblk != NULL) {
2213 sp<ThreadBase> baseThread = thread.promote();
2214 if (baseThread != 0) {
2215 PlaybackThread *playbackThread = (PlaybackThread *)baseThread.get();
2216 mName = playbackThread->getTrackName_l();
2217 }
2218 LOGV("Track constructor name %d, calling thread %d", mName, IPCThreadState::self()->getCallingPid());
2219 if (mName < 0) {
2220 LOGE("no more track names available");
2221 }
2222 mVolume[0] = 1.0f;
2223 mVolume[1] = 1.0f;
2224 mStreamType = streamType;
2225 // NOTE: audio_track_cblk_t::frameSize for 8 bit PCM data is based on a sample size of
2226 // 16 bit because data is converted to 16 bit before being stored in buffer by AudioTrack
2227 mCblk->frameSize = AudioSystem::isLinearPCM(format) ? channelCount * sizeof(int16_t) : sizeof(int8_t);
Eric Laurent9d91ad52009-07-17 12:17:14 -07002228 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002229}
2230
Eric Laurent9d91ad52009-07-17 12:17:14 -07002231AudioFlinger::PlaybackThread::Track::~Track()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002232{
Eric Laurent9d91ad52009-07-17 12:17:14 -07002233 LOGV("PlaybackThread::Track destructor");
2234 sp<ThreadBase> thread = mThread.promote();
2235 if (thread != 0) {
2236 Mutex::Autolock _l(thread->mLock);
2237 mState = TERMINATED;
The Android Open Source Project22f8def2009-03-09 11:52:12 -07002238 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002239}
2240
Eric Laurent9d91ad52009-07-17 12:17:14 -07002241void AudioFlinger::PlaybackThread::Track::destroy()
2242{
2243 // NOTE: destroyTrack_l() can remove a strong reference to this Track
2244 // by removing it from mTracks vector, so there is a risk that this Tracks's
2245 // desctructor is called. As the destructor needs to lock mLock,
2246 // we must acquire a strong reference on this Track before locking mLock
2247 // here so that the destructor is called only when exiting this function.
2248 // On the other hand, as long as Track::destroy() is only called by
2249 // TrackHandle destructor, the TrackHandle still holds a strong ref on
2250 // this Track with its member mTrack.
2251 sp<Track> keep(this);
2252 { // scope for mLock
2253 sp<ThreadBase> thread = mThread.promote();
2254 if (thread != 0) {
2255 Mutex::Autolock _l(thread->mLock);
2256 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
2257 playbackThread->destroyTrack_l(this);
2258 }
2259 }
2260}
2261
2262void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002263{
2264 snprintf(buffer, size, " %5d %5d %3u %3u %3u %3u %1d %1d %1d %5u %5u %5u %04x %04x\n",
2265 mName - AudioMixer::TRACK0,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002266 (mClient == NULL) ? getpid() : mClient->pid(),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002267 mStreamType,
2268 mFormat,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002269 mCblk->channels,
2270 mFrameCount,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002271 mState,
2272 mMute,
2273 mFillingUpStatus,
2274 mCblk->sampleRate,
2275 mCblk->volume[0],
2276 mCblk->volume[1],
2277 mCblk->server,
2278 mCblk->user);
2279}
2280
Eric Laurent9d91ad52009-07-17 12:17:14 -07002281status_t AudioFlinger::PlaybackThread::Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002282{
2283 audio_track_cblk_t* cblk = this->cblk();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002284 uint32_t framesReady;
2285 uint32_t framesReq = buffer->frameCount;
2286
2287 // Check if last stepServer failed, try to step now
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002288 if (mFlags & TrackBase::STEPSERVER_FAILED) {
2289 if (!step()) goto getNextBuffer_exit;
2290 LOGV("stepServer recovered");
2291 mFlags &= ~TrackBase::STEPSERVER_FAILED;
2292 }
2293
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002294 framesReady = cblk->framesReady();
2295
2296 if (LIKELY(framesReady)) {
2297 uint32_t s = cblk->server;
2298 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
2299
2300 bufferEnd = (cblk->loopEnd < bufferEnd) ? cblk->loopEnd : bufferEnd;
2301 if (framesReq > framesReady) {
2302 framesReq = framesReady;
2303 }
2304 if (s + framesReq > bufferEnd) {
2305 framesReq = bufferEnd - s;
2306 }
2307
2308 buffer->raw = getBuffer(s, framesReq);
2309 if (buffer->raw == 0) goto getNextBuffer_exit;
2310
2311 buffer->frameCount = framesReq;
2312 return NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002313 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002314
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002315getNextBuffer_exit:
2316 buffer->raw = 0;
2317 buffer->frameCount = 0;
Eric Laurentf5e868b2009-10-05 20:29:18 -07002318 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 -07002319 return NOT_ENOUGH_DATA;
2320}
2321
Eric Laurent9d91ad52009-07-17 12:17:14 -07002322bool AudioFlinger::PlaybackThread::Track::isReady() const {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002323 if (mFillingUpStatus != FS_FILLING) return true;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002324
2325 if (mCblk->framesReady() >= mCblk->frameCount ||
2326 mCblk->forceReady) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002327 mFillingUpStatus = FS_FILLED;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002328 mCblk->forceReady = 0;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002329 return true;
2330 }
2331 return false;
2332}
2333
Eric Laurent9d91ad52009-07-17 12:17:14 -07002334status_t AudioFlinger::PlaybackThread::Track::start()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002335{
Eric Laurent9d91ad52009-07-17 12:17:14 -07002336 LOGV("start(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
2337 sp<ThreadBase> thread = mThread.promote();
2338 if (thread != 0) {
2339 Mutex::Autolock _l(thread->mLock);
2340 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
2341 playbackThread->addTrack_l(this);
2342 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002343 return NO_ERROR;
2344}
2345
Eric Laurent9d91ad52009-07-17 12:17:14 -07002346void AudioFlinger::PlaybackThread::Track::stop()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002347{
Eric Laurent9d91ad52009-07-17 12:17:14 -07002348 LOGV("stop(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
2349 sp<ThreadBase> thread = mThread.promote();
2350 if (thread != 0) {
2351 Mutex::Autolock _l(thread->mLock);
2352 if (mState > STOPPED) {
2353 mState = STOPPED;
2354 // If the track is not active (PAUSED and buffers full), flush buffers
2355 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
2356 if (playbackThread->mActiveTracks.indexOf(this) < 0) {
2357 reset();
2358 }
Eric Laurentf5e868b2009-10-05 20:29:18 -07002359 LOGV("(> STOPPED) => STOPPED (%d) on thread %p", mName, playbackThread);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002360 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002361 }
2362}
2363
Eric Laurent9d91ad52009-07-17 12:17:14 -07002364void AudioFlinger::PlaybackThread::Track::pause()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002365{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002366 LOGV("pause(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
Eric Laurent9d91ad52009-07-17 12:17:14 -07002367 sp<ThreadBase> thread = mThread.promote();
2368 if (thread != 0) {
2369 Mutex::Autolock _l(thread->mLock);
2370 if (mState == ACTIVE || mState == RESUMING) {
2371 mState = PAUSING;
Eric Laurentf5e868b2009-10-05 20:29:18 -07002372 LOGV("ACTIVE/RESUMING => PAUSING (%d) on thread %p", mName, thread.get());
Eric Laurent9d91ad52009-07-17 12:17:14 -07002373 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002374 }
2375}
2376
Eric Laurent9d91ad52009-07-17 12:17:14 -07002377void AudioFlinger::PlaybackThread::Track::flush()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002378{
2379 LOGV("flush(%d)", mName);
Eric Laurent9d91ad52009-07-17 12:17:14 -07002380 sp<ThreadBase> thread = mThread.promote();
2381 if (thread != 0) {
2382 Mutex::Autolock _l(thread->mLock);
2383 if (mState != STOPPED && mState != PAUSED && mState != PAUSING) {
2384 return;
2385 }
2386 // No point remaining in PAUSED state after a flush => go to
2387 // STOPPED state
2388 mState = STOPPED;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002389
Eric Laurent9d91ad52009-07-17 12:17:14 -07002390 mCblk->lock.lock();
2391 // NOTE: reset() will reset cblk->user and cblk->server with
2392 // the risk that at the same time, the AudioMixer is trying to read
2393 // data. In this case, getNextBuffer() would return a NULL pointer
2394 // as audio buffer => the AudioMixer code MUST always test that pointer
2395 // returned by getNextBuffer() is not NULL!
2396 reset();
2397 mCblk->lock.unlock();
2398 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002399}
2400
Eric Laurent9d91ad52009-07-17 12:17:14 -07002401void AudioFlinger::PlaybackThread::Track::reset()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002402{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002403 // Do not reset twice to avoid discarding data written just after a flush and before
2404 // the audioflinger thread detects the track is stopped.
2405 if (!mResetDone) {
2406 TrackBase::reset();
2407 // Force underrun condition to avoid false underrun callback until first data is
2408 // written to buffer
2409 mCblk->flowControlFlag = 1;
2410 mCblk->forceReady = 0;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002411 mFillingUpStatus = FS_FILLING;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002412 mResetDone = true;
2413 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002414}
2415
Eric Laurent9d91ad52009-07-17 12:17:14 -07002416void AudioFlinger::PlaybackThread::Track::mute(bool muted)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002417{
2418 mMute = muted;
2419}
2420
Eric Laurent9d91ad52009-07-17 12:17:14 -07002421void AudioFlinger::PlaybackThread::Track::setVolume(float left, float right)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002422{
2423 mVolume[0] = left;
2424 mVolume[1] = right;
2425}
2426
2427// ----------------------------------------------------------------------------
2428
The Android Open Source Project22f8def2009-03-09 11:52:12 -07002429// RecordTrack constructor must be called with AudioFlinger::mLock held
Eric Laurent9d91ad52009-07-17 12:17:14 -07002430AudioFlinger::RecordThread::RecordTrack::RecordTrack(
2431 const wp<ThreadBase>& thread,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002432 const sp<Client>& client,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002433 uint32_t sampleRate,
2434 int format,
2435 int channelCount,
2436 int frameCount,
2437 uint32_t flags)
Eric Laurent9d91ad52009-07-17 12:17:14 -07002438 : TrackBase(thread, client, sampleRate, format,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002439 channelCount, frameCount, flags, 0),
Eric Laurent9d91ad52009-07-17 12:17:14 -07002440 mOverflow(false)
2441{
Eric Laurent6ad8c642009-09-09 05:16:08 -07002442 if (mCblk != NULL) {
2443 LOGV("RecordTrack constructor, size %d", (int)mBufferEnd - (int)mBuffer);
2444 if (format == AudioSystem::PCM_16_BIT) {
2445 mCblk->frameSize = channelCount * sizeof(int16_t);
2446 } else if (format == AudioSystem::PCM_8_BIT) {
2447 mCblk->frameSize = channelCount * sizeof(int8_t);
2448 } else {
2449 mCblk->frameSize = sizeof(int8_t);
2450 }
2451 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002452}
2453
2454AudioFlinger::RecordThread::RecordTrack::~RecordTrack()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002455{
2456}
2457
Eric Laurent9d91ad52009-07-17 12:17:14 -07002458status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002459{
2460 audio_track_cblk_t* cblk = this->cblk();
2461 uint32_t framesAvail;
2462 uint32_t framesReq = buffer->frameCount;
2463
2464 // Check if last stepServer failed, try to step now
2465 if (mFlags & TrackBase::STEPSERVER_FAILED) {
2466 if (!step()) goto getNextBuffer_exit;
2467 LOGV("stepServer recovered");
2468 mFlags &= ~TrackBase::STEPSERVER_FAILED;
2469 }
2470
2471 framesAvail = cblk->framesAvailable_l();
2472
2473 if (LIKELY(framesAvail)) {
2474 uint32_t s = cblk->server;
2475 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
2476
2477 if (framesReq > framesAvail) {
2478 framesReq = framesAvail;
2479 }
2480 if (s + framesReq > bufferEnd) {
2481 framesReq = bufferEnd - s;
2482 }
2483
2484 buffer->raw = getBuffer(s, framesReq);
2485 if (buffer->raw == 0) goto getNextBuffer_exit;
2486
2487 buffer->frameCount = framesReq;
2488 return NO_ERROR;
2489 }
2490
2491getNextBuffer_exit:
2492 buffer->raw = 0;
2493 buffer->frameCount = 0;
2494 return NOT_ENOUGH_DATA;
2495}
2496
Eric Laurent9d91ad52009-07-17 12:17:14 -07002497status_t AudioFlinger::RecordThread::RecordTrack::start()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002498{
Eric Laurent9d91ad52009-07-17 12:17:14 -07002499 sp<ThreadBase> thread = mThread.promote();
2500 if (thread != 0) {
2501 RecordThread *recordThread = (RecordThread *)thread.get();
2502 return recordThread->start(this);
2503 }
2504 return NO_INIT;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002505}
2506
Eric Laurent9d91ad52009-07-17 12:17:14 -07002507void AudioFlinger::RecordThread::RecordTrack::stop()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002508{
Eric Laurent9d91ad52009-07-17 12:17:14 -07002509 sp<ThreadBase> thread = mThread.promote();
2510 if (thread != 0) {
2511 RecordThread *recordThread = (RecordThread *)thread.get();
2512 recordThread->stop(this);
2513 TrackBase::reset();
2514 // Force overerrun condition to avoid false overrun callback until first data is
2515 // read from buffer
2516 mCblk->flowControlFlag = 1;
2517 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002518}
2519
2520
2521// ----------------------------------------------------------------------------
2522
Eric Laurent9d91ad52009-07-17 12:17:14 -07002523AudioFlinger::PlaybackThread::OutputTrack::OutputTrack(
2524 const wp<ThreadBase>& thread,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002525 uint32_t sampleRate,
2526 int format,
2527 int channelCount,
2528 int frameCount)
Eric Laurent9d91ad52009-07-17 12:17:14 -07002529 : Track(thread, NULL, AudioSystem::NUM_STREAM_TYPES, sampleRate, format, channelCount, frameCount, NULL),
2530 mActive(false)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002531{
Eric Laurent9d91ad52009-07-17 12:17:14 -07002532
2533 PlaybackThread *playbackThread = (PlaybackThread *)thread.unsafe_get();
Eric Laurentf5aba822009-08-10 23:22:32 -07002534 if (mCblk != NULL) {
2535 mCblk->out = 1;
2536 mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
2537 mCblk->volume[0] = mCblk->volume[1] = 0x1000;
2538 mOutBuffer.frameCount = 0;
2539 mWaitTimeMs = (playbackThread->frameCount() * 2 * 1000) / playbackThread->sampleRate();
2540 playbackThread->mTracks.add(this);
2541 LOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, mCblk->frameCount %d, mCblk->sampleRate %d, mCblk->channels %d mBufferEnd %p mWaitTimeMs %d",
2542 mCblk, mBuffer, mCblk->buffers, mCblk->frameCount, mCblk->sampleRate, mCblk->channels, mBufferEnd, mWaitTimeMs);
2543 } else {
2544 LOGW("Error creating output track on thread %p", playbackThread);
2545 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002546}
2547
Eric Laurent9d91ad52009-07-17 12:17:14 -07002548AudioFlinger::PlaybackThread::OutputTrack::~OutputTrack()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002549{
Eric Laurentf5aba822009-08-10 23:22:32 -07002550 clearBufferQueue();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002551}
2552
Eric Laurent9d91ad52009-07-17 12:17:14 -07002553status_t AudioFlinger::PlaybackThread::OutputTrack::start()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002554{
2555 status_t status = Track::start();
Eric Laurent9d91ad52009-07-17 12:17:14 -07002556 if (status != NO_ERROR) {
2557 return status;
2558 }
2559
2560 mActive = true;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002561 mRetryCount = 127;
2562 return status;
2563}
2564
Eric Laurent9d91ad52009-07-17 12:17:14 -07002565void AudioFlinger::PlaybackThread::OutputTrack::stop()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002566{
2567 Track::stop();
2568 clearBufferQueue();
2569 mOutBuffer.frameCount = 0;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002570 mActive = false;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002571}
2572
Eric Laurent9d91ad52009-07-17 12:17:14 -07002573bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t frames)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002574{
2575 Buffer *pInBuffer;
2576 Buffer inBuffer;
2577 uint32_t channels = mCblk->channels;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002578 bool outputBufferFull = false;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002579 inBuffer.frameCount = frames;
2580 inBuffer.i16 = data;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002581
2582 uint32_t waitTimeLeftMs = mWaitTimeMs;
2583
Eric Laurentf5e868b2009-10-05 20:29:18 -07002584 if (!mActive && frames != 0) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07002585 start();
2586 sp<ThreadBase> thread = mThread.promote();
2587 if (thread != 0) {
2588 MixerThread *mixerThread = (MixerThread *)thread.get();
2589 if (mCblk->frameCount > frames){
2590 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
2591 uint32_t startFrames = (mCblk->frameCount - frames);
2592 pInBuffer = new Buffer;
2593 pInBuffer->mBuffer = new int16_t[startFrames * channels];
2594 pInBuffer->frameCount = startFrames;
2595 pInBuffer->i16 = pInBuffer->mBuffer;
2596 memset(pInBuffer->raw, 0, startFrames * channels * sizeof(int16_t));
2597 mBufferQueue.add(pInBuffer);
2598 } else {
2599 LOGW ("OutputTrack::write() %p no more buffers in queue", this);
2600 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002601 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002602 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002603 }
2604
Eric Laurent9d91ad52009-07-17 12:17:14 -07002605 while (waitTimeLeftMs) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002606 // First write pending buffers, then new data
2607 if (mBufferQueue.size()) {
2608 pInBuffer = mBufferQueue.itemAt(0);
2609 } else {
2610 pInBuffer = &inBuffer;
2611 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002612
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002613 if (pInBuffer->frameCount == 0) {
2614 break;
2615 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002616
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002617 if (mOutBuffer.frameCount == 0) {
2618 mOutBuffer.frameCount = pInBuffer->frameCount;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002619 nsecs_t startTime = systemTime();
2620 if (obtainBuffer(&mOutBuffer, waitTimeLeftMs) == (status_t)AudioTrack::NO_MORE_BUFFERS) {
2621 LOGV ("OutputTrack::write() %p no more output buffers", this);
2622 outputBufferFull = true;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002623 break;
2624 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002625 uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
Eric Laurentf5e868b2009-10-05 20:29:18 -07002626 LOGV("OutputTrack::write() to thread %p waitTimeMs %d waitTimeLeftMs %d", mThread.unsafe_get(), waitTimeMs, waitTimeLeftMs);
Eric Laurent9d91ad52009-07-17 12:17:14 -07002627 if (waitTimeLeftMs >= waitTimeMs) {
2628 waitTimeLeftMs -= waitTimeMs;
2629 } else {
2630 waitTimeLeftMs = 0;
2631 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002632 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002633
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002634 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount : pInBuffer->frameCount;
2635 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * channels * sizeof(int16_t));
2636 mCblk->stepUser(outFrames);
2637 pInBuffer->frameCount -= outFrames;
2638 pInBuffer->i16 += outFrames * channels;
2639 mOutBuffer.frameCount -= outFrames;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002640 mOutBuffer.i16 += outFrames * channels;
2641
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002642 if (pInBuffer->frameCount == 0) {
2643 if (mBufferQueue.size()) {
2644 mBufferQueue.removeAt(0);
2645 delete [] pInBuffer->mBuffer;
2646 delete pInBuffer;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002647 LOGV("OutputTrack::write() %p released overflow buffer %d", this, mBufferQueue.size());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002648 } else {
2649 break;
2650 }
2651 }
2652 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002653
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002654 // If we could not write all frames, allocate a buffer and queue it for next time.
2655 if (inBuffer.frameCount) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07002656 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002657 pInBuffer = new Buffer;
2658 pInBuffer->mBuffer = new int16_t[inBuffer.frameCount * channels];
2659 pInBuffer->frameCount = inBuffer.frameCount;
2660 pInBuffer->i16 = pInBuffer->mBuffer;
2661 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * channels * sizeof(int16_t));
2662 mBufferQueue.add(pInBuffer);
Eric Laurent9d91ad52009-07-17 12:17:14 -07002663 LOGV("OutputTrack::write() %p adding overflow buffer %d", this, mBufferQueue.size());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002664 } else {
Eric Laurent9d91ad52009-07-17 12:17:14 -07002665 LOGW("OutputTrack::write() %p no more overflow buffers", this);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002666 }
2667 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07002668
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002669 // Calling write() with a 0 length buffer, means that no more data will be written:
Eric Laurent9d91ad52009-07-17 12:17:14 -07002670 // 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 -08002671 // by output mixer.
Eric Laurent9d91ad52009-07-17 12:17:14 -07002672 if (frames == 0 && mBufferQueue.size() == 0) {
2673 if (mCblk->user < mCblk->frameCount) {
2674 frames = mCblk->frameCount - mCblk->user;
2675 pInBuffer = new Buffer;
2676 pInBuffer->mBuffer = new int16_t[frames * channels];
2677 pInBuffer->frameCount = frames;
2678 pInBuffer->i16 = pInBuffer->mBuffer;
2679 memset(pInBuffer->raw, 0, frames * channels * sizeof(int16_t));
2680 mBufferQueue.add(pInBuffer);
Eric Laurentf5e868b2009-10-05 20:29:18 -07002681 } else if (mActive) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07002682 stop();
2683 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002684 }
2685
Eric Laurent9d91ad52009-07-17 12:17:14 -07002686 return outputBufferFull;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002687}
2688
Eric Laurent9d91ad52009-07-17 12:17:14 -07002689status_t AudioFlinger::PlaybackThread::OutputTrack::obtainBuffer(AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002690{
2691 int active;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002692 status_t result;
2693 audio_track_cblk_t* cblk = mCblk;
2694 uint32_t framesReq = buffer->frameCount;
2695
Eric Laurent9d91ad52009-07-17 12:17:14 -07002696// LOGV("OutputTrack::obtainBuffer user %d, server %d", cblk->user, cblk->server);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002697 buffer->frameCount = 0;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002698
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002699 uint32_t framesAvail = cblk->framesAvailable();
2700
Eric Laurent9d91ad52009-07-17 12:17:14 -07002701
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002702 if (framesAvail == 0) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07002703 Mutex::Autolock _l(cblk->lock);
2704 goto start_loop_here;
2705 while (framesAvail == 0) {
2706 active = mActive;
2707 if (UNLIKELY(!active)) {
2708 LOGV("Not active and NO_MORE_BUFFERS");
2709 return AudioTrack::NO_MORE_BUFFERS;
2710 }
2711 result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
2712 if (result != NO_ERROR) {
2713 return AudioTrack::NO_MORE_BUFFERS;
2714 }
2715 // read the server count again
2716 start_loop_here:
2717 framesAvail = cblk->framesAvailable_l();
2718 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002719 }
2720
Eric Laurent9d91ad52009-07-17 12:17:14 -07002721// if (framesAvail < framesReq) {
2722// return AudioTrack::NO_MORE_BUFFERS;
2723// }
2724
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002725 if (framesReq > framesAvail) {
2726 framesReq = framesAvail;
2727 }
2728
2729 uint32_t u = cblk->user;
2730 uint32_t bufferEnd = cblk->userBase + cblk->frameCount;
2731
2732 if (u + framesReq > bufferEnd) {
2733 framesReq = bufferEnd - u;
2734 }
2735
2736 buffer->frameCount = framesReq;
2737 buffer->raw = (void *)cblk->buffer(u);
2738 return NO_ERROR;
2739}
2740
2741
Eric Laurent9d91ad52009-07-17 12:17:14 -07002742void AudioFlinger::PlaybackThread::OutputTrack::clearBufferQueue()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002743{
2744 size_t size = mBufferQueue.size();
2745 Buffer *pBuffer;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002746
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002747 for (size_t i = 0; i < size; i++) {
2748 pBuffer = mBufferQueue.itemAt(i);
2749 delete [] pBuffer->mBuffer;
2750 delete pBuffer;
2751 }
2752 mBufferQueue.clear();
2753}
2754
2755// ----------------------------------------------------------------------------
2756
2757AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
2758 : RefBase(),
2759 mAudioFlinger(audioFlinger),
2760 mMemoryDealer(new MemoryDealer(1024*1024)),
2761 mPid(pid)
2762{
2763 // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
2764}
2765
Eric Laurent0f8ab672009-09-17 05:12:56 -07002766// Client destructor must be called with AudioFlinger::mLock held
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002767AudioFlinger::Client::~Client()
2768{
Eric Laurent0f8ab672009-09-17 05:12:56 -07002769 mAudioFlinger->removeClient_l(mPid);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002770}
2771
2772const sp<MemoryDealer>& AudioFlinger::Client::heap() const
2773{
2774 return mMemoryDealer;
2775}
2776
2777// ----------------------------------------------------------------------------
2778
Eric Laurent9d91ad52009-07-17 12:17:14 -07002779AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::PlaybackThread::Track>& track)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002780 : BnAudioTrack(),
2781 mTrack(track)
2782{
2783}
2784
2785AudioFlinger::TrackHandle::~TrackHandle() {
2786 // just stop the track on deletion, associated resources
2787 // will be freed from the main thread once all pending buffers have
2788 // been played. Unless it's not in the active track list, in which
2789 // case we free everything now...
2790 mTrack->destroy();
2791}
2792
2793status_t AudioFlinger::TrackHandle::start() {
2794 return mTrack->start();
2795}
2796
2797void AudioFlinger::TrackHandle::stop() {
2798 mTrack->stop();
2799}
2800
2801void AudioFlinger::TrackHandle::flush() {
2802 mTrack->flush();
2803}
2804
2805void AudioFlinger::TrackHandle::mute(bool e) {
2806 mTrack->mute(e);
2807}
2808
2809void AudioFlinger::TrackHandle::pause() {
2810 mTrack->pause();
2811}
2812
2813void AudioFlinger::TrackHandle::setVolume(float left, float right) {
2814 mTrack->setVolume(left, right);
2815}
2816
2817sp<IMemory> AudioFlinger::TrackHandle::getCblk() const {
2818 return mTrack->getCblk();
2819}
2820
2821status_t AudioFlinger::TrackHandle::onTransact(
2822 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
2823{
2824 return BnAudioTrack::onTransact(code, data, reply, flags);
2825}
2826
2827// ----------------------------------------------------------------------------
2828
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002829sp<IAudioRecord> AudioFlinger::openRecord(
2830 pid_t pid,
Eric Laurente0e9ecc2009-07-28 08:44:33 -07002831 int input,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002832 uint32_t sampleRate,
2833 int format,
2834 int channelCount,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002835 int frameCount,
2836 uint32_t flags,
2837 status_t *status)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002838{
Eric Laurent9d91ad52009-07-17 12:17:14 -07002839 sp<RecordThread::RecordTrack> recordTrack;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002840 sp<RecordHandle> recordHandle;
2841 sp<Client> client;
2842 wp<Client> wclient;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002843 status_t lStatus;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002844 RecordThread *thread;
2845 size_t inFrameCount;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002846
2847 // check calling permissions
2848 if (!recordingAllowed()) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002849 lStatus = PERMISSION_DENIED;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002850 goto Exit;
2851 }
2852
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002853 // add client to list
The Android Open Source Project22f8def2009-03-09 11:52:12 -07002854 { // scope for mLock
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002855 Mutex::Autolock _l(mLock);
Eric Laurent9d91ad52009-07-17 12:17:14 -07002856 thread = checkRecordThread_l(input);
2857 if (thread == NULL) {
2858 lStatus = BAD_VALUE;
2859 goto Exit;
2860 }
2861
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002862 wclient = mClients.valueFor(pid);
2863 if (wclient != NULL) {
2864 client = wclient.promote();
2865 } else {
2866 client = new Client(this, pid);
2867 mClients.add(pid, client);
2868 }
The Android Open Source Project22f8def2009-03-09 11:52:12 -07002869
The Android Open Source Project22f8def2009-03-09 11:52:12 -07002870 // create new record track. The record track uses one track in mHardwareMixerThread by convention.
Eric Laurent9d91ad52009-07-17 12:17:14 -07002871 recordTrack = new RecordThread::RecordTrack(thread, client, sampleRate,
The Android Open Source Project22f8def2009-03-09 11:52:12 -07002872 format, channelCount, frameCount, flags);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002873 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002874 if (recordTrack->getCblk() == NULL) {
Eric Laurent0f8ab672009-09-17 05:12:56 -07002875 // remove local strong reference to Client before deleting the RecordTrack so that the Client
2876 // destructor is called by the TrackBase destructor with mLock held
2877 client.clear();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002878 recordTrack.clear();
2879 lStatus = NO_MEMORY;
2880 goto Exit;
2881 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002882
2883 // return to handle to client
2884 recordHandle = new RecordHandle(recordTrack);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002885 lStatus = NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002886
2887Exit:
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002888 if (status) {
2889 *status = lStatus;
2890 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002891 return recordHandle;
2892}
2893
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002894// ----------------------------------------------------------------------------
2895
Eric Laurent9d91ad52009-07-17 12:17:14 -07002896AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::RecordThread::RecordTrack>& recordTrack)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002897 : BnAudioRecord(),
2898 mRecordTrack(recordTrack)
2899{
2900}
2901
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002902AudioFlinger::RecordHandle::~RecordHandle() {
2903 stop();
2904}
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002905
2906status_t AudioFlinger::RecordHandle::start() {
2907 LOGV("RecordHandle::start()");
2908 return mRecordTrack->start();
2909}
2910
2911void AudioFlinger::RecordHandle::stop() {
2912 LOGV("RecordHandle::stop()");
2913 mRecordTrack->stop();
2914}
2915
2916sp<IMemory> AudioFlinger::RecordHandle::getCblk() const {
2917 return mRecordTrack->getCblk();
2918}
2919
2920status_t AudioFlinger::RecordHandle::onTransact(
2921 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
2922{
2923 return BnAudioRecord::onTransact(code, data, reply, flags);
2924}
2925
2926// ----------------------------------------------------------------------------
2927
Eric Laurent9d91ad52009-07-17 12:17:14 -07002928AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, AudioStreamIn *input, uint32_t sampleRate, uint32_t channels) :
2929 ThreadBase(audioFlinger),
2930 mInput(input), mResampler(0), mRsmpOutBuffer(0), mRsmpInBuffer(0)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002931{
Eric Laurent9d91ad52009-07-17 12:17:14 -07002932 mReqChannelCount = AudioSystem::popCount(channels);
2933 mReqSampleRate = sampleRate;
2934 readInputParameters();
2935 sendConfigEvent(AudioSystem::INPUT_OPENED);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002936}
2937
Eric Laurent9d91ad52009-07-17 12:17:14 -07002938
2939AudioFlinger::RecordThread::~RecordThread()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002940{
Eric Laurent9d91ad52009-07-17 12:17:14 -07002941 delete[] mRsmpInBuffer;
2942 if (mResampler != 0) {
2943 delete mResampler;
2944 delete[] mRsmpOutBuffer;
2945 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002946}
2947
Eric Laurent9d91ad52009-07-17 12:17:14 -07002948void AudioFlinger::RecordThread::onFirstRef()
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002949{
Eric Laurent9d91ad52009-07-17 12:17:14 -07002950 const size_t SIZE = 256;
2951 char buffer[SIZE];
2952
2953 snprintf(buffer, SIZE, "Record Thread %p", this);
2954
2955 run(buffer, PRIORITY_URGENT_AUDIO);
2956}
2957bool AudioFlinger::RecordThread::threadLoop()
2958{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002959 AudioBufferProvider::Buffer buffer;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002960 sp<RecordTrack> activeTrack;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002961
2962 // start recording
2963 while (!exitPending()) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08002964
Eric Laurent9d91ad52009-07-17 12:17:14 -07002965 processConfigEvents();
2966
2967 { // scope for mLock
2968 Mutex::Autolock _l(mLock);
2969 checkForNewParameters_l();
2970 if (mActiveTrack == 0 && mConfigEvents.isEmpty()) {
2971 if (!mStandby) {
2972 mInput->standby();
2973 mStandby = true;
2974 }
2975
2976 if (exitPending()) break;
2977
2978 LOGV("RecordThread: loop stopping");
2979 // go to sleep
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07002980 mWaitWorkCV.wait(mLock);
Eric Laurent9d91ad52009-07-17 12:17:14 -07002981 LOGV("RecordThread: loop starting");
2982 continue;
2983 }
2984 if (mActiveTrack != 0) {
2985 if (mActiveTrack->mState == TrackBase::PAUSING) {
2986 mActiveTrack.clear();
2987 mStartStopCond.broadcast();
2988 } else if (mActiveTrack->mState == TrackBase::RESUMING) {
2989 mRsmpInIndex = mFrameCount;
2990 if (mReqChannelCount != mActiveTrack->channelCount()) {
2991 mActiveTrack.clear();
2992 } else {
Eric Laurent9e7b8192009-08-10 02:41:54 -07002993 mActiveTrack->mState = TrackBase::ACTIVE;
Eric Laurent9d91ad52009-07-17 12:17:14 -07002994 }
2995 mStartStopCond.broadcast();
2996 }
2997 mStandby = false;
2998 }
2999 }
3000
3001 if (mActiveTrack != 0) {
3002 buffer.frameCount = mFrameCount;
3003 if (LIKELY(mActiveTrack->getNextBuffer(&buffer) == NO_ERROR)) {
3004 size_t framesOut = buffer.frameCount;
3005 if (mResampler == 0) {
3006 // no resampling
3007 while (framesOut) {
3008 size_t framesIn = mFrameCount - mRsmpInIndex;
3009 if (framesIn) {
3010 int8_t *src = (int8_t *)mRsmpInBuffer + mRsmpInIndex * mFrameSize;
3011 int8_t *dst = buffer.i8 + (buffer.frameCount - framesOut) * mActiveTrack->mCblk->frameSize;
3012 if (framesIn > framesOut)
3013 framesIn = framesOut;
3014 mRsmpInIndex += framesIn;
3015 framesOut -= framesIn;
3016 if (mChannelCount == mReqChannelCount ||
3017 mFormat != AudioSystem::PCM_16_BIT) {
3018 memcpy(dst, src, framesIn * mFrameSize);
3019 } else {
3020 int16_t *src16 = (int16_t *)src;
3021 int16_t *dst16 = (int16_t *)dst;
3022 if (mChannelCount == 1) {
3023 while (framesIn--) {
3024 *dst16++ = *src16;
3025 *dst16++ = *src16++;
3026 }
3027 } else {
3028 while (framesIn--) {
3029 *dst16++ = (int16_t)(((int32_t)*src16 + (int32_t)*(src16 + 1)) >> 1);
3030 src16 += 2;
3031 }
3032 }
3033 }
3034 }
3035 if (framesOut && mFrameCount == mRsmpInIndex) {
3036 ssize_t bytesRead;
3037 if (framesOut == mFrameCount &&
3038 (mChannelCount == mReqChannelCount || mFormat != AudioSystem::PCM_16_BIT)) {
3039 bytesRead = mInput->read(buffer.raw, mInputBytes);
3040 framesOut = 0;
3041 } else {
3042 bytesRead = mInput->read(mRsmpInBuffer, mInputBytes);
3043 mRsmpInIndex = 0;
3044 }
3045 if (bytesRead < 0) {
3046 LOGE("Error reading audio input");
3047 sleep(1);
3048 mRsmpInIndex = mFrameCount;
3049 framesOut = 0;
3050 buffer.frameCount = 0;
3051 }
3052 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08003053 }
3054 } else {
Eric Laurent9d91ad52009-07-17 12:17:14 -07003055 // resampling
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003056
Eric Laurent9d91ad52009-07-17 12:17:14 -07003057 memset(mRsmpOutBuffer, 0, framesOut * 2 * sizeof(int32_t));
3058 // alter output frame count as if we were expecting stereo samples
3059 if (mChannelCount == 1 && mReqChannelCount == 1) {
3060 framesOut >>= 1;
3061 }
3062 mResampler->resample(mRsmpOutBuffer, framesOut, this);
3063 // ditherAndClamp() works as long as all buffers returned by mActiveTrack->getNextBuffer()
3064 // are 32 bit aligned which should be always true.
3065 if (mChannelCount == 2 && mReqChannelCount == 1) {
3066 AudioMixer::ditherAndClamp(mRsmpOutBuffer, mRsmpOutBuffer, framesOut);
3067 // the resampler always outputs stereo samples: do post stereo to mono conversion
3068 int16_t *src = (int16_t *)mRsmpOutBuffer;
3069 int16_t *dst = buffer.i16;
3070 while (framesOut--) {
3071 *dst++ = (int16_t)(((int32_t)*src + (int32_t)*(src + 1)) >> 1);
3072 src += 2;
3073 }
3074 } else {
3075 AudioMixer::ditherAndClamp((int32_t *)buffer.raw, mRsmpOutBuffer, framesOut);
3076 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003077
Eric Laurent9d91ad52009-07-17 12:17:14 -07003078 }
3079 mActiveTrack->releaseBuffer(&buffer);
3080 mActiveTrack->overflow();
3081 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003082 // client isn't retrieving buffers fast enough
3083 else {
Eric Laurent9d91ad52009-07-17 12:17:14 -07003084 if (!mActiveTrack->setOverflow())
3085 LOGW("RecordThread: buffer overflow");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08003086 // Release the processor for a while before asking for a new buffer.
3087 // This will give the application more chance to read from the buffer and
3088 // clear the overflow.
3089 usleep(5000);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003090 }
3091 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08003092 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003093
Eric Laurent9d91ad52009-07-17 12:17:14 -07003094 if (!mStandby) {
3095 mInput->standby();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08003096 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07003097 mActiveTrack.clear();
3098
Eric Laurent9d91ad52009-07-17 12:17:14 -07003099 LOGV("RecordThread %p exiting", this);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003100 return false;
3101}
3102
Eric Laurent9d91ad52009-07-17 12:17:14 -07003103status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003104{
Eric Laurent9d91ad52009-07-17 12:17:14 -07003105 LOGV("RecordThread::start");
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003106 AutoMutex lock(&mLock);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003107
Eric Laurent9d91ad52009-07-17 12:17:14 -07003108 if (mActiveTrack != 0) {
3109 if (recordTrack != mActiveTrack.get()) return -EBUSY;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08003110
Eric Laurent9d91ad52009-07-17 12:17:14 -07003111 if (mActiveTrack->mState == TrackBase::PAUSING) mActiveTrack->mState = TrackBase::RESUMING;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003112
Eric Laurent9d91ad52009-07-17 12:17:14 -07003113 return NO_ERROR;
3114 }
3115
3116 mActiveTrack = recordTrack;
3117 mActiveTrack->mState = TrackBase::RESUMING;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003118 // signal thread to start
3119 LOGV("Signal record thread");
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003120 mWaitWorkCV.signal();
Eric Laurent9d91ad52009-07-17 12:17:14 -07003121 mStartStopCond.wait(mLock);
3122 if (mActiveTrack != 0) {
3123 LOGV("Record started OK");
3124 return NO_ERROR;
3125 } else {
3126 LOGV("Record failed to start");
3127 return BAD_VALUE;
3128 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003129}
3130
Eric Laurent9d91ad52009-07-17 12:17:14 -07003131void AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) {
3132 LOGV("RecordThread::stop");
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003133 AutoMutex lock(&mLock);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003134 if (mActiveTrack != 0 && recordTrack == mActiveTrack.get()) {
3135 mActiveTrack->mState = TrackBase::PAUSING;
3136 mStartStopCond.wait(mLock);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003137 }
3138}
3139
Eric Laurent9d91ad52009-07-17 12:17:14 -07003140status_t AudioFlinger::RecordThread::dump(int fd, const Vector<String16>& args)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08003141{
3142 const size_t SIZE = 256;
3143 char buffer[SIZE];
3144 String8 result;
3145 pid_t pid = 0;
3146
Eric Laurent9d91ad52009-07-17 12:17:14 -07003147 if (mActiveTrack != 0 && mActiveTrack->mClient != 0) {
3148 snprintf(buffer, SIZE, "Record client pid: %d\n", mActiveTrack->mClient->pid());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08003149 result.append(buffer);
3150 } else {
3151 result.append("No record client\n");
3152 }
3153 write(fd, result.string(), result.size());
3154 return NO_ERROR;
3155}
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003156
Eric Laurent9d91ad52009-07-17 12:17:14 -07003157status_t AudioFlinger::RecordThread::getNextBuffer(AudioBufferProvider::Buffer* buffer)
3158{
3159 size_t framesReq = buffer->frameCount;
3160 size_t framesReady = mFrameCount - mRsmpInIndex;
3161 int channelCount;
3162
3163 if (framesReady == 0) {
3164 ssize_t bytesRead = mInput->read(mRsmpInBuffer, mInputBytes);
3165 if (bytesRead < 0) {
3166 LOGE("RecordThread::getNextBuffer() Error reading audio input");
3167 sleep(1);
3168 buffer->raw = 0;
3169 buffer->frameCount = 0;
3170 return NOT_ENOUGH_DATA;
3171 }
3172 mRsmpInIndex = 0;
3173 framesReady = mFrameCount;
3174 }
3175
3176 if (framesReq > framesReady) {
3177 framesReq = framesReady;
3178 }
3179
3180 if (mChannelCount == 1 && mReqChannelCount == 2) {
3181 channelCount = 1;
3182 } else {
3183 channelCount = 2;
3184 }
3185 buffer->raw = mRsmpInBuffer + mRsmpInIndex * channelCount;
3186 buffer->frameCount = framesReq;
3187 return NO_ERROR;
3188}
3189
3190void AudioFlinger::RecordThread::releaseBuffer(AudioBufferProvider::Buffer* buffer)
3191{
3192 mRsmpInIndex += buffer->frameCount;
3193 buffer->frameCount = 0;
3194}
3195
3196bool AudioFlinger::RecordThread::checkForNewParameters_l()
3197{
3198 bool reconfig = false;
3199
Eric Laurent3464c012009-08-04 09:45:33 -07003200 while (!mNewParameters.isEmpty()) {
Eric Laurent9d91ad52009-07-17 12:17:14 -07003201 status_t status = NO_ERROR;
Eric Laurent3464c012009-08-04 09:45:33 -07003202 String8 keyValuePair = mNewParameters[0];
3203 AudioParameter param = AudioParameter(keyValuePair);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003204 int value;
3205 int reqFormat = mFormat;
3206 int reqSamplingRate = mReqSampleRate;
3207 int reqChannelCount = mReqChannelCount;
Eric Laurent3464c012009-08-04 09:45:33 -07003208
3209 mNewParameters.removeAt(0);
3210
Eric Laurent9d91ad52009-07-17 12:17:14 -07003211 if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
3212 reqSamplingRate = value;
3213 reconfig = true;
3214 }
3215 if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
3216 reqFormat = value;
3217 reconfig = true;
3218 }
3219 if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
3220 reqChannelCount = AudioSystem::popCount(value);
3221 reconfig = true;
3222 }
3223 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
3224 // do not accept frame count changes if tracks are open as the track buffer
3225 // size depends on frame count and correct behavior would not be garantied
3226 // if frame count is changed after track creation
3227 if (mActiveTrack != 0) {
3228 status = INVALID_OPERATION;
3229 } else {
3230 reconfig = true;
3231 }
3232 }
3233 if (status == NO_ERROR) {
Eric Laurent3464c012009-08-04 09:45:33 -07003234 status = mInput->setParameters(keyValuePair);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003235 if (status == INVALID_OPERATION) {
3236 mInput->standby();
Eric Laurent3464c012009-08-04 09:45:33 -07003237 status = mInput->setParameters(keyValuePair);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003238 }
3239 if (reconfig) {
3240 if (status == BAD_VALUE &&
3241 reqFormat == mInput->format() && reqFormat == AudioSystem::PCM_16_BIT &&
3242 ((int)mInput->sampleRate() <= 2 * reqSamplingRate) &&
3243 (AudioSystem::popCount(mInput->channels()) < 3) && (reqChannelCount < 3)) {
3244 status = NO_ERROR;
3245 }
3246 if (status == NO_ERROR) {
3247 readInputParameters();
Eric Laurent3464c012009-08-04 09:45:33 -07003248 sendConfigEvent_l(AudioSystem::INPUT_CONFIG_CHANGED);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003249 }
3250 }
3251 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07003252 mParamStatus = status;
3253 mParamCond.signal();
Eric Laurent3464c012009-08-04 09:45:33 -07003254 mWaitWorkCV.wait(mLock);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003255 }
3256 return reconfig;
3257}
3258
3259String8 AudioFlinger::RecordThread::getParameters(const String8& keys)
3260{
3261 return mInput->getParameters(keys);
3262}
3263
3264void AudioFlinger::RecordThread::audioConfigChanged(int event, int param) {
3265 AudioSystem::OutputDescriptor desc;
3266 void *param2 = 0;
3267
3268 switch (event) {
3269 case AudioSystem::INPUT_OPENED:
3270 case AudioSystem::INPUT_CONFIG_CHANGED:
3271 desc.channels = mChannelCount;
3272 desc.samplingRate = mSampleRate;
3273 desc.format = mFormat;
3274 desc.frameCount = mFrameCount;
3275 desc.latency = 0;
3276 param2 = &desc;
3277 break;
3278
3279 case AudioSystem::INPUT_CLOSED:
3280 default:
3281 break;
3282 }
Eric Laurentb3687ae2009-09-15 07:10:12 -07003283 Mutex::Autolock _l(mAudioFlinger->mLock);
3284 mAudioFlinger->audioConfigChanged_l(event, this, param2);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003285}
3286
3287void AudioFlinger::RecordThread::readInputParameters()
3288{
3289 if (mRsmpInBuffer) delete mRsmpInBuffer;
3290 if (mRsmpOutBuffer) delete mRsmpOutBuffer;
3291 if (mResampler) delete mResampler;
3292 mResampler = 0;
3293
3294 mSampleRate = mInput->sampleRate();
3295 mChannelCount = AudioSystem::popCount(mInput->channels());
3296 mFormat = mInput->format();
3297 mFrameSize = mInput->frameSize();
3298 mInputBytes = mInput->bufferSize();
3299 mFrameCount = mInputBytes / mFrameSize;
3300 mRsmpInBuffer = new int16_t[mFrameCount * mChannelCount];
3301
3302 if (mSampleRate != mReqSampleRate && mChannelCount < 3 && mReqChannelCount < 3)
3303 {
3304 int channelCount;
3305 // optmization: if mono to mono, use the resampler in stereo to stereo mode to avoid
3306 // stereo to mono post process as the resampler always outputs stereo.
3307 if (mChannelCount == 1 && mReqChannelCount == 2) {
3308 channelCount = 1;
3309 } else {
3310 channelCount = 2;
3311 }
3312 mResampler = AudioResampler::create(16, channelCount, mReqSampleRate);
3313 mResampler->setSampleRate(mSampleRate);
3314 mResampler->setVolume(AudioMixer::UNITY_GAIN, AudioMixer::UNITY_GAIN);
3315 mRsmpOutBuffer = new int32_t[mFrameCount * 2];
3316
3317 // optmization: if mono to mono, alter input frame count as if we were inputing stereo samples
3318 if (mChannelCount == 1 && mReqChannelCount == 1) {
3319 mFrameCount >>= 1;
3320 }
3321
3322 }
3323 mRsmpInIndex = mFrameCount;
3324}
3325
3326// ----------------------------------------------------------------------------
3327
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003328int AudioFlinger::openOutput(uint32_t *pDevices,
Eric Laurent9d91ad52009-07-17 12:17:14 -07003329 uint32_t *pSamplingRate,
3330 uint32_t *pFormat,
3331 uint32_t *pChannels,
3332 uint32_t *pLatencyMs,
3333 uint32_t flags)
3334{
3335 status_t status;
3336 PlaybackThread *thread = NULL;
3337 mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
3338 uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
3339 uint32_t format = pFormat ? *pFormat : 0;
3340 uint32_t channels = pChannels ? *pChannels : 0;
3341 uint32_t latency = pLatencyMs ? *pLatencyMs : 0;
3342
3343 LOGV("openOutput(), Device %x, SamplingRate %d, Format %d, Channels %x, flags %x",
3344 pDevices ? *pDevices : 0,
3345 samplingRate,
3346 format,
3347 channels,
3348 flags);
3349
3350 if (pDevices == NULL || *pDevices == 0) {
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003351 return 0;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003352 }
3353 Mutex::Autolock _l(mLock);
3354
3355 AudioStreamOut *output = mAudioHardware->openOutputStream(*pDevices,
3356 (int *)&format,
3357 &channels,
3358 &samplingRate,
3359 &status);
3360 LOGV("openOutput() openOutputStream returned output %p, SamplingRate %d, Format %d, Channels %x, status %d",
3361 output,
3362 samplingRate,
3363 format,
3364 channels,
3365 status);
3366
3367 mHardwareStatus = AUDIO_HW_IDLE;
3368 if (output != 0) {
3369 if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) ||
3370 (format != AudioSystem::PCM_16_BIT) ||
3371 (channels != AudioSystem::CHANNEL_OUT_STEREO)) {
3372 thread = new DirectOutputThread(this, output);
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003373 LOGV("openOutput() created direct output: ID %d thread %p", (mNextThreadId + 1), thread);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003374 } else {
3375 thread = new MixerThread(this, output);
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003376 LOGV("openOutput() created mixer output: ID %d thread %p", (mNextThreadId + 1), thread);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003377 }
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003378 mPlaybackThreads.add(++mNextThreadId, thread);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003379
3380 if (pSamplingRate) *pSamplingRate = samplingRate;
3381 if (pFormat) *pFormat = format;
3382 if (pChannels) *pChannels = channels;
3383 if (pLatencyMs) *pLatencyMs = thread->latency();
3384 }
3385
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003386 return mNextThreadId;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003387}
3388
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003389int AudioFlinger::openDuplicateOutput(int output1, int output2)
Eric Laurent9d91ad52009-07-17 12:17:14 -07003390{
3391 Mutex::Autolock _l(mLock);
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003392 MixerThread *thread1 = checkMixerThread_l(output1);
3393 MixerThread *thread2 = checkMixerThread_l(output2);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003394
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003395 if (thread1 == NULL || thread2 == NULL) {
3396 LOGW("openDuplicateOutput() wrong output mixer type for output %d or %d", output1, output2);
3397 return 0;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003398 }
3399
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003400
3401 DuplicatingThread *thread = new DuplicatingThread(this, thread1);
3402 thread->addOutputTrack(thread2);
3403 mPlaybackThreads.add(++mNextThreadId, thread);
3404 return mNextThreadId;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003405}
3406
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003407status_t AudioFlinger::closeOutput(int output)
Eric Laurent9d91ad52009-07-17 12:17:14 -07003408{
Eric Laurentdae20d92009-08-04 08:37:05 -07003409 // keep strong reference on the playback thread so that
3410 // it is not destroyed while exit() is executed
3411 sp <PlaybackThread> thread;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003412 {
3413 Mutex::Autolock _l(mLock);
3414 thread = checkPlaybackThread_l(output);
3415 if (thread == NULL) {
3416 return BAD_VALUE;
3417 }
3418
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003419 LOGV("closeOutput() %d", output);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003420
3421 if (thread->type() == PlaybackThread::MIXER) {
3422 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003423 if (mPlaybackThreads.valueAt(i)->type() == PlaybackThread::DUPLICATING) {
3424 DuplicatingThread *dupThread = (DuplicatingThread *)mPlaybackThreads.valueAt(i).get();
Eric Laurentdae20d92009-08-04 08:37:05 -07003425 dupThread->removeOutputTrack((MixerThread *)thread.get());
Eric Laurent9d91ad52009-07-17 12:17:14 -07003426 }
3427 }
3428 }
Eric Laurentb3687ae2009-09-15 07:10:12 -07003429 void *param2 = 0;
3430 audioConfigChanged_l(AudioSystem::OUTPUT_CLOSED, thread, param2);
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003431 mPlaybackThreads.removeItem(output);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003432 }
3433 thread->exit();
3434
Eric Laurentdae20d92009-08-04 08:37:05 -07003435 if (thread->type() != PlaybackThread::DUPLICATING) {
3436 mAudioHardware->closeOutputStream(thread->getOutput());
3437 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07003438 return NO_ERROR;
3439}
3440
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003441status_t AudioFlinger::suspendOutput(int output)
Eric Laurent9d91ad52009-07-17 12:17:14 -07003442{
3443 Mutex::Autolock _l(mLock);
3444 PlaybackThread *thread = checkPlaybackThread_l(output);
3445
3446 if (thread == NULL) {
3447 return BAD_VALUE;
3448 }
3449
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003450 LOGV("suspendOutput() %d", output);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003451 thread->suspend();
3452
3453 return NO_ERROR;
3454}
3455
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003456status_t AudioFlinger::restoreOutput(int output)
Eric Laurent9d91ad52009-07-17 12:17:14 -07003457{
3458 Mutex::Autolock _l(mLock);
3459 PlaybackThread *thread = checkPlaybackThread_l(output);
3460
3461 if (thread == NULL) {
3462 return BAD_VALUE;
3463 }
3464
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003465 LOGV("restoreOutput() %d", output);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003466
3467 thread->restore();
3468
3469 return NO_ERROR;
3470}
3471
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003472int AudioFlinger::openInput(uint32_t *pDevices,
Eric Laurent9d91ad52009-07-17 12:17:14 -07003473 uint32_t *pSamplingRate,
3474 uint32_t *pFormat,
3475 uint32_t *pChannels,
3476 uint32_t acoustics)
3477{
3478 status_t status;
3479 RecordThread *thread = NULL;
3480 uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
3481 uint32_t format = pFormat ? *pFormat : 0;
3482 uint32_t channels = pChannels ? *pChannels : 0;
3483 uint32_t reqSamplingRate = samplingRate;
3484 uint32_t reqFormat = format;
3485 uint32_t reqChannels = channels;
3486
3487 if (pDevices == NULL || *pDevices == 0) {
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003488 return 0;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003489 }
3490 Mutex::Autolock _l(mLock);
3491
3492 AudioStreamIn *input = mAudioHardware->openInputStream(*pDevices,
3493 (int *)&format,
3494 &channels,
3495 &samplingRate,
3496 &status,
3497 (AudioSystem::audio_in_acoustics)acoustics);
3498 LOGV("openInput() openInputStream returned input %p, SamplingRate %d, Format %d, Channels %x, acoustics %x, status %d",
3499 input,
3500 samplingRate,
3501 format,
3502 channels,
3503 acoustics,
3504 status);
3505
3506 // If the input could not be opened with the requested parameters and we can handle the conversion internally,
3507 // try to open again with the proposed parameters. The AudioFlinger can resample the input and do mono to stereo
3508 // or stereo to mono conversions on 16 bit PCM inputs.
3509 if (input == 0 && status == BAD_VALUE &&
3510 reqFormat == format && format == AudioSystem::PCM_16_BIT &&
3511 (samplingRate <= 2 * reqSamplingRate) &&
3512 (AudioSystem::popCount(channels) < 3) && (AudioSystem::popCount(reqChannels) < 3)) {
3513 LOGV("openInput() reopening with proposed sampling rate and channels");
3514 input = mAudioHardware->openInputStream(*pDevices,
3515 (int *)&format,
3516 &channels,
3517 &samplingRate,
3518 &status,
3519 (AudioSystem::audio_in_acoustics)acoustics);
3520 }
3521
3522 if (input != 0) {
3523 // Start record thread
3524 thread = new RecordThread(this, input, reqSamplingRate, reqChannels);
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003525 mRecordThreads.add(++mNextThreadId, thread);
3526 LOGV("openInput() created record thread: ID %d thread %p", mNextThreadId, thread);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003527 if (pSamplingRate) *pSamplingRate = reqSamplingRate;
3528 if (pFormat) *pFormat = format;
3529 if (pChannels) *pChannels = reqChannels;
3530
3531 input->standby();
3532 }
3533
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003534 return mNextThreadId;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003535}
3536
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003537status_t AudioFlinger::closeInput(int input)
Eric Laurent9d91ad52009-07-17 12:17:14 -07003538{
Eric Laurentdae20d92009-08-04 08:37:05 -07003539 // keep strong reference on the record thread so that
3540 // it is not destroyed while exit() is executed
3541 sp <RecordThread> thread;
Eric Laurent9d91ad52009-07-17 12:17:14 -07003542 {
3543 Mutex::Autolock _l(mLock);
3544 thread = checkRecordThread_l(input);
3545 if (thread == NULL) {
3546 return BAD_VALUE;
3547 }
3548
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003549 LOGV("closeInput() %d", input);
Eric Laurentb3687ae2009-09-15 07:10:12 -07003550 void *param2 = 0;
3551 audioConfigChanged_l(AudioSystem::INPUT_CLOSED, thread, param2);
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003552 mRecordThreads.removeItem(input);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003553 }
3554 thread->exit();
3555
Eric Laurentdae20d92009-08-04 08:37:05 -07003556 mAudioHardware->closeInputStream(thread->getInput());
3557
Eric Laurent9d91ad52009-07-17 12:17:14 -07003558 return NO_ERROR;
3559}
3560
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003561status_t AudioFlinger::setStreamOutput(uint32_t stream, int output)
Eric Laurent9d91ad52009-07-17 12:17:14 -07003562{
3563 Mutex::Autolock _l(mLock);
3564 MixerThread *dstThread = checkMixerThread_l(output);
3565 if (dstThread == NULL) {
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003566 LOGW("setStreamOutput() bad output id %d", output);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003567 return BAD_VALUE;
3568 }
3569
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003570 LOGV("setStreamOutput() stream %d to output %d", stream, output);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003571
3572 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003573 PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
Eric Laurent9d91ad52009-07-17 12:17:14 -07003574 if (thread != dstThread &&
3575 thread->type() != PlaybackThread::DIRECT) {
3576 MixerThread *srcThread = (MixerThread *)thread;
3577 SortedVector < sp<MixerThread::Track> > tracks;
3578 SortedVector < wp<MixerThread::Track> > activeTracks;
3579 srcThread->getTracks(tracks, activeTracks, stream);
3580 if (tracks.size()) {
3581 dstThread->putTracks(tracks, activeTracks);
Eric Laurent9d91ad52009-07-17 12:17:14 -07003582 }
3583 }
3584 }
3585
Eric Laurent06437712009-09-01 05:56:26 -07003586 dstThread->sendConfigEvent(AudioSystem::STREAM_CONFIG_CHANGED, stream);
3587
Eric Laurent9d91ad52009-07-17 12:17:14 -07003588 return NO_ERROR;
3589}
3590
3591// checkPlaybackThread_l() must be called with AudioFlinger::mLock held
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003592AudioFlinger::PlaybackThread *AudioFlinger::checkPlaybackThread_l(int output) const
Eric Laurent9d91ad52009-07-17 12:17:14 -07003593{
3594 PlaybackThread *thread = NULL;
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003595 if (mPlaybackThreads.indexOfKey(output) >= 0) {
3596 thread = (PlaybackThread *)mPlaybackThreads.valueFor(output).get();
Eric Laurent9d91ad52009-07-17 12:17:14 -07003597 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07003598 return thread;
3599}
3600
3601// checkMixerThread_l() must be called with AudioFlinger::mLock held
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003602AudioFlinger::MixerThread *AudioFlinger::checkMixerThread_l(int output) const
Eric Laurent9d91ad52009-07-17 12:17:14 -07003603{
3604 PlaybackThread *thread = checkPlaybackThread_l(output);
3605 if (thread != NULL) {
3606 if (thread->type() == PlaybackThread::DIRECT) {
3607 thread = NULL;
3608 }
3609 }
3610 return (MixerThread *)thread;
3611}
3612
3613// checkRecordThread_l() must be called with AudioFlinger::mLock held
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003614AudioFlinger::RecordThread *AudioFlinger::checkRecordThread_l(int input) const
Eric Laurent9d91ad52009-07-17 12:17:14 -07003615{
3616 RecordThread *thread = NULL;
Eric Laurente0e9ecc2009-07-28 08:44:33 -07003617 if (mRecordThreads.indexOfKey(input) >= 0) {
3618 thread = (RecordThread *)mRecordThreads.valueFor(input).get();
Eric Laurent9d91ad52009-07-17 12:17:14 -07003619 }
Eric Laurent9d91ad52009-07-17 12:17:14 -07003620 return thread;
3621}
3622
3623// ----------------------------------------------------------------------------
3624
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003625status_t AudioFlinger::onTransact(
3626 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
3627{
3628 return BnAudioFlinger::onTransact(code, data, reply, flags);
3629}
3630
3631// ----------------------------------------------------------------------------
Eric Laurent9d91ad52009-07-17 12:17:14 -07003632
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07003633void AudioFlinger::instantiate() {
3634 defaultServiceManager()->addService(
3635 String16("media.audio_flinger"), new AudioFlinger());
3636}
3637
3638}; // namespace android