blob: 301f46701c0fba33b662836eb4fe666edbe20def [file] [log] [blame]
Mathias Agopian65ab4712010-07-14 17:59:35 -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
Gloria Wang9ee159b2011-02-24 14:51:45 -080027#include <binder/IPCThreadState.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070028#include <binder/IServiceManager.h>
29#include <utils/Log.h>
30#include <binder/Parcel.h>
31#include <binder/IPCThreadState.h>
32#include <utils/String16.h>
33#include <utils/threads.h>
Eric Laurent38ccae22011-03-28 18:37:07 -070034#include <utils/Atomic.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070035
Dima Zavinfce7a472011-04-19 22:30:36 -070036#include <cutils/bitops.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070037#include <cutils/properties.h>
38
39#include <media/AudioTrack.h>
40#include <media/AudioRecord.h>
Gloria Wang9ee159b2011-02-24 14:51:45 -080041#include <media/IMediaPlayerService.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070042
43#include <private/media/AudioTrackShared.h>
44#include <private/media/AudioEffectShared.h>
Dima Zavinfce7a472011-04-19 22:30:36 -070045
46#include <hardware/audio.h>
47#include <hardware/audio_hal.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070048
49#include "AudioMixer.h"
50#include "AudioFlinger.h"
51
Mathias Agopian65ab4712010-07-14 17:59:35 -070052#include <media/EffectsFactoryApi.h>
53#include <media/EffectVisualizerApi.h>
54
55// ----------------------------------------------------------------------------
56// the sim build doesn't have gettid
57
58#ifndef HAVE_GETTID
59# define gettid getpid
60#endif
61
62// ----------------------------------------------------------------------------
63
Eric Laurentde070132010-07-13 04:45:46 -070064extern const char * const gEffectLibPath;
65
Mathias Agopian65ab4712010-07-14 17:59:35 -070066namespace android {
67
68static const char* kDeadlockedString = "AudioFlinger may be deadlocked\n";
69static const char* kHardwareLockedString = "Hardware lock is taken\n";
70
71//static const nsecs_t kStandbyTimeInNsecs = seconds(3);
72static const float MAX_GAIN = 4096.0f;
73static const float MAX_GAIN_INT = 0x1000;
74
75// retry counts for buffer fill timeout
76// 50 * ~20msecs = 1 second
77static const int8_t kMaxTrackRetries = 50;
78static const int8_t kMaxTrackStartupRetries = 50;
79// allow less retry attempts on direct output thread.
80// direct outputs can be a scarce resource in audio hardware and should
81// be released as quickly as possible.
82static const int8_t kMaxTrackRetriesDirect = 2;
83
84static const int kDumpLockRetries = 50;
85static const int kDumpLockSleep = 20000;
86
87static const nsecs_t kWarningThrottle = seconds(5);
88
89
90#define AUDIOFLINGER_SECURITY_ENABLED 1
91
92// ----------------------------------------------------------------------------
93
94static bool recordingAllowed() {
95#ifndef HAVE_ANDROID_OS
96 return true;
97#endif
98#if AUDIOFLINGER_SECURITY_ENABLED
99 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
100 bool ok = checkCallingPermission(String16("android.permission.RECORD_AUDIO"));
101 if (!ok) LOGE("Request requires android.permission.RECORD_AUDIO");
102 return ok;
103#else
104 if (!checkCallingPermission(String16("android.permission.RECORD_AUDIO")))
105 LOGW("WARNING: Need to add android.permission.RECORD_AUDIO to manifest");
106 return true;
107#endif
108}
109
110static bool settingsAllowed() {
111#ifndef HAVE_ANDROID_OS
112 return true;
113#endif
114#if AUDIOFLINGER_SECURITY_ENABLED
115 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
116 bool ok = checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS"));
117 if (!ok) LOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS");
118 return ok;
119#else
120 if (!checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS")))
121 LOGW("WARNING: Need to add android.permission.MODIFY_AUDIO_SETTINGS to manifest");
122 return true;
123#endif
124}
125
Gloria Wang9ee159b2011-02-24 14:51:45 -0800126// To collect the amplifier usage
127static void addBatteryData(uint32_t params) {
128 sp<IBinder> binder =
129 defaultServiceManager()->getService(String16("media.player"));
130 sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
131 if (service.get() == NULL) {
132 LOGW("Cannot connect to the MediaPlayerService for battery tracking");
133 return;
134 }
135
136 service->addBatteryData(params);
137}
138
Mathias Agopian65ab4712010-07-14 17:59:35 -0700139// ----------------------------------------------------------------------------
140
141AudioFlinger::AudioFlinger()
142 : BnAudioFlinger(),
Dima Zavinfce7a472011-04-19 22:30:36 -0700143 mAudioHardwareDev(0), mMasterVolume(1.0f), mMasterMute(false), mNextUniqueId(1)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700144{
Dima Zavinfce7a472011-04-19 22:30:36 -0700145 const hw_module_t *module;
146 int rc;
147 char mod_name[PATH_MAX];
148
Eric Laurent93575202011-01-18 18:39:02 -0800149 Mutex::Autolock _l(mLock);
150
Mathias Agopian65ab4712010-07-14 17:59:35 -0700151 mHardwareStatus = AUDIO_HW_IDLE;
152
Dima Zavinfce7a472011-04-19 22:30:36 -0700153 /* get the audio hw module and create an audio_hw device */
154 snprintf(mod_name, PATH_MAX, "%s.%s", AUDIO_HARDWARE_MODULE_ID, "primary");
155 rc = hw_get_module(mod_name, &module);
156 if (rc)
157 return;
158
159 rc = audio_hw_device_open(module, &mAudioHardwareDev);
160 LOGE_IF(rc, "couldn't open audio hw device (%s)", strerror(-rc));
161 if (rc)
162 return;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700163
164 mHardwareStatus = AUDIO_HW_INIT;
Dima Zavinfce7a472011-04-19 22:30:36 -0700165
166 rc = mAudioHardwareDev->init_check(mAudioHardwareDev);
167 if (rc == 0) {
Eric Laurent93575202011-01-18 18:39:02 -0800168 AutoMutex lock(mHardwareLock);
Dima Zavinfce7a472011-04-19 22:30:36 -0700169 mMode = AUDIO_MODE_NORMAL;
Eric Laurent93575202011-01-18 18:39:02 -0800170 mHardwareStatus = AUDIO_HW_SET_MODE;
Dima Zavinfce7a472011-04-19 22:30:36 -0700171 mAudioHardwareDev->set_mode(mAudioHardwareDev, mMode);
Eric Laurent93575202011-01-18 18:39:02 -0800172 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
Dima Zavinfce7a472011-04-19 22:30:36 -0700173 mAudioHardwareDev->set_master_volume(mAudioHardwareDev, 1.0f);
Eric Laurent93575202011-01-18 18:39:02 -0800174 mHardwareStatus = AUDIO_HW_IDLE;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700175 } else {
176 LOGE("Couldn't even initialize the stubbed audio hardware!");
177 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700178}
179
180AudioFlinger::~AudioFlinger()
181{
182 while (!mRecordThreads.isEmpty()) {
183 // closeInput() will remove first entry from mRecordThreads
184 closeInput(mRecordThreads.keyAt(0));
185 }
186 while (!mPlaybackThreads.isEmpty()) {
187 // closeOutput() will remove first entry from mPlaybackThreads
188 closeOutput(mPlaybackThreads.keyAt(0));
189 }
Dima Zavinfce7a472011-04-19 22:30:36 -0700190 if (mAudioHardwareDev) {
191 audio_hw_device_close(mAudioHardwareDev);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700192 }
193}
194
195
196
197status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args)
198{
199 const size_t SIZE = 256;
200 char buffer[SIZE];
201 String8 result;
202
203 result.append("Clients:\n");
204 for (size_t i = 0; i < mClients.size(); ++i) {
205 wp<Client> wClient = mClients.valueAt(i);
206 if (wClient != 0) {
207 sp<Client> client = wClient.promote();
208 if (client != 0) {
209 snprintf(buffer, SIZE, " pid: %d\n", client->pid());
210 result.append(buffer);
211 }
212 }
213 }
214 write(fd, result.string(), result.size());
215 return NO_ERROR;
216}
217
218
219status_t AudioFlinger::dumpInternals(int fd, const Vector<String16>& args)
220{
221 const size_t SIZE = 256;
222 char buffer[SIZE];
223 String8 result;
224 int hardwareStatus = mHardwareStatus;
225
226 snprintf(buffer, SIZE, "Hardware status: %d\n", hardwareStatus);
227 result.append(buffer);
228 write(fd, result.string(), result.size());
229 return NO_ERROR;
230}
231
232status_t AudioFlinger::dumpPermissionDenial(int fd, const Vector<String16>& args)
233{
234 const size_t SIZE = 256;
235 char buffer[SIZE];
236 String8 result;
237 snprintf(buffer, SIZE, "Permission Denial: "
238 "can't dump AudioFlinger from pid=%d, uid=%d\n",
239 IPCThreadState::self()->getCallingPid(),
240 IPCThreadState::self()->getCallingUid());
241 result.append(buffer);
242 write(fd, result.string(), result.size());
243 return NO_ERROR;
244}
245
246static bool tryLock(Mutex& mutex)
247{
248 bool locked = false;
249 for (int i = 0; i < kDumpLockRetries; ++i) {
250 if (mutex.tryLock() == NO_ERROR) {
251 locked = true;
252 break;
253 }
254 usleep(kDumpLockSleep);
255 }
256 return locked;
257}
258
259status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
260{
261 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
262 dumpPermissionDenial(fd, args);
263 } else {
264 // get state of hardware lock
265 bool hardwareLocked = tryLock(mHardwareLock);
266 if (!hardwareLocked) {
267 String8 result(kHardwareLockedString);
268 write(fd, result.string(), result.size());
269 } else {
270 mHardwareLock.unlock();
271 }
272
273 bool locked = tryLock(mLock);
274
275 // failed to lock - AudioFlinger is probably deadlocked
276 if (!locked) {
277 String8 result(kDeadlockedString);
278 write(fd, result.string(), result.size());
279 }
280
281 dumpClients(fd, args);
282 dumpInternals(fd, args);
283
284 // dump playback threads
285 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
286 mPlaybackThreads.valueAt(i)->dump(fd, args);
287 }
288
289 // dump record threads
290 for (size_t i = 0; i < mRecordThreads.size(); i++) {
291 mRecordThreads.valueAt(i)->dump(fd, args);
292 }
293
Dima Zavinfce7a472011-04-19 22:30:36 -0700294 if (mAudioHardwareDev) {
295 mAudioHardwareDev->dump(mAudioHardwareDev, fd);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700296 }
297 if (locked) mLock.unlock();
298 }
299 return NO_ERROR;
300}
301
302
303// IAudioFlinger interface
304
305
306sp<IAudioTrack> AudioFlinger::createTrack(
307 pid_t pid,
308 int streamType,
309 uint32_t sampleRate,
310 int format,
311 int channelCount,
312 int frameCount,
313 uint32_t flags,
314 const sp<IMemory>& sharedBuffer,
315 int output,
316 int *sessionId,
317 status_t *status)
318{
319 sp<PlaybackThread::Track> track;
320 sp<TrackHandle> trackHandle;
321 sp<Client> client;
322 wp<Client> wclient;
323 status_t lStatus;
324 int lSessionId;
325
Dima Zavinfce7a472011-04-19 22:30:36 -0700326 if (streamType >= AUDIO_STREAM_CNT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700327 LOGE("invalid stream type");
328 lStatus = BAD_VALUE;
329 goto Exit;
330 }
331
332 {
333 Mutex::Autolock _l(mLock);
334 PlaybackThread *thread = checkPlaybackThread_l(output);
Eric Laurent39e94f82010-07-28 01:32:47 -0700335 PlaybackThread *effectThread = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700336 if (thread == NULL) {
337 LOGE("unknown output thread");
338 lStatus = BAD_VALUE;
339 goto Exit;
340 }
341
342 wclient = mClients.valueFor(pid);
343
344 if (wclient != NULL) {
345 client = wclient.promote();
346 } else {
347 client = new Client(this, pid);
348 mClients.add(pid, client);
349 }
350
Mathias Agopian65ab4712010-07-14 17:59:35 -0700351 LOGV("createTrack() sessionId: %d", (sessionId == NULL) ? -2 : *sessionId);
Dima Zavinfce7a472011-04-19 22:30:36 -0700352 if (sessionId != NULL && *sessionId != AUDIO_SESSION_OUTPUT_MIX) {
Eric Laurentde070132010-07-13 04:45:46 -0700353 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurent39e94f82010-07-28 01:32:47 -0700354 sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
355 if (mPlaybackThreads.keyAt(i) != output) {
356 // prevent same audio session on different output threads
357 uint32_t sessions = t->hasAudioSession(*sessionId);
358 if (sessions & PlaybackThread::TRACK_SESSION) {
359 lStatus = BAD_VALUE;
360 goto Exit;
361 }
362 // check if an effect with same session ID is waiting for a track to be created
363 if (sessions & PlaybackThread::EFFECT_SESSION) {
364 effectThread = t.get();
365 }
Eric Laurentde070132010-07-13 04:45:46 -0700366 }
367 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700368 lSessionId = *sessionId;
369 } else {
Eric Laurentde070132010-07-13 04:45:46 -0700370 // if no audio session id is provided, create one here
Eric Laurentf5aafb22010-11-18 08:40:16 -0800371 lSessionId = nextUniqueId_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700372 if (sessionId != NULL) {
373 *sessionId = lSessionId;
374 }
375 }
376 LOGV("createTrack() lSessionId: %d", lSessionId);
377
378 track = thread->createTrack_l(client, streamType, sampleRate, format,
379 channelCount, frameCount, sharedBuffer, lSessionId, &lStatus);
Eric Laurent39e94f82010-07-28 01:32:47 -0700380
381 // move effect chain to this output thread if an effect on same session was waiting
382 // for a track to be created
383 if (lStatus == NO_ERROR && effectThread != NULL) {
384 Mutex::Autolock _dl(thread->mLock);
385 Mutex::Autolock _sl(effectThread->mLock);
386 moveEffectChain_l(lSessionId, effectThread, thread, true);
387 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700388 }
389 if (lStatus == NO_ERROR) {
390 trackHandle = new TrackHandle(track);
391 } else {
392 // remove local strong reference to Client before deleting the Track so that the Client
393 // destructor is called by the TrackBase destructor with mLock held
394 client.clear();
395 track.clear();
396 }
397
398Exit:
399 if(status) {
400 *status = lStatus;
401 }
402 return trackHandle;
403}
404
405uint32_t AudioFlinger::sampleRate(int output) const
406{
407 Mutex::Autolock _l(mLock);
408 PlaybackThread *thread = checkPlaybackThread_l(output);
409 if (thread == NULL) {
410 LOGW("sampleRate() unknown thread %d", output);
411 return 0;
412 }
413 return thread->sampleRate();
414}
415
416int AudioFlinger::channelCount(int output) const
417{
418 Mutex::Autolock _l(mLock);
419 PlaybackThread *thread = checkPlaybackThread_l(output);
420 if (thread == NULL) {
421 LOGW("channelCount() unknown thread %d", output);
422 return 0;
423 }
424 return thread->channelCount();
425}
426
427int AudioFlinger::format(int output) const
428{
429 Mutex::Autolock _l(mLock);
430 PlaybackThread *thread = checkPlaybackThread_l(output);
431 if (thread == NULL) {
432 LOGW("format() unknown thread %d", output);
433 return 0;
434 }
435 return thread->format();
436}
437
438size_t AudioFlinger::frameCount(int output) const
439{
440 Mutex::Autolock _l(mLock);
441 PlaybackThread *thread = checkPlaybackThread_l(output);
442 if (thread == NULL) {
443 LOGW("frameCount() unknown thread %d", output);
444 return 0;
445 }
446 return thread->frameCount();
447}
448
449uint32_t AudioFlinger::latency(int output) const
450{
451 Mutex::Autolock _l(mLock);
452 PlaybackThread *thread = checkPlaybackThread_l(output);
453 if (thread == NULL) {
454 LOGW("latency() unknown thread %d", output);
455 return 0;
456 }
457 return thread->latency();
458}
459
460status_t AudioFlinger::setMasterVolume(float value)
461{
462 // check calling permissions
463 if (!settingsAllowed()) {
464 return PERMISSION_DENIED;
465 }
466
467 // when hw supports master volume, don't scale in sw mixer
Eric Laurent93575202011-01-18 18:39:02 -0800468 { // scope for the lock
469 AutoMutex lock(mHardwareLock);
470 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
Dima Zavinfce7a472011-04-19 22:30:36 -0700471 if (mAudioHardwareDev->set_master_volume(mAudioHardwareDev, value) == NO_ERROR) {
Eric Laurent93575202011-01-18 18:39:02 -0800472 value = 1.0f;
473 }
474 mHardwareStatus = AUDIO_HW_IDLE;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700475 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700476
Eric Laurent93575202011-01-18 18:39:02 -0800477 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700478 mMasterVolume = value;
479 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
480 mPlaybackThreads.valueAt(i)->setMasterVolume(value);
481
482 return NO_ERROR;
483}
484
485status_t AudioFlinger::setMode(int mode)
486{
487 status_t ret;
488
489 // check calling permissions
490 if (!settingsAllowed()) {
491 return PERMISSION_DENIED;
492 }
Dima Zavinfce7a472011-04-19 22:30:36 -0700493 if ((mode < 0) || (mode >= AUDIO_MODE_CNT)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700494 LOGW("Illegal value: setMode(%d)", mode);
495 return BAD_VALUE;
496 }
497
498 { // scope for the lock
499 AutoMutex lock(mHardwareLock);
500 mHardwareStatus = AUDIO_HW_SET_MODE;
Dima Zavinfce7a472011-04-19 22:30:36 -0700501 ret = mAudioHardwareDev->set_mode(mAudioHardwareDev, mode);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700502 mHardwareStatus = AUDIO_HW_IDLE;
503 }
504
505 if (NO_ERROR == ret) {
506 Mutex::Autolock _l(mLock);
507 mMode = mode;
508 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
509 mPlaybackThreads.valueAt(i)->setMode(mode);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700510 }
511
512 return ret;
513}
514
515status_t AudioFlinger::setMicMute(bool state)
516{
517 // check calling permissions
518 if (!settingsAllowed()) {
519 return PERMISSION_DENIED;
520 }
521
522 AutoMutex lock(mHardwareLock);
523 mHardwareStatus = AUDIO_HW_SET_MIC_MUTE;
Dima Zavinfce7a472011-04-19 22:30:36 -0700524 status_t ret = mAudioHardwareDev->set_mic_mute(mAudioHardwareDev, state);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700525 mHardwareStatus = AUDIO_HW_IDLE;
526 return ret;
527}
528
529bool AudioFlinger::getMicMute() const
530{
Dima Zavinfce7a472011-04-19 22:30:36 -0700531 bool state = AUDIO_MODE_INVALID;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700532 mHardwareStatus = AUDIO_HW_GET_MIC_MUTE;
Dima Zavinfce7a472011-04-19 22:30:36 -0700533 mAudioHardwareDev->get_mic_mute(mAudioHardwareDev, &state);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700534 mHardwareStatus = AUDIO_HW_IDLE;
535 return state;
536}
537
538status_t AudioFlinger::setMasterMute(bool muted)
539{
540 // check calling permissions
541 if (!settingsAllowed()) {
542 return PERMISSION_DENIED;
543 }
544
Eric Laurent93575202011-01-18 18:39:02 -0800545 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700546 mMasterMute = muted;
547 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
548 mPlaybackThreads.valueAt(i)->setMasterMute(muted);
549
550 return NO_ERROR;
551}
552
553float AudioFlinger::masterVolume() const
554{
555 return mMasterVolume;
556}
557
558bool AudioFlinger::masterMute() const
559{
560 return mMasterMute;
561}
562
563status_t AudioFlinger::setStreamVolume(int stream, float value, int output)
564{
565 // check calling permissions
566 if (!settingsAllowed()) {
567 return PERMISSION_DENIED;
568 }
569
Dima Zavinfce7a472011-04-19 22:30:36 -0700570 if (stream < 0 || uint32_t(stream) >= AUDIO_STREAM_CNT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700571 return BAD_VALUE;
572 }
573
574 AutoMutex lock(mLock);
575 PlaybackThread *thread = NULL;
576 if (output) {
577 thread = checkPlaybackThread_l(output);
578 if (thread == NULL) {
579 return BAD_VALUE;
580 }
581 }
582
583 mStreamTypes[stream].volume = value;
584
585 if (thread == NULL) {
586 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++) {
587 mPlaybackThreads.valueAt(i)->setStreamVolume(stream, value);
588 }
589 } else {
590 thread->setStreamVolume(stream, value);
591 }
592
593 return NO_ERROR;
594}
595
596status_t AudioFlinger::setStreamMute(int stream, bool muted)
597{
598 // check calling permissions
599 if (!settingsAllowed()) {
600 return PERMISSION_DENIED;
601 }
602
Dima Zavinfce7a472011-04-19 22:30:36 -0700603 if (stream < 0 || uint32_t(stream) >= AUDIO_STREAM_CNT ||
604 uint32_t(stream) == AUDIO_STREAM_ENFORCED_AUDIBLE) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700605 return BAD_VALUE;
606 }
607
Eric Laurent93575202011-01-18 18:39:02 -0800608 AutoMutex lock(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700609 mStreamTypes[stream].mute = muted;
610 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
611 mPlaybackThreads.valueAt(i)->setStreamMute(stream, muted);
612
613 return NO_ERROR;
614}
615
616float AudioFlinger::streamVolume(int stream, int output) const
617{
Dima Zavinfce7a472011-04-19 22:30:36 -0700618 if (stream < 0 || uint32_t(stream) >= AUDIO_STREAM_CNT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700619 return 0.0f;
620 }
621
622 AutoMutex lock(mLock);
623 float volume;
624 if (output) {
625 PlaybackThread *thread = checkPlaybackThread_l(output);
626 if (thread == NULL) {
627 return 0.0f;
628 }
629 volume = thread->streamVolume(stream);
630 } else {
631 volume = mStreamTypes[stream].volume;
632 }
633
634 return volume;
635}
636
637bool AudioFlinger::streamMute(int stream) const
638{
Dima Zavinfce7a472011-04-19 22:30:36 -0700639 if (stream < 0 || stream >= (int)AUDIO_STREAM_CNT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700640 return true;
641 }
642
643 return mStreamTypes[stream].mute;
644}
645
Mathias Agopian65ab4712010-07-14 17:59:35 -0700646status_t AudioFlinger::setParameters(int ioHandle, const String8& keyValuePairs)
647{
648 status_t result;
649
650 LOGV("setParameters(): io %d, keyvalue %s, tid %d, calling tid %d",
651 ioHandle, keyValuePairs.string(), gettid(), IPCThreadState::self()->getCallingPid());
652 // check calling permissions
653 if (!settingsAllowed()) {
654 return PERMISSION_DENIED;
655 }
656
Mathias Agopian65ab4712010-07-14 17:59:35 -0700657 // ioHandle == 0 means the parameters are global to the audio hardware interface
658 if (ioHandle == 0) {
659 AutoMutex lock(mHardwareLock);
660 mHardwareStatus = AUDIO_SET_PARAMETER;
Dima Zavinfce7a472011-04-19 22:30:36 -0700661 result = mAudioHardwareDev->set_parameters(mAudioHardwareDev, keyValuePairs.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -0700662 mHardwareStatus = AUDIO_HW_IDLE;
663 return result;
664 }
665
666 // hold a strong ref on thread in case closeOutput() or closeInput() is called
667 // and the thread is exited once the lock is released
668 sp<ThreadBase> thread;
669 {
670 Mutex::Autolock _l(mLock);
671 thread = checkPlaybackThread_l(ioHandle);
672 if (thread == NULL) {
673 thread = checkRecordThread_l(ioHandle);
674 }
675 }
676 if (thread != NULL) {
677 result = thread->setParameters(keyValuePairs);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700678 return result;
679 }
680 return BAD_VALUE;
681}
682
683String8 AudioFlinger::getParameters(int ioHandle, const String8& keys)
684{
685// LOGV("getParameters() io %d, keys %s, tid %d, calling tid %d",
686// ioHandle, keys.string(), gettid(), IPCThreadState::self()->getCallingPid());
687
688 if (ioHandle == 0) {
Dima Zavinfce7a472011-04-19 22:30:36 -0700689 char *s;
690 String8 out_s8;
691
692 s = mAudioHardwareDev->get_parameters(mAudioHardwareDev, keys.string());
693 out_s8 = String8(s);
694 free(s);
695 return out_s8;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700696 }
697
698 Mutex::Autolock _l(mLock);
699
700 PlaybackThread *playbackThread = checkPlaybackThread_l(ioHandle);
701 if (playbackThread != NULL) {
702 return playbackThread->getParameters(keys);
703 }
704 RecordThread *recordThread = checkRecordThread_l(ioHandle);
705 if (recordThread != NULL) {
706 return recordThread->getParameters(keys);
707 }
708 return String8("");
709}
710
711size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
712{
Dima Zavinfce7a472011-04-19 22:30:36 -0700713 return mAudioHardwareDev->get_input_buffer_size(mAudioHardwareDev, sampleRate, format, channelCount);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700714}
715
716unsigned int AudioFlinger::getInputFramesLost(int ioHandle)
717{
718 if (ioHandle == 0) {
719 return 0;
720 }
721
722 Mutex::Autolock _l(mLock);
723
724 RecordThread *recordThread = checkRecordThread_l(ioHandle);
725 if (recordThread != NULL) {
726 return recordThread->getInputFramesLost();
727 }
728 return 0;
729}
730
731status_t AudioFlinger::setVoiceVolume(float value)
732{
733 // check calling permissions
734 if (!settingsAllowed()) {
735 return PERMISSION_DENIED;
736 }
737
738 AutoMutex lock(mHardwareLock);
739 mHardwareStatus = AUDIO_SET_VOICE_VOLUME;
Dima Zavinfce7a472011-04-19 22:30:36 -0700740 status_t ret = mAudioHardwareDev->set_voice_volume(mAudioHardwareDev, value);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700741 mHardwareStatus = AUDIO_HW_IDLE;
742
743 return ret;
744}
745
746status_t AudioFlinger::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int output)
747{
748 status_t status;
749
750 Mutex::Autolock _l(mLock);
751
752 PlaybackThread *playbackThread = checkPlaybackThread_l(output);
753 if (playbackThread != NULL) {
754 return playbackThread->getRenderPosition(halFrames, dspFrames);
755 }
756
757 return BAD_VALUE;
758}
759
760void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
761{
762
763 Mutex::Autolock _l(mLock);
764
765 int pid = IPCThreadState::self()->getCallingPid();
766 if (mNotificationClients.indexOfKey(pid) < 0) {
767 sp<NotificationClient> notificationClient = new NotificationClient(this,
768 client,
769 pid);
770 LOGV("registerClient() client %p, pid %d", notificationClient.get(), pid);
771
772 mNotificationClients.add(pid, notificationClient);
773
774 sp<IBinder> binder = client->asBinder();
775 binder->linkToDeath(notificationClient);
776
777 // the config change is always sent from playback or record threads to avoid deadlock
778 // with AudioSystem::gLock
779 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
780 mPlaybackThreads.valueAt(i)->sendConfigEvent(AudioSystem::OUTPUT_OPENED);
781 }
782
783 for (size_t i = 0; i < mRecordThreads.size(); i++) {
784 mRecordThreads.valueAt(i)->sendConfigEvent(AudioSystem::INPUT_OPENED);
785 }
786 }
787}
788
789void AudioFlinger::removeNotificationClient(pid_t pid)
790{
791 Mutex::Autolock _l(mLock);
792
793 int index = mNotificationClients.indexOfKey(pid);
794 if (index >= 0) {
795 sp <NotificationClient> client = mNotificationClients.valueFor(pid);
796 LOGV("removeNotificationClient() %p, pid %d", client.get(), pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700797 mNotificationClients.removeItem(pid);
798 }
799}
800
801// audioConfigChanged_l() must be called with AudioFlinger::mLock held
802void AudioFlinger::audioConfigChanged_l(int event, int ioHandle, void *param2)
803{
804 size_t size = mNotificationClients.size();
805 for (size_t i = 0; i < size; i++) {
806 mNotificationClients.valueAt(i)->client()->ioConfigChanged(event, ioHandle, param2);
807 }
808}
809
810// removeClient_l() must be called with AudioFlinger::mLock held
811void AudioFlinger::removeClient_l(pid_t pid)
812{
813 LOGV("removeClient_l() pid %d, tid %d, calling tid %d", pid, gettid(), IPCThreadState::self()->getCallingPid());
814 mClients.removeItem(pid);
815}
816
817
818// ----------------------------------------------------------------------------
819
820AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, int id)
821 : Thread(false),
822 mAudioFlinger(audioFlinger), mSampleRate(0), mFrameCount(0), mChannelCount(0),
823 mFrameSize(1), mFormat(0), mStandby(false), mId(id), mExiting(false)
824{
825}
826
827AudioFlinger::ThreadBase::~ThreadBase()
828{
829 mParamCond.broadcast();
830 mNewParameters.clear();
831}
832
833void AudioFlinger::ThreadBase::exit()
834{
835 // keep a strong ref on ourself so that we wont get
836 // destroyed in the middle of requestExitAndWait()
837 sp <ThreadBase> strongMe = this;
838
839 LOGV("ThreadBase::exit");
840 {
841 AutoMutex lock(&mLock);
842 mExiting = true;
843 requestExit();
844 mWaitWorkCV.signal();
845 }
846 requestExitAndWait();
847}
848
849uint32_t AudioFlinger::ThreadBase::sampleRate() const
850{
851 return mSampleRate;
852}
853
854int AudioFlinger::ThreadBase::channelCount() const
855{
856 return (int)mChannelCount;
857}
858
859int AudioFlinger::ThreadBase::format() const
860{
861 return mFormat;
862}
863
864size_t AudioFlinger::ThreadBase::frameCount() const
865{
866 return mFrameCount;
867}
868
869status_t AudioFlinger::ThreadBase::setParameters(const String8& keyValuePairs)
870{
871 status_t status;
872
873 LOGV("ThreadBase::setParameters() %s", keyValuePairs.string());
874 Mutex::Autolock _l(mLock);
875
876 mNewParameters.add(keyValuePairs);
877 mWaitWorkCV.signal();
878 // wait condition with timeout in case the thread loop has exited
879 // before the request could be processed
880 if (mParamCond.waitRelative(mLock, seconds(2)) == NO_ERROR) {
881 status = mParamStatus;
882 mWaitWorkCV.signal();
883 } else {
884 status = TIMED_OUT;
885 }
886 return status;
887}
888
889void AudioFlinger::ThreadBase::sendConfigEvent(int event, int param)
890{
891 Mutex::Autolock _l(mLock);
892 sendConfigEvent_l(event, param);
893}
894
895// sendConfigEvent_l() must be called with ThreadBase::mLock held
896void AudioFlinger::ThreadBase::sendConfigEvent_l(int event, int param)
897{
898 ConfigEvent *configEvent = new ConfigEvent();
899 configEvent->mEvent = event;
900 configEvent->mParam = param;
901 mConfigEvents.add(configEvent);
902 LOGV("sendConfigEvent() num events %d event %d, param %d", mConfigEvents.size(), event, param);
903 mWaitWorkCV.signal();
904}
905
906void AudioFlinger::ThreadBase::processConfigEvents()
907{
908 mLock.lock();
909 while(!mConfigEvents.isEmpty()) {
910 LOGV("processConfigEvents() remaining events %d", mConfigEvents.size());
911 ConfigEvent *configEvent = mConfigEvents[0];
912 mConfigEvents.removeAt(0);
913 // release mLock before locking AudioFlinger mLock: lock order is always
914 // AudioFlinger then ThreadBase to avoid cross deadlock
915 mLock.unlock();
916 mAudioFlinger->mLock.lock();
917 audioConfigChanged_l(configEvent->mEvent, configEvent->mParam);
918 mAudioFlinger->mLock.unlock();
919 delete configEvent;
920 mLock.lock();
921 }
922 mLock.unlock();
923}
924
925status_t AudioFlinger::ThreadBase::dumpBase(int fd, const Vector<String16>& args)
926{
927 const size_t SIZE = 256;
928 char buffer[SIZE];
929 String8 result;
930
931 bool locked = tryLock(mLock);
932 if (!locked) {
933 snprintf(buffer, SIZE, "thread %p maybe dead locked\n", this);
934 write(fd, buffer, strlen(buffer));
935 }
936
937 snprintf(buffer, SIZE, "standby: %d\n", mStandby);
938 result.append(buffer);
939 snprintf(buffer, SIZE, "Sample rate: %d\n", mSampleRate);
940 result.append(buffer);
941 snprintf(buffer, SIZE, "Frame count: %d\n", mFrameCount);
942 result.append(buffer);
943 snprintf(buffer, SIZE, "Channel Count: %d\n", mChannelCount);
944 result.append(buffer);
945 snprintf(buffer, SIZE, "Format: %d\n", mFormat);
946 result.append(buffer);
947 snprintf(buffer, SIZE, "Frame size: %d\n", mFrameSize);
948 result.append(buffer);
949
950 snprintf(buffer, SIZE, "\nPending setParameters commands: \n");
951 result.append(buffer);
952 result.append(" Index Command");
953 for (size_t i = 0; i < mNewParameters.size(); ++i) {
954 snprintf(buffer, SIZE, "\n %02d ", i);
955 result.append(buffer);
956 result.append(mNewParameters[i]);
957 }
958
959 snprintf(buffer, SIZE, "\n\nPending config events: \n");
960 result.append(buffer);
961 snprintf(buffer, SIZE, " Index event param\n");
962 result.append(buffer);
963 for (size_t i = 0; i < mConfigEvents.size(); i++) {
964 snprintf(buffer, SIZE, " %02d %02d %d\n", i, mConfigEvents[i]->mEvent, mConfigEvents[i]->mParam);
965 result.append(buffer);
966 }
967 result.append("\n");
968
969 write(fd, result.string(), result.size());
970
971 if (locked) {
972 mLock.unlock();
973 }
974 return NO_ERROR;
975}
976
977
978// ----------------------------------------------------------------------------
979
Dima Zavinfce7a472011-04-19 22:30:36 -0700980AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger, struct audio_stream_out* output, int id, uint32_t device)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700981 : ThreadBase(audioFlinger, id),
982 mMixBuffer(0), mSuspended(0), mBytesWritten(0), mOutput(output),
983 mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false),
984 mDevice(device)
985{
986 readOutputParameters();
987
988 mMasterVolume = mAudioFlinger->masterVolume();
989 mMasterMute = mAudioFlinger->masterMute();
990
Dima Zavinfce7a472011-04-19 22:30:36 -0700991 for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700992 mStreamTypes[stream].volume = mAudioFlinger->streamVolumeInternal(stream);
993 mStreamTypes[stream].mute = mAudioFlinger->streamMute(stream);
994 }
995}
996
997AudioFlinger::PlaybackThread::~PlaybackThread()
998{
999 delete [] mMixBuffer;
1000}
1001
1002status_t AudioFlinger::PlaybackThread::dump(int fd, const Vector<String16>& args)
1003{
1004 dumpInternals(fd, args);
1005 dumpTracks(fd, args);
1006 dumpEffectChains(fd, args);
1007 return NO_ERROR;
1008}
1009
1010status_t AudioFlinger::PlaybackThread::dumpTracks(int fd, const Vector<String16>& args)
1011{
1012 const size_t SIZE = 256;
1013 char buffer[SIZE];
1014 String8 result;
1015
1016 snprintf(buffer, SIZE, "Output thread %p tracks\n", this);
1017 result.append(buffer);
1018 result.append(" Name Clien Typ Fmt Chn Session Buf S M F SRate LeftV RighV Serv User Main buf Aux Buf\n");
1019 for (size_t i = 0; i < mTracks.size(); ++i) {
1020 sp<Track> track = mTracks[i];
1021 if (track != 0) {
1022 track->dump(buffer, SIZE);
1023 result.append(buffer);
1024 }
1025 }
1026
1027 snprintf(buffer, SIZE, "Output thread %p active tracks\n", this);
1028 result.append(buffer);
1029 result.append(" Name Clien Typ Fmt Chn Session Buf S M F SRate LeftV RighV Serv User Main buf Aux Buf\n");
1030 for (size_t i = 0; i < mActiveTracks.size(); ++i) {
1031 wp<Track> wTrack = mActiveTracks[i];
1032 if (wTrack != 0) {
1033 sp<Track> track = wTrack.promote();
1034 if (track != 0) {
1035 track->dump(buffer, SIZE);
1036 result.append(buffer);
1037 }
1038 }
1039 }
1040 write(fd, result.string(), result.size());
1041 return NO_ERROR;
1042}
1043
1044status_t AudioFlinger::PlaybackThread::dumpEffectChains(int fd, const Vector<String16>& args)
1045{
1046 const size_t SIZE = 256;
1047 char buffer[SIZE];
1048 String8 result;
1049
1050 snprintf(buffer, SIZE, "\n- %d Effect Chains:\n", mEffectChains.size());
1051 write(fd, buffer, strlen(buffer));
1052
1053 for (size_t i = 0; i < mEffectChains.size(); ++i) {
1054 sp<EffectChain> chain = mEffectChains[i];
1055 if (chain != 0) {
1056 chain->dump(fd, args);
1057 }
1058 }
1059 return NO_ERROR;
1060}
1061
1062status_t AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String16>& args)
1063{
1064 const size_t SIZE = 256;
1065 char buffer[SIZE];
1066 String8 result;
1067
1068 snprintf(buffer, SIZE, "\nOutput thread %p internals\n", this);
1069 result.append(buffer);
1070 snprintf(buffer, SIZE, "last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime));
1071 result.append(buffer);
1072 snprintf(buffer, SIZE, "total writes: %d\n", mNumWrites);
1073 result.append(buffer);
1074 snprintf(buffer, SIZE, "delayed writes: %d\n", mNumDelayedWrites);
1075 result.append(buffer);
1076 snprintf(buffer, SIZE, "blocked in write: %d\n", mInWrite);
1077 result.append(buffer);
1078 snprintf(buffer, SIZE, "suspend count: %d\n", mSuspended);
1079 result.append(buffer);
1080 snprintf(buffer, SIZE, "mix buffer : %p\n", mMixBuffer);
1081 result.append(buffer);
1082 write(fd, result.string(), result.size());
1083
1084 dumpBase(fd, args);
1085
1086 return NO_ERROR;
1087}
1088
1089// Thread virtuals
1090status_t AudioFlinger::PlaybackThread::readyToRun()
1091{
1092 if (mSampleRate == 0) {
1093 LOGE("No working audio driver found.");
1094 return NO_INIT;
1095 }
1096 LOGI("AudioFlinger's thread %p ready to run", this);
1097 return NO_ERROR;
1098}
1099
1100void AudioFlinger::PlaybackThread::onFirstRef()
1101{
1102 const size_t SIZE = 256;
1103 char buffer[SIZE];
1104
1105 snprintf(buffer, SIZE, "Playback Thread %p", this);
1106
1107 run(buffer, ANDROID_PRIORITY_URGENT_AUDIO);
1108}
1109
1110// PlaybackThread::createTrack_l() must be called with AudioFlinger::mLock held
1111sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrack_l(
1112 const sp<AudioFlinger::Client>& client,
1113 int streamType,
1114 uint32_t sampleRate,
1115 int format,
1116 int channelCount,
1117 int frameCount,
1118 const sp<IMemory>& sharedBuffer,
1119 int sessionId,
1120 status_t *status)
1121{
1122 sp<Track> track;
1123 status_t lStatus;
1124
1125 if (mType == DIRECT) {
1126 if (sampleRate != mSampleRate || format != mFormat || channelCount != (int)mChannelCount) {
1127 LOGE("createTrack_l() Bad parameter: sampleRate %d format %d, channelCount %d for output %p",
1128 sampleRate, format, channelCount, mOutput);
1129 lStatus = BAD_VALUE;
1130 goto Exit;
1131 }
1132 } else {
1133 // Resampler implementation limits input sampling rate to 2 x output sampling rate.
1134 if (sampleRate > mSampleRate*2) {
1135 LOGE("Sample rate out of range: %d mSampleRate %d", sampleRate, mSampleRate);
1136 lStatus = BAD_VALUE;
1137 goto Exit;
1138 }
1139 }
1140
1141 if (mOutput == 0) {
1142 LOGE("Audio driver not initialized.");
1143 lStatus = NO_INIT;
1144 goto Exit;
1145 }
1146
1147 { // scope for mLock
1148 Mutex::Autolock _l(mLock);
Eric Laurentde070132010-07-13 04:45:46 -07001149
1150 // all tracks in same audio session must share the same routing strategy otherwise
1151 // conflicts will happen when tracks are moved from one output to another by audio policy
1152 // manager
1153 uint32_t strategy =
Dima Zavinfce7a472011-04-19 22:30:36 -07001154 AudioSystem::getStrategyForStream((audio_stream_type_t)streamType);
Eric Laurentde070132010-07-13 04:45:46 -07001155 for (size_t i = 0; i < mTracks.size(); ++i) {
1156 sp<Track> t = mTracks[i];
1157 if (t != 0) {
1158 if (sessionId == t->sessionId() &&
Dima Zavinfce7a472011-04-19 22:30:36 -07001159 strategy != AudioSystem::getStrategyForStream((audio_stream_type_t)t->type())) {
Eric Laurentde070132010-07-13 04:45:46 -07001160 lStatus = BAD_VALUE;
1161 goto Exit;
1162 }
1163 }
1164 }
1165
Mathias Agopian65ab4712010-07-14 17:59:35 -07001166 track = new Track(this, client, streamType, sampleRate, format,
1167 channelCount, frameCount, sharedBuffer, sessionId);
1168 if (track->getCblk() == NULL || track->name() < 0) {
1169 lStatus = NO_MEMORY;
1170 goto Exit;
1171 }
1172 mTracks.add(track);
1173
1174 sp<EffectChain> chain = getEffectChain_l(sessionId);
1175 if (chain != 0) {
1176 LOGV("createTrack_l() setting main buffer %p", chain->inBuffer());
1177 track->setMainBuffer(chain->inBuffer());
Dima Zavinfce7a472011-04-19 22:30:36 -07001178 chain->setStrategy(AudioSystem::getStrategyForStream((audio_stream_type_t)track->type()));
Mathias Agopian65ab4712010-07-14 17:59:35 -07001179 }
1180 }
1181 lStatus = NO_ERROR;
1182
1183Exit:
1184 if(status) {
1185 *status = lStatus;
1186 }
1187 return track;
1188}
1189
1190uint32_t AudioFlinger::PlaybackThread::latency() const
1191{
1192 if (mOutput) {
Dima Zavinfce7a472011-04-19 22:30:36 -07001193 return mOutput->get_latency(mOutput);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001194 }
1195 else {
1196 return 0;
1197 }
1198}
1199
1200status_t AudioFlinger::PlaybackThread::setMasterVolume(float value)
1201{
Mathias Agopian65ab4712010-07-14 17:59:35 -07001202 mMasterVolume = value;
1203 return NO_ERROR;
1204}
1205
1206status_t AudioFlinger::PlaybackThread::setMasterMute(bool muted)
1207{
Mathias Agopian65ab4712010-07-14 17:59:35 -07001208 mMasterMute = muted;
1209 return NO_ERROR;
1210}
1211
1212float AudioFlinger::PlaybackThread::masterVolume() const
1213{
1214 return mMasterVolume;
1215}
1216
1217bool AudioFlinger::PlaybackThread::masterMute() const
1218{
1219 return mMasterMute;
1220}
1221
1222status_t AudioFlinger::PlaybackThread::setStreamVolume(int stream, float value)
1223{
Mathias Agopian65ab4712010-07-14 17:59:35 -07001224 mStreamTypes[stream].volume = value;
1225 return NO_ERROR;
1226}
1227
1228status_t AudioFlinger::PlaybackThread::setStreamMute(int stream, bool muted)
1229{
Mathias Agopian65ab4712010-07-14 17:59:35 -07001230 mStreamTypes[stream].mute = muted;
1231 return NO_ERROR;
1232}
1233
1234float AudioFlinger::PlaybackThread::streamVolume(int stream) const
1235{
1236 return mStreamTypes[stream].volume;
1237}
1238
1239bool AudioFlinger::PlaybackThread::streamMute(int stream) const
1240{
1241 return mStreamTypes[stream].mute;
1242}
1243
Mathias Agopian65ab4712010-07-14 17:59:35 -07001244// addTrack_l() must be called with ThreadBase::mLock held
1245status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track)
1246{
1247 status_t status = ALREADY_EXISTS;
1248
1249 // set retry count for buffer fill
1250 track->mRetryCount = kMaxTrackStartupRetries;
1251 if (mActiveTracks.indexOf(track) < 0) {
1252 // the track is newly added, make sure it fills up all its
1253 // buffers before playing. This is to ensure the client will
1254 // effectively get the latency it requested.
1255 track->mFillingUpStatus = Track::FS_FILLING;
1256 track->mResetDone = false;
1257 mActiveTracks.add(track);
1258 if (track->mainBuffer() != mMixBuffer) {
1259 sp<EffectChain> chain = getEffectChain_l(track->sessionId());
1260 if (chain != 0) {
1261 LOGV("addTrack_l() starting track on chain %p for session %d", chain.get(), track->sessionId());
1262 chain->startTrack();
1263 }
1264 }
1265
1266 status = NO_ERROR;
1267 }
1268
1269 LOGV("mWaitWorkCV.broadcast");
1270 mWaitWorkCV.broadcast();
1271
1272 return status;
1273}
1274
1275// destroyTrack_l() must be called with ThreadBase::mLock held
1276void AudioFlinger::PlaybackThread::destroyTrack_l(const sp<Track>& track)
1277{
1278 track->mState = TrackBase::TERMINATED;
1279 if (mActiveTracks.indexOf(track) < 0) {
1280 mTracks.remove(track);
1281 deleteTrackName_l(track->name());
1282 }
1283}
1284
1285String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys)
1286{
Dima Zavinfce7a472011-04-19 22:30:36 -07001287 String8 out_s8;
1288 char *s;
1289
1290 s = mOutput->common.get_parameters(&mOutput->common, keys.string());
1291 out_s8 = String8(s);
1292 free(s);
1293 return out_s8;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001294}
1295
1296// destroyTrack_l() must be called with AudioFlinger::mLock held
1297void AudioFlinger::PlaybackThread::audioConfigChanged_l(int event, int param) {
1298 AudioSystem::OutputDescriptor desc;
1299 void *param2 = 0;
1300
1301 LOGV("PlaybackThread::audioConfigChanged_l, thread %p, event %d, param %d", this, event, param);
1302
1303 switch (event) {
1304 case AudioSystem::OUTPUT_OPENED:
1305 case AudioSystem::OUTPUT_CONFIG_CHANGED:
1306 desc.channels = mChannels;
1307 desc.samplingRate = mSampleRate;
1308 desc.format = mFormat;
1309 desc.frameCount = mFrameCount;
1310 desc.latency = latency();
1311 param2 = &desc;
1312 break;
1313
1314 case AudioSystem::STREAM_CONFIG_CHANGED:
1315 param2 = &param;
1316 case AudioSystem::OUTPUT_CLOSED:
1317 default:
1318 break;
1319 }
1320 mAudioFlinger->audioConfigChanged_l(event, mId, param2);
1321}
1322
1323void AudioFlinger::PlaybackThread::readOutputParameters()
1324{
Dima Zavinfce7a472011-04-19 22:30:36 -07001325 mSampleRate = mOutput->common.get_sample_rate(&mOutput->common);
1326 mChannels = mOutput->common.get_channels(&mOutput->common);
1327 mChannelCount = (uint16_t)popcount(mChannels);
1328 mFormat = mOutput->common.get_format(&mOutput->common);
1329 mFrameSize = (uint16_t)audio_stream_frame_size(&mOutput->common);
1330 mFrameCount = mOutput->common.get_buffer_size(&mOutput->common) / mFrameSize;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001331
1332 // FIXME - Current mixer implementation only supports stereo output: Always
1333 // Allocate a stereo buffer even if HW output is mono.
1334 if (mMixBuffer != NULL) delete[] mMixBuffer;
1335 mMixBuffer = new int16_t[mFrameCount * 2];
1336 memset(mMixBuffer, 0, mFrameCount * 2 * sizeof(int16_t));
1337
Eric Laurentde070132010-07-13 04:45:46 -07001338 // force reconfiguration of effect chains and engines to take new buffer size and audio
1339 // parameters into account
1340 // Note that mLock is not held when readOutputParameters() is called from the constructor
1341 // but in this case nothing is done below as no audio sessions have effect yet so it doesn't
1342 // matter.
1343 // create a copy of mEffectChains as calling moveEffectChain_l() can reorder some effect chains
1344 Vector< sp<EffectChain> > effectChains = mEffectChains;
1345 for (size_t i = 0; i < effectChains.size(); i ++) {
Eric Laurent39e94f82010-07-28 01:32:47 -07001346 mAudioFlinger->moveEffectChain_l(effectChains[i]->sessionId(), this, this, false);
Eric Laurentde070132010-07-13 04:45:46 -07001347 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001348}
1349
1350status_t AudioFlinger::PlaybackThread::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames)
1351{
1352 if (halFrames == 0 || dspFrames == 0) {
1353 return BAD_VALUE;
1354 }
1355 if (mOutput == 0) {
1356 return INVALID_OPERATION;
1357 }
Dima Zavinfce7a472011-04-19 22:30:36 -07001358 *halFrames = mBytesWritten / audio_stream_frame_size(&mOutput->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001359
Dima Zavinfce7a472011-04-19 22:30:36 -07001360 return mOutput->get_render_position(mOutput, dspFrames);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001361}
1362
Eric Laurent39e94f82010-07-28 01:32:47 -07001363uint32_t AudioFlinger::PlaybackThread::hasAudioSession(int sessionId)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001364{
1365 Mutex::Autolock _l(mLock);
Eric Laurent39e94f82010-07-28 01:32:47 -07001366 uint32_t result = 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001367 if (getEffectChain_l(sessionId) != 0) {
Eric Laurent39e94f82010-07-28 01:32:47 -07001368 result = EFFECT_SESSION;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001369 }
1370
1371 for (size_t i = 0; i < mTracks.size(); ++i) {
1372 sp<Track> track = mTracks[i];
Eric Laurentde070132010-07-13 04:45:46 -07001373 if (sessionId == track->sessionId() &&
1374 !(track->mCblk->flags & CBLK_INVALID_MSK)) {
Eric Laurent39e94f82010-07-28 01:32:47 -07001375 result |= TRACK_SESSION;
1376 break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001377 }
1378 }
1379
Eric Laurent39e94f82010-07-28 01:32:47 -07001380 return result;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001381}
1382
Eric Laurentde070132010-07-13 04:45:46 -07001383uint32_t AudioFlinger::PlaybackThread::getStrategyForSession_l(int sessionId)
1384{
Dima Zavinfce7a472011-04-19 22:30:36 -07001385 // session AUDIO_SESSION_OUTPUT_MIX is placed in same strategy as MUSIC stream so that
Eric Laurentde070132010-07-13 04:45:46 -07001386 // it is moved to correct output by audio policy manager when A2DP is connected or disconnected
Dima Zavinfce7a472011-04-19 22:30:36 -07001387 if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
1388 return AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
Eric Laurentde070132010-07-13 04:45:46 -07001389 }
1390 for (size_t i = 0; i < mTracks.size(); i++) {
1391 sp<Track> track = mTracks[i];
1392 if (sessionId == track->sessionId() &&
1393 !(track->mCblk->flags & CBLK_INVALID_MSK)) {
Dima Zavinfce7a472011-04-19 22:30:36 -07001394 return AudioSystem::getStrategyForStream((audio_stream_type_t) track->type());
Eric Laurentde070132010-07-13 04:45:46 -07001395 }
1396 }
Dima Zavinfce7a472011-04-19 22:30:36 -07001397 return AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
Eric Laurentde070132010-07-13 04:45:46 -07001398}
1399
Mathias Agopian65ab4712010-07-14 17:59:35 -07001400sp<AudioFlinger::EffectChain> AudioFlinger::PlaybackThread::getEffectChain(int sessionId)
1401{
1402 Mutex::Autolock _l(mLock);
1403 return getEffectChain_l(sessionId);
1404}
1405
1406sp<AudioFlinger::EffectChain> AudioFlinger::PlaybackThread::getEffectChain_l(int sessionId)
1407{
1408 sp<EffectChain> chain;
1409
1410 size_t size = mEffectChains.size();
1411 for (size_t i = 0; i < size; i++) {
1412 if (mEffectChains[i]->sessionId() == sessionId) {
1413 chain = mEffectChains[i];
1414 break;
1415 }
1416 }
1417 return chain;
1418}
1419
1420void AudioFlinger::PlaybackThread::setMode(uint32_t mode)
1421{
1422 Mutex::Autolock _l(mLock);
1423 size_t size = mEffectChains.size();
1424 for (size_t i = 0; i < size; i++) {
Eric Laurentcab11242010-07-15 12:50:15 -07001425 mEffectChains[i]->setMode_l(mode);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001426 }
1427}
1428
1429// ----------------------------------------------------------------------------
1430
Dima Zavinfce7a472011-04-19 22:30:36 -07001431AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, struct audio_stream_out* output, int id, uint32_t device)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001432 : PlaybackThread(audioFlinger, output, id, device),
1433 mAudioMixer(0)
1434{
1435 mType = PlaybackThread::MIXER;
1436 mAudioMixer = new AudioMixer(mFrameCount, mSampleRate);
1437
1438 // FIXME - Current mixer implementation only supports stereo output
1439 if (mChannelCount == 1) {
1440 LOGE("Invalid audio hardware channel count");
1441 }
1442}
1443
1444AudioFlinger::MixerThread::~MixerThread()
1445{
1446 delete mAudioMixer;
1447}
1448
1449bool AudioFlinger::MixerThread::threadLoop()
1450{
1451 Vector< sp<Track> > tracksToRemove;
1452 uint32_t mixerStatus = MIXER_IDLE;
1453 nsecs_t standbyTime = systemTime();
1454 size_t mixBufferSize = mFrameCount * mFrameSize;
1455 // FIXME: Relaxed timing because of a certain device that can't meet latency
1456 // Should be reduced to 2x after the vendor fixes the driver issue
1457 nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 3;
1458 nsecs_t lastWarning = 0;
1459 bool longStandbyExit = false;
1460 uint32_t activeSleepTime = activeSleepTimeUs();
1461 uint32_t idleSleepTime = idleSleepTimeUs();
1462 uint32_t sleepTime = idleSleepTime;
1463 Vector< sp<EffectChain> > effectChains;
1464
1465 while (!exitPending())
1466 {
1467 processConfigEvents();
1468
1469 mixerStatus = MIXER_IDLE;
1470 { // scope for mLock
1471
1472 Mutex::Autolock _l(mLock);
1473
1474 if (checkForNewParameters_l()) {
1475 mixBufferSize = mFrameCount * mFrameSize;
1476 // FIXME: Relaxed timing because of a certain device that can't meet latency
1477 // Should be reduced to 2x after the vendor fixes the driver issue
1478 maxPeriod = seconds(mFrameCount) / mSampleRate * 3;
1479 activeSleepTime = activeSleepTimeUs();
1480 idleSleepTime = idleSleepTimeUs();
1481 }
1482
1483 const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
1484
1485 // put audio hardware into standby after short delay
1486 if UNLIKELY((!activeTracks.size() && systemTime() > standbyTime) ||
1487 mSuspended) {
1488 if (!mStandby) {
1489 LOGV("Audio hardware entering standby, mixer %p, mSuspended %d\n", this, mSuspended);
Dima Zavinfce7a472011-04-19 22:30:36 -07001490 mOutput->common.standby(&mOutput->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001491 mStandby = true;
1492 mBytesWritten = 0;
1493 }
1494
1495 if (!activeTracks.size() && mConfigEvents.isEmpty()) {
1496 // we're about to wait, flush the binder command buffer
1497 IPCThreadState::self()->flushCommands();
1498
1499 if (exitPending()) break;
1500
1501 // wait until we have something to do...
1502 LOGV("MixerThread %p TID %d going to sleep\n", this, gettid());
1503 mWaitWorkCV.wait(mLock);
1504 LOGV("MixerThread %p TID %d waking up\n", this, gettid());
1505
1506 if (mMasterMute == false) {
1507 char value[PROPERTY_VALUE_MAX];
1508 property_get("ro.audio.silent", value, "0");
1509 if (atoi(value)) {
1510 LOGD("Silence is golden");
1511 setMasterMute(true);
1512 }
1513 }
1514
1515 standbyTime = systemTime() + kStandbyTimeInNsecs;
1516 sleepTime = idleSleepTime;
1517 continue;
1518 }
1519 }
1520
1521 mixerStatus = prepareTracks_l(activeTracks, &tracksToRemove);
1522
1523 // prevent any changes in effect chain list and in each effect chain
1524 // during mixing and effect process as the audio buffers could be deleted
1525 // or modified if an effect is created or deleted
Eric Laurentde070132010-07-13 04:45:46 -07001526 lockEffectChains_l(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001527 }
1528
1529 if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
1530 // mix buffers...
1531 mAudioMixer->process();
1532 sleepTime = 0;
1533 standbyTime = systemTime() + kStandbyTimeInNsecs;
1534 //TODO: delay standby when effects have a tail
1535 } else {
1536 // If no tracks are ready, sleep once for the duration of an output
1537 // buffer size, then write 0s to the output
1538 if (sleepTime == 0) {
1539 if (mixerStatus == MIXER_TRACKS_ENABLED) {
1540 sleepTime = activeSleepTime;
1541 } else {
1542 sleepTime = idleSleepTime;
1543 }
1544 } else if (mBytesWritten != 0 ||
1545 (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)) {
1546 memset (mMixBuffer, 0, mixBufferSize);
1547 sleepTime = 0;
1548 LOGV_IF((mBytesWritten == 0 && (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)), "anticipated start");
1549 }
1550 // TODO add standby time extension fct of effect tail
1551 }
1552
1553 if (mSuspended) {
Eric Laurent25cbe0e2010-08-18 18:13:17 -07001554 sleepTime = suspendSleepTimeUs();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001555 }
1556 // sleepTime == 0 means we must write to audio hardware
1557 if (sleepTime == 0) {
1558 for (size_t i = 0; i < effectChains.size(); i ++) {
1559 effectChains[i]->process_l();
1560 }
1561 // enable changes in effect chain
Eric Laurentde070132010-07-13 04:45:46 -07001562 unlockEffectChains(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001563 mLastWriteTime = systemTime();
1564 mInWrite = true;
1565 mBytesWritten += mixBufferSize;
1566
Dima Zavinfce7a472011-04-19 22:30:36 -07001567 int bytesWritten = (int)mOutput->write(mOutput, mMixBuffer, mixBufferSize);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001568 if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
1569 mNumWrites++;
1570 mInWrite = false;
1571 nsecs_t now = systemTime();
1572 nsecs_t delta = now - mLastWriteTime;
1573 if (delta > maxPeriod) {
1574 mNumDelayedWrites++;
1575 if ((now - lastWarning) > kWarningThrottle) {
1576 LOGW("write blocked for %llu msecs, %d delayed writes, thread %p",
1577 ns2ms(delta), mNumDelayedWrites, this);
1578 lastWarning = now;
1579 }
1580 if (mStandby) {
1581 longStandbyExit = true;
1582 }
1583 }
1584 mStandby = false;
1585 } else {
1586 // enable changes in effect chain
Eric Laurentde070132010-07-13 04:45:46 -07001587 unlockEffectChains(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001588 usleep(sleepTime);
1589 }
1590
1591 // finally let go of all our tracks, without the lock held
1592 // since we can't guarantee the destructors won't acquire that
1593 // same lock.
1594 tracksToRemove.clear();
1595
1596 // Effect chains will be actually deleted here if they were removed from
1597 // mEffectChains list during mixing or effects processing
1598 effectChains.clear();
1599 }
1600
1601 if (!mStandby) {
Dima Zavinfce7a472011-04-19 22:30:36 -07001602 mOutput->common.standby(&mOutput->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001603 }
1604
1605 LOGV("MixerThread %p exiting", this);
1606 return false;
1607}
1608
1609// prepareTracks_l() must be called with ThreadBase::mLock held
1610uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove)
1611{
1612
1613 uint32_t mixerStatus = MIXER_IDLE;
1614 // find out which tracks need to be processed
1615 size_t count = activeTracks.size();
1616 size_t mixedTracks = 0;
1617 size_t tracksWithEffect = 0;
1618
1619 float masterVolume = mMasterVolume;
1620 bool masterMute = mMasterMute;
1621
Eric Laurent571d49c2010-08-11 05:20:11 -07001622 if (masterMute) {
1623 masterVolume = 0;
1624 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001625 // Delegate master volume control to effect in output mix effect chain if needed
Dima Zavinfce7a472011-04-19 22:30:36 -07001626 sp<EffectChain> chain = getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001627 if (chain != 0) {
Eric Laurent571d49c2010-08-11 05:20:11 -07001628 uint32_t v = (uint32_t)(masterVolume * (1 << 24));
Eric Laurentcab11242010-07-15 12:50:15 -07001629 chain->setVolume_l(&v, &v);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001630 masterVolume = (float)((v + (1 << 23)) >> 24);
1631 chain.clear();
1632 }
1633
1634 for (size_t i=0 ; i<count ; i++) {
1635 sp<Track> t = activeTracks[i].promote();
1636 if (t == 0) continue;
1637
1638 Track* const track = t.get();
1639 audio_track_cblk_t* cblk = track->cblk();
1640
1641 // The first time a track is added we wait
1642 // for all its buffers to be filled before processing it
1643 mAudioMixer->setActiveTrack(track->name());
Eric Laurentaf59ce22010-10-05 14:41:42 -07001644 if (cblk->framesReady() && track->isReady() &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07001645 !track->isPaused() && !track->isTerminated())
1646 {
1647 //LOGV("track %d u=%08x, s=%08x [OK] on thread %p", track->name(), cblk->user, cblk->server, this);
1648
1649 mixedTracks++;
1650
1651 // track->mainBuffer() != mMixBuffer means there is an effect chain
1652 // connected to the track
1653 chain.clear();
1654 if (track->mainBuffer() != mMixBuffer) {
1655 chain = getEffectChain_l(track->sessionId());
1656 // Delegate volume control to effect in track effect chain if needed
1657 if (chain != 0) {
1658 tracksWithEffect++;
1659 } else {
1660 LOGW("prepareTracks_l(): track %08x attached to effect but no chain found on session %d",
1661 track->name(), track->sessionId());
1662 }
1663 }
1664
1665
1666 int param = AudioMixer::VOLUME;
1667 if (track->mFillingUpStatus == Track::FS_FILLED) {
1668 // no ramp for the first volume setting
1669 track->mFillingUpStatus = Track::FS_ACTIVE;
1670 if (track->mState == TrackBase::RESUMING) {
1671 track->mState = TrackBase::ACTIVE;
1672 param = AudioMixer::RAMP_VOLUME;
1673 }
Eric Laurent243f5f92011-02-28 16:52:51 -08001674 mAudioMixer->setParameter(AudioMixer::RESAMPLE, AudioMixer::RESET, NULL);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001675 } else if (cblk->server != 0) {
1676 // If the track is stopped before the first frame was mixed,
1677 // do not apply ramp
1678 param = AudioMixer::RAMP_VOLUME;
1679 }
1680
1681 // compute volume for this track
Eric Laurente0aed6d2010-09-10 17:44:44 -07001682 uint32_t vl, vr, va;
Eric Laurent8569f0d2010-07-29 23:43:43 -07001683 if (track->isMuted() || track->isPausing() ||
Mathias Agopian65ab4712010-07-14 17:59:35 -07001684 mStreamTypes[track->type()].mute) {
Eric Laurente0aed6d2010-09-10 17:44:44 -07001685 vl = vr = va = 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001686 if (track->isPausing()) {
1687 track->setPaused();
1688 }
1689 } else {
Eric Laurente0aed6d2010-09-10 17:44:44 -07001690
Mathias Agopian65ab4712010-07-14 17:59:35 -07001691 // read original volumes with volume control
1692 float typeVolume = mStreamTypes[track->type()].volume;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001693 float v = masterVolume * typeVolume;
Eric Laurente0aed6d2010-09-10 17:44:44 -07001694 vl = (uint32_t)(v * cblk->volume[0]) << 12;
1695 vr = (uint32_t)(v * cblk->volume[1]) << 12;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001696
Eric Laurente0aed6d2010-09-10 17:44:44 -07001697 va = (uint32_t)(v * cblk->sendLevel);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001698 }
Eric Laurente0aed6d2010-09-10 17:44:44 -07001699 // Delegate volume control to effect in track effect chain if needed
1700 if (chain != 0 && chain->setVolume_l(&vl, &vr)) {
1701 // Do not ramp volume if volume is controlled by effect
1702 param = AudioMixer::VOLUME;
1703 track->mHasVolumeController = true;
1704 } else {
1705 // force no volume ramp when volume controller was just disabled or removed
1706 // from effect chain to avoid volume spike
1707 if (track->mHasVolumeController) {
1708 param = AudioMixer::VOLUME;
1709 }
1710 track->mHasVolumeController = false;
1711 }
1712
1713 // Convert volumes from 8.24 to 4.12 format
1714 int16_t left, right, aux;
1715 uint32_t v_clamped = (vl + (1 << 11)) >> 12;
1716 if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
1717 left = int16_t(v_clamped);
1718 v_clamped = (vr + (1 << 11)) >> 12;
1719 if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
1720 right = int16_t(v_clamped);
1721
1722 if (va > MAX_GAIN_INT) va = MAX_GAIN_INT;
1723 aux = int16_t(va);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001724
Mathias Agopian65ab4712010-07-14 17:59:35 -07001725 // XXX: these things DON'T need to be done each time
1726 mAudioMixer->setBufferProvider(track);
1727 mAudioMixer->enable(AudioMixer::MIXING);
1728
1729 mAudioMixer->setParameter(param, AudioMixer::VOLUME0, (void *)left);
1730 mAudioMixer->setParameter(param, AudioMixer::VOLUME1, (void *)right);
1731 mAudioMixer->setParameter(param, AudioMixer::AUXLEVEL, (void *)aux);
1732 mAudioMixer->setParameter(
1733 AudioMixer::TRACK,
1734 AudioMixer::FORMAT, (void *)track->format());
1735 mAudioMixer->setParameter(
1736 AudioMixer::TRACK,
1737 AudioMixer::CHANNEL_COUNT, (void *)track->channelCount());
1738 mAudioMixer->setParameter(
1739 AudioMixer::RESAMPLE,
1740 AudioMixer::SAMPLE_RATE,
1741 (void *)(cblk->sampleRate));
1742 mAudioMixer->setParameter(
1743 AudioMixer::TRACK,
1744 AudioMixer::MAIN_BUFFER, (void *)track->mainBuffer());
1745 mAudioMixer->setParameter(
1746 AudioMixer::TRACK,
1747 AudioMixer::AUX_BUFFER, (void *)track->auxBuffer());
1748
1749 // reset retry count
1750 track->mRetryCount = kMaxTrackRetries;
1751 mixerStatus = MIXER_TRACKS_READY;
1752 } else {
1753 //LOGV("track %d u=%08x, s=%08x [NOT READY] on thread %p", track->name(), cblk->user, cblk->server, this);
1754 if (track->isStopped()) {
1755 track->reset();
1756 }
1757 if (track->isTerminated() || track->isStopped() || track->isPaused()) {
1758 // We have consumed all the buffers of this track.
1759 // Remove it from the list of active tracks.
1760 tracksToRemove->add(track);
1761 } else {
1762 // No buffers for this track. Give it a few chances to
1763 // fill a buffer, then remove it from active list.
1764 if (--(track->mRetryCount) <= 0) {
1765 LOGV("BUFFER TIMEOUT: remove(%d) from active list on thread %p", track->name(), this);
1766 tracksToRemove->add(track);
Eric Laurent44d98482010-09-30 16:12:31 -07001767 // indicate to client process that the track was disabled because of underrun
Eric Laurent38ccae22011-03-28 18:37:07 -07001768 android_atomic_or(CBLK_DISABLED_ON, &cblk->flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001769 } else if (mixerStatus != MIXER_TRACKS_READY) {
1770 mixerStatus = MIXER_TRACKS_ENABLED;
1771 }
1772 }
1773 mAudioMixer->disable(AudioMixer::MIXING);
1774 }
1775 }
1776
1777 // remove all the tracks that need to be...
1778 count = tracksToRemove->size();
1779 if (UNLIKELY(count)) {
1780 for (size_t i=0 ; i<count ; i++) {
1781 const sp<Track>& track = tracksToRemove->itemAt(i);
1782 mActiveTracks.remove(track);
1783 if (track->mainBuffer() != mMixBuffer) {
1784 chain = getEffectChain_l(track->sessionId());
1785 if (chain != 0) {
1786 LOGV("stopping track on chain %p for session Id: %d", chain.get(), track->sessionId());
1787 chain->stopTrack();
1788 }
1789 }
1790 if (track->isTerminated()) {
1791 mTracks.remove(track);
1792 deleteTrackName_l(track->mName);
1793 }
1794 }
1795 }
1796
1797 // mix buffer must be cleared if all tracks are connected to an
1798 // effect chain as in this case the mixer will not write to
1799 // mix buffer and track effects will accumulate into it
1800 if (mixedTracks != 0 && mixedTracks == tracksWithEffect) {
1801 memset(mMixBuffer, 0, mFrameCount * mChannelCount * sizeof(int16_t));
1802 }
1803
1804 return mixerStatus;
1805}
1806
1807void AudioFlinger::MixerThread::invalidateTracks(int streamType)
1808{
Eric Laurentde070132010-07-13 04:45:46 -07001809 LOGV ("MixerThread::invalidateTracks() mixer %p, streamType %d, mTracks.size %d",
1810 this, streamType, mTracks.size());
Mathias Agopian65ab4712010-07-14 17:59:35 -07001811 Mutex::Autolock _l(mLock);
Eric Laurentde070132010-07-13 04:45:46 -07001812
Mathias Agopian65ab4712010-07-14 17:59:35 -07001813 size_t size = mTracks.size();
1814 for (size_t i = 0; i < size; i++) {
1815 sp<Track> t = mTracks[i];
1816 if (t->type() == streamType) {
Eric Laurent38ccae22011-03-28 18:37:07 -07001817 android_atomic_or(CBLK_INVALID_ON, &t->mCblk->flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001818 t->mCblk->cv.signal();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001819 }
1820 }
1821}
1822
1823
1824// getTrackName_l() must be called with ThreadBase::mLock held
1825int AudioFlinger::MixerThread::getTrackName_l()
1826{
1827 return mAudioMixer->getTrackName();
1828}
1829
1830// deleteTrackName_l() must be called with ThreadBase::mLock held
1831void AudioFlinger::MixerThread::deleteTrackName_l(int name)
1832{
1833 LOGV("remove track (%d) and delete from mixer", name);
1834 mAudioMixer->deleteTrackName(name);
1835}
1836
1837// checkForNewParameters_l() must be called with ThreadBase::mLock held
1838bool AudioFlinger::MixerThread::checkForNewParameters_l()
1839{
1840 bool reconfig = false;
1841
1842 while (!mNewParameters.isEmpty()) {
1843 status_t status = NO_ERROR;
1844 String8 keyValuePair = mNewParameters[0];
1845 AudioParameter param = AudioParameter(keyValuePair);
1846 int value;
1847
1848 if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
1849 reconfig = true;
1850 }
1851 if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
Dima Zavinfce7a472011-04-19 22:30:36 -07001852 if (value != AUDIO_FORMAT_PCM_16_BIT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001853 status = BAD_VALUE;
1854 } else {
1855 reconfig = true;
1856 }
1857 }
1858 if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
Dima Zavinfce7a472011-04-19 22:30:36 -07001859 if (value != AUDIO_CHANNEL_OUT_STEREO) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001860 status = BAD_VALUE;
1861 } else {
1862 reconfig = true;
1863 }
1864 }
1865 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
1866 // do not accept frame count changes if tracks are open as the track buffer
1867 // size depends on frame count and correct behavior would not be garantied
1868 // if frame count is changed after track creation
1869 if (!mTracks.isEmpty()) {
1870 status = INVALID_OPERATION;
1871 } else {
1872 reconfig = true;
1873 }
1874 }
1875 if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
Gloria Wang9ee159b2011-02-24 14:51:45 -08001876 // when changing the audio output device, call addBatteryData to notify
1877 // the change
1878 if (mDevice != value) {
1879 uint32_t params = 0;
1880 // check whether speaker is on
Dima Zavinfce7a472011-04-19 22:30:36 -07001881 if (value & AUDIO_DEVICE_OUT_SPEAKER) {
Gloria Wang9ee159b2011-02-24 14:51:45 -08001882 params |= IMediaPlayerService::kBatteryDataSpeakerOn;
1883 }
1884
1885 int deviceWithoutSpeaker
Dima Zavinfce7a472011-04-19 22:30:36 -07001886 = AUDIO_DEVICE_OUT_ALL & ~AUDIO_DEVICE_OUT_SPEAKER;
Gloria Wang9ee159b2011-02-24 14:51:45 -08001887 // check if any other device (except speaker) is on
1888 if (value & deviceWithoutSpeaker ) {
1889 params |= IMediaPlayerService::kBatteryDataOtherAudioDeviceOn;
1890 }
1891
1892 if (params != 0) {
1893 addBatteryData(params);
1894 }
1895 }
1896
Mathias Agopian65ab4712010-07-14 17:59:35 -07001897 // forward device change to effects that have requested to be
1898 // aware of attached audio device.
1899 mDevice = (uint32_t)value;
1900 for (size_t i = 0; i < mEffectChains.size(); i++) {
Eric Laurentcab11242010-07-15 12:50:15 -07001901 mEffectChains[i]->setDevice_l(mDevice);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001902 }
1903 }
1904
1905 if (status == NO_ERROR) {
Dima Zavinfce7a472011-04-19 22:30:36 -07001906 status = mOutput->common.set_parameters(&mOutput->common,
1907 keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07001908 if (!mStandby && status == INVALID_OPERATION) {
Dima Zavinfce7a472011-04-19 22:30:36 -07001909 mOutput->common.standby(&mOutput->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001910 mStandby = true;
1911 mBytesWritten = 0;
Dima Zavinfce7a472011-04-19 22:30:36 -07001912 status = mOutput->common.set_parameters(&mOutput->common,
1913 keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07001914 }
1915 if (status == NO_ERROR && reconfig) {
1916 delete mAudioMixer;
1917 readOutputParameters();
1918 mAudioMixer = new AudioMixer(mFrameCount, mSampleRate);
1919 for (size_t i = 0; i < mTracks.size() ; i++) {
1920 int name = getTrackName_l();
1921 if (name < 0) break;
1922 mTracks[i]->mName = name;
1923 // limit track sample rate to 2 x new output sample rate
1924 if (mTracks[i]->mCblk->sampleRate > 2 * sampleRate()) {
1925 mTracks[i]->mCblk->sampleRate = 2 * sampleRate();
1926 }
1927 }
1928 sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
1929 }
1930 }
1931
1932 mNewParameters.removeAt(0);
1933
1934 mParamStatus = status;
1935 mParamCond.signal();
1936 mWaitWorkCV.wait(mLock);
1937 }
1938 return reconfig;
1939}
1940
1941status_t AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>& args)
1942{
1943 const size_t SIZE = 256;
1944 char buffer[SIZE];
1945 String8 result;
1946
1947 PlaybackThread::dumpInternals(fd, args);
1948
1949 snprintf(buffer, SIZE, "AudioMixer tracks: %08x\n", mAudioMixer->trackNames());
1950 result.append(buffer);
1951 write(fd, result.string(), result.size());
1952 return NO_ERROR;
1953}
1954
1955uint32_t AudioFlinger::MixerThread::activeSleepTimeUs()
1956{
Dima Zavinfce7a472011-04-19 22:30:36 -07001957 return (uint32_t)(mOutput->get_latency(mOutput) * 1000) / 2;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001958}
1959
1960uint32_t AudioFlinger::MixerThread::idleSleepTimeUs()
1961{
Eric Laurent60e18242010-07-29 06:50:24 -07001962 return (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000) / 2;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001963}
1964
Eric Laurent25cbe0e2010-08-18 18:13:17 -07001965uint32_t AudioFlinger::MixerThread::suspendSleepTimeUs()
1966{
1967 return (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000);
1968}
1969
Mathias Agopian65ab4712010-07-14 17:59:35 -07001970// ----------------------------------------------------------------------------
Dima Zavinfce7a472011-04-19 22:30:36 -07001971AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, struct audio_stream_out* output, int id, uint32_t device)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001972 : PlaybackThread(audioFlinger, output, id, device)
1973{
1974 mType = PlaybackThread::DIRECT;
1975}
1976
1977AudioFlinger::DirectOutputThread::~DirectOutputThread()
1978{
1979}
1980
1981
1982static inline int16_t clamp16(int32_t sample)
1983{
1984 if ((sample>>15) ^ (sample>>31))
1985 sample = 0x7FFF ^ (sample>>31);
1986 return sample;
1987}
1988
1989static inline
1990int32_t mul(int16_t in, int16_t v)
1991{
1992#if defined(__arm__) && !defined(__thumb__)
1993 int32_t out;
1994 asm( "smulbb %[out], %[in], %[v] \n"
1995 : [out]"=r"(out)
1996 : [in]"%r"(in), [v]"r"(v)
1997 : );
1998 return out;
1999#else
2000 return in * int32_t(v);
2001#endif
2002}
2003
2004void AudioFlinger::DirectOutputThread::applyVolume(uint16_t leftVol, uint16_t rightVol, bool ramp)
2005{
2006 // Do not apply volume on compressed audio
Dima Zavinfce7a472011-04-19 22:30:36 -07002007 if (!audio_is_linear_pcm(mFormat)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002008 return;
2009 }
2010
2011 // convert to signed 16 bit before volume calculation
Dima Zavinfce7a472011-04-19 22:30:36 -07002012 if (mFormat == AUDIO_FORMAT_PCM_8_BIT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002013 size_t count = mFrameCount * mChannelCount;
2014 uint8_t *src = (uint8_t *)mMixBuffer + count-1;
2015 int16_t *dst = mMixBuffer + count-1;
2016 while(count--) {
2017 *dst-- = (int16_t)(*src--^0x80) << 8;
2018 }
2019 }
2020
2021 size_t frameCount = mFrameCount;
2022 int16_t *out = mMixBuffer;
2023 if (ramp) {
2024 if (mChannelCount == 1) {
2025 int32_t d = ((int32_t)leftVol - (int32_t)mLeftVolShort) << 16;
2026 int32_t vlInc = d / (int32_t)frameCount;
2027 int32_t vl = ((int32_t)mLeftVolShort << 16);
2028 do {
2029 out[0] = clamp16(mul(out[0], vl >> 16) >> 12);
2030 out++;
2031 vl += vlInc;
2032 } while (--frameCount);
2033
2034 } else {
2035 int32_t d = ((int32_t)leftVol - (int32_t)mLeftVolShort) << 16;
2036 int32_t vlInc = d / (int32_t)frameCount;
2037 d = ((int32_t)rightVol - (int32_t)mRightVolShort) << 16;
2038 int32_t vrInc = d / (int32_t)frameCount;
2039 int32_t vl = ((int32_t)mLeftVolShort << 16);
2040 int32_t vr = ((int32_t)mRightVolShort << 16);
2041 do {
2042 out[0] = clamp16(mul(out[0], vl >> 16) >> 12);
2043 out[1] = clamp16(mul(out[1], vr >> 16) >> 12);
2044 out += 2;
2045 vl += vlInc;
2046 vr += vrInc;
2047 } while (--frameCount);
2048 }
2049 } else {
2050 if (mChannelCount == 1) {
2051 do {
2052 out[0] = clamp16(mul(out[0], leftVol) >> 12);
2053 out++;
2054 } while (--frameCount);
2055 } else {
2056 do {
2057 out[0] = clamp16(mul(out[0], leftVol) >> 12);
2058 out[1] = clamp16(mul(out[1], rightVol) >> 12);
2059 out += 2;
2060 } while (--frameCount);
2061 }
2062 }
2063
2064 // convert back to unsigned 8 bit after volume calculation
Dima Zavinfce7a472011-04-19 22:30:36 -07002065 if (mFormat == AUDIO_FORMAT_PCM_8_BIT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002066 size_t count = mFrameCount * mChannelCount;
2067 int16_t *src = mMixBuffer;
2068 uint8_t *dst = (uint8_t *)mMixBuffer;
2069 while(count--) {
2070 *dst++ = (uint8_t)(((int32_t)*src++ + (1<<7)) >> 8)^0x80;
2071 }
2072 }
2073
2074 mLeftVolShort = leftVol;
2075 mRightVolShort = rightVol;
2076}
2077
2078bool AudioFlinger::DirectOutputThread::threadLoop()
2079{
2080 uint32_t mixerStatus = MIXER_IDLE;
2081 sp<Track> trackToRemove;
2082 sp<Track> activeTrack;
2083 nsecs_t standbyTime = systemTime();
2084 int8_t *curBuf;
2085 size_t mixBufferSize = mFrameCount*mFrameSize;
2086 uint32_t activeSleepTime = activeSleepTimeUs();
2087 uint32_t idleSleepTime = idleSleepTimeUs();
2088 uint32_t sleepTime = idleSleepTime;
2089 // use shorter standby delay as on normal output to release
2090 // hardware resources as soon as possible
2091 nsecs_t standbyDelay = microseconds(activeSleepTime*2);
2092
Mathias Agopian65ab4712010-07-14 17:59:35 -07002093 while (!exitPending())
2094 {
2095 bool rampVolume;
2096 uint16_t leftVol;
2097 uint16_t rightVol;
2098 Vector< sp<EffectChain> > effectChains;
2099
2100 processConfigEvents();
2101
2102 mixerStatus = MIXER_IDLE;
2103
2104 { // scope for the mLock
2105
2106 Mutex::Autolock _l(mLock);
2107
2108 if (checkForNewParameters_l()) {
2109 mixBufferSize = mFrameCount*mFrameSize;
2110 activeSleepTime = activeSleepTimeUs();
2111 idleSleepTime = idleSleepTimeUs();
2112 standbyDelay = microseconds(activeSleepTime*2);
2113 }
2114
2115 // put audio hardware into standby after short delay
2116 if UNLIKELY((!mActiveTracks.size() && systemTime() > standbyTime) ||
2117 mSuspended) {
2118 // wait until we have something to do...
2119 if (!mStandby) {
2120 LOGV("Audio hardware entering standby, mixer %p\n", this);
Dima Zavinfce7a472011-04-19 22:30:36 -07002121 mOutput->common.standby(&mOutput->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002122 mStandby = true;
2123 mBytesWritten = 0;
2124 }
2125
2126 if (!mActiveTracks.size() && mConfigEvents.isEmpty()) {
2127 // we're about to wait, flush the binder command buffer
2128 IPCThreadState::self()->flushCommands();
2129
2130 if (exitPending()) break;
2131
2132 LOGV("DirectOutputThread %p TID %d going to sleep\n", this, gettid());
2133 mWaitWorkCV.wait(mLock);
2134 LOGV("DirectOutputThread %p TID %d waking up in active mode\n", this, gettid());
2135
2136 if (mMasterMute == false) {
2137 char value[PROPERTY_VALUE_MAX];
2138 property_get("ro.audio.silent", value, "0");
2139 if (atoi(value)) {
2140 LOGD("Silence is golden");
2141 setMasterMute(true);
2142 }
2143 }
2144
2145 standbyTime = systemTime() + standbyDelay;
2146 sleepTime = idleSleepTime;
2147 continue;
2148 }
2149 }
2150
2151 effectChains = mEffectChains;
2152
2153 // find out which tracks need to be processed
2154 if (mActiveTracks.size() != 0) {
2155 sp<Track> t = mActiveTracks[0].promote();
2156 if (t == 0) continue;
2157
2158 Track* const track = t.get();
2159 audio_track_cblk_t* cblk = track->cblk();
2160
2161 // The first time a track is added we wait
2162 // for all its buffers to be filled before processing it
Eric Laurentaf59ce22010-10-05 14:41:42 -07002163 if (cblk->framesReady() && track->isReady() &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07002164 !track->isPaused() && !track->isTerminated())
2165 {
2166 //LOGV("track %d u=%08x, s=%08x [OK]", track->name(), cblk->user, cblk->server);
2167
2168 if (track->mFillingUpStatus == Track::FS_FILLED) {
2169 track->mFillingUpStatus = Track::FS_ACTIVE;
2170 mLeftVolFloat = mRightVolFloat = 0;
2171 mLeftVolShort = mRightVolShort = 0;
2172 if (track->mState == TrackBase::RESUMING) {
2173 track->mState = TrackBase::ACTIVE;
2174 rampVolume = true;
2175 }
2176 } else if (cblk->server != 0) {
2177 // If the track is stopped before the first frame was mixed,
2178 // do not apply ramp
2179 rampVolume = true;
2180 }
2181 // compute volume for this track
2182 float left, right;
2183 if (track->isMuted() || mMasterMute || track->isPausing() ||
2184 mStreamTypes[track->type()].mute) {
2185 left = right = 0;
2186 if (track->isPausing()) {
2187 track->setPaused();
2188 }
2189 } else {
2190 float typeVolume = mStreamTypes[track->type()].volume;
2191 float v = mMasterVolume * typeVolume;
2192 float v_clamped = v * cblk->volume[0];
2193 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
2194 left = v_clamped/MAX_GAIN;
2195 v_clamped = v * cblk->volume[1];
2196 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
2197 right = v_clamped/MAX_GAIN;
2198 }
2199
2200 if (left != mLeftVolFloat || right != mRightVolFloat) {
2201 mLeftVolFloat = left;
2202 mRightVolFloat = right;
2203
2204 // If audio HAL implements volume control,
2205 // force software volume to nominal value
Dima Zavinfce7a472011-04-19 22:30:36 -07002206 if (mOutput->set_volume(mOutput, left, right) == NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002207 left = 1.0f;
2208 right = 1.0f;
2209 }
2210
2211 // Convert volumes from float to 8.24
2212 uint32_t vl = (uint32_t)(left * (1 << 24));
2213 uint32_t vr = (uint32_t)(right * (1 << 24));
2214
2215 // Delegate volume control to effect in track effect chain if needed
2216 // only one effect chain can be present on DirectOutputThread, so if
2217 // there is one, the track is connected to it
2218 if (!effectChains.isEmpty()) {
Eric Laurente0aed6d2010-09-10 17:44:44 -07002219 // Do not ramp volume if volume is controlled by effect
Eric Laurentcab11242010-07-15 12:50:15 -07002220 if(effectChains[0]->setVolume_l(&vl, &vr)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002221 rampVolume = false;
2222 }
2223 }
2224
2225 // Convert volumes from 8.24 to 4.12 format
2226 uint32_t v_clamped = (vl + (1 << 11)) >> 12;
2227 if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
2228 leftVol = (uint16_t)v_clamped;
2229 v_clamped = (vr + (1 << 11)) >> 12;
2230 if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
2231 rightVol = (uint16_t)v_clamped;
2232 } else {
2233 leftVol = mLeftVolShort;
2234 rightVol = mRightVolShort;
2235 rampVolume = false;
2236 }
2237
2238 // reset retry count
2239 track->mRetryCount = kMaxTrackRetriesDirect;
2240 activeTrack = t;
2241 mixerStatus = MIXER_TRACKS_READY;
2242 } else {
2243 //LOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
2244 if (track->isStopped()) {
2245 track->reset();
2246 }
2247 if (track->isTerminated() || track->isStopped() || track->isPaused()) {
2248 // We have consumed all the buffers of this track.
2249 // Remove it from the list of active tracks.
2250 trackToRemove = track;
2251 } else {
2252 // No buffers for this track. Give it a few chances to
2253 // fill a buffer, then remove it from active list.
2254 if (--(track->mRetryCount) <= 0) {
2255 LOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
2256 trackToRemove = track;
2257 } else {
2258 mixerStatus = MIXER_TRACKS_ENABLED;
2259 }
2260 }
2261 }
2262 }
2263
2264 // remove all the tracks that need to be...
2265 if (UNLIKELY(trackToRemove != 0)) {
2266 mActiveTracks.remove(trackToRemove);
2267 if (!effectChains.isEmpty()) {
Eric Laurentde070132010-07-13 04:45:46 -07002268 LOGV("stopping track on chain %p for session Id: %d", effectChains[0].get(),
2269 trackToRemove->sessionId());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002270 effectChains[0]->stopTrack();
2271 }
2272 if (trackToRemove->isTerminated()) {
2273 mTracks.remove(trackToRemove);
2274 deleteTrackName_l(trackToRemove->mName);
2275 }
2276 }
2277
Eric Laurentde070132010-07-13 04:45:46 -07002278 lockEffectChains_l(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002279 }
2280
2281 if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
2282 AudioBufferProvider::Buffer buffer;
2283 size_t frameCount = mFrameCount;
2284 curBuf = (int8_t *)mMixBuffer;
2285 // output audio to hardware
2286 while (frameCount) {
2287 buffer.frameCount = frameCount;
2288 activeTrack->getNextBuffer(&buffer);
2289 if (UNLIKELY(buffer.raw == 0)) {
2290 memset(curBuf, 0, frameCount * mFrameSize);
2291 break;
2292 }
2293 memcpy(curBuf, buffer.raw, buffer.frameCount * mFrameSize);
2294 frameCount -= buffer.frameCount;
2295 curBuf += buffer.frameCount * mFrameSize;
2296 activeTrack->releaseBuffer(&buffer);
2297 }
2298 sleepTime = 0;
2299 standbyTime = systemTime() + standbyDelay;
2300 } else {
2301 if (sleepTime == 0) {
2302 if (mixerStatus == MIXER_TRACKS_ENABLED) {
2303 sleepTime = activeSleepTime;
2304 } else {
2305 sleepTime = idleSleepTime;
2306 }
Dima Zavinfce7a472011-04-19 22:30:36 -07002307 } else if (mBytesWritten != 0 && audio_is_linear_pcm(mFormat)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002308 memset (mMixBuffer, 0, mFrameCount * mFrameSize);
2309 sleepTime = 0;
2310 }
2311 }
2312
2313 if (mSuspended) {
Eric Laurent25cbe0e2010-08-18 18:13:17 -07002314 sleepTime = suspendSleepTimeUs();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002315 }
2316 // sleepTime == 0 means we must write to audio hardware
2317 if (sleepTime == 0) {
2318 if (mixerStatus == MIXER_TRACKS_READY) {
2319 applyVolume(leftVol, rightVol, rampVolume);
2320 }
2321 for (size_t i = 0; i < effectChains.size(); i ++) {
2322 effectChains[i]->process_l();
2323 }
Eric Laurentde070132010-07-13 04:45:46 -07002324 unlockEffectChains(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002325
2326 mLastWriteTime = systemTime();
2327 mInWrite = true;
2328 mBytesWritten += mixBufferSize;
Dima Zavinfce7a472011-04-19 22:30:36 -07002329 int bytesWritten = (int)mOutput->write(mOutput, mMixBuffer, mixBufferSize);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002330 if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
2331 mNumWrites++;
2332 mInWrite = false;
2333 mStandby = false;
2334 } else {
Eric Laurentde070132010-07-13 04:45:46 -07002335 unlockEffectChains(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002336 usleep(sleepTime);
2337 }
2338
2339 // finally let go of removed track, without the lock held
2340 // since we can't guarantee the destructors won't acquire that
2341 // same lock.
2342 trackToRemove.clear();
2343 activeTrack.clear();
2344
2345 // Effect chains will be actually deleted here if they were removed from
2346 // mEffectChains list during mixing or effects processing
2347 effectChains.clear();
2348 }
2349
2350 if (!mStandby) {
Dima Zavinfce7a472011-04-19 22:30:36 -07002351 mOutput->common.standby(&mOutput->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002352 }
2353
2354 LOGV("DirectOutputThread %p exiting", this);
2355 return false;
2356}
2357
2358// getTrackName_l() must be called with ThreadBase::mLock held
2359int AudioFlinger::DirectOutputThread::getTrackName_l()
2360{
2361 return 0;
2362}
2363
2364// deleteTrackName_l() must be called with ThreadBase::mLock held
2365void AudioFlinger::DirectOutputThread::deleteTrackName_l(int name)
2366{
2367}
2368
2369// checkForNewParameters_l() must be called with ThreadBase::mLock held
2370bool AudioFlinger::DirectOutputThread::checkForNewParameters_l()
2371{
2372 bool reconfig = false;
2373
2374 while (!mNewParameters.isEmpty()) {
2375 status_t status = NO_ERROR;
2376 String8 keyValuePair = mNewParameters[0];
2377 AudioParameter param = AudioParameter(keyValuePair);
2378 int value;
2379
2380 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
2381 // do not accept frame count changes if tracks are open as the track buffer
2382 // size depends on frame count and correct behavior would not be garantied
2383 // if frame count is changed after track creation
2384 if (!mTracks.isEmpty()) {
2385 status = INVALID_OPERATION;
2386 } else {
2387 reconfig = true;
2388 }
2389 }
2390 if (status == NO_ERROR) {
Dima Zavinfce7a472011-04-19 22:30:36 -07002391 status = mOutput->common.set_parameters(&mOutput->common,
2392 keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002393 if (!mStandby && status == INVALID_OPERATION) {
Dima Zavinfce7a472011-04-19 22:30:36 -07002394 mOutput->common.standby(&mOutput->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002395 mStandby = true;
2396 mBytesWritten = 0;
Dima Zavinfce7a472011-04-19 22:30:36 -07002397 status = mOutput->common.set_parameters(&mOutput->common,
2398 keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002399 }
2400 if (status == NO_ERROR && reconfig) {
2401 readOutputParameters();
2402 sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
2403 }
2404 }
2405
2406 mNewParameters.removeAt(0);
2407
2408 mParamStatus = status;
2409 mParamCond.signal();
2410 mWaitWorkCV.wait(mLock);
2411 }
2412 return reconfig;
2413}
2414
2415uint32_t AudioFlinger::DirectOutputThread::activeSleepTimeUs()
2416{
2417 uint32_t time;
Dima Zavinfce7a472011-04-19 22:30:36 -07002418 if (audio_is_linear_pcm(mFormat)) {
2419 time = (uint32_t)(mOutput->get_latency(mOutput) * 1000) / 2;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002420 } else {
2421 time = 10000;
2422 }
2423 return time;
2424}
2425
2426uint32_t AudioFlinger::DirectOutputThread::idleSleepTimeUs()
2427{
2428 uint32_t time;
Dima Zavinfce7a472011-04-19 22:30:36 -07002429 if (audio_is_linear_pcm(mFormat)) {
Eric Laurent60e18242010-07-29 06:50:24 -07002430 time = (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000) / 2;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002431 } else {
2432 time = 10000;
2433 }
2434 return time;
2435}
2436
Eric Laurent25cbe0e2010-08-18 18:13:17 -07002437uint32_t AudioFlinger::DirectOutputThread::suspendSleepTimeUs()
2438{
2439 uint32_t time;
Dima Zavinfce7a472011-04-19 22:30:36 -07002440 if (audio_is_linear_pcm(mFormat)) {
Eric Laurent25cbe0e2010-08-18 18:13:17 -07002441 time = (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000);
2442 } else {
2443 time = 10000;
2444 }
2445 return time;
2446}
2447
2448
Mathias Agopian65ab4712010-07-14 17:59:35 -07002449// ----------------------------------------------------------------------------
2450
2451AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger, AudioFlinger::MixerThread* mainThread, int id)
2452 : MixerThread(audioFlinger, mainThread->getOutput(), id, mainThread->device()), mWaitTimeMs(UINT_MAX)
2453{
2454 mType = PlaybackThread::DUPLICATING;
2455 addOutputTrack(mainThread);
2456}
2457
2458AudioFlinger::DuplicatingThread::~DuplicatingThread()
2459{
2460 for (size_t i = 0; i < mOutputTracks.size(); i++) {
2461 mOutputTracks[i]->destroy();
2462 }
2463 mOutputTracks.clear();
2464}
2465
2466bool AudioFlinger::DuplicatingThread::threadLoop()
2467{
2468 Vector< sp<Track> > tracksToRemove;
2469 uint32_t mixerStatus = MIXER_IDLE;
2470 nsecs_t standbyTime = systemTime();
2471 size_t mixBufferSize = mFrameCount*mFrameSize;
2472 SortedVector< sp<OutputTrack> > outputTracks;
2473 uint32_t writeFrames = 0;
2474 uint32_t activeSleepTime = activeSleepTimeUs();
2475 uint32_t idleSleepTime = idleSleepTimeUs();
2476 uint32_t sleepTime = idleSleepTime;
2477 Vector< sp<EffectChain> > effectChains;
2478
2479 while (!exitPending())
2480 {
2481 processConfigEvents();
2482
2483 mixerStatus = MIXER_IDLE;
2484 { // scope for the mLock
2485
2486 Mutex::Autolock _l(mLock);
2487
2488 if (checkForNewParameters_l()) {
2489 mixBufferSize = mFrameCount*mFrameSize;
2490 updateWaitTime();
2491 activeSleepTime = activeSleepTimeUs();
2492 idleSleepTime = idleSleepTimeUs();
2493 }
2494
2495 const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
2496
2497 for (size_t i = 0; i < mOutputTracks.size(); i++) {
2498 outputTracks.add(mOutputTracks[i]);
2499 }
2500
2501 // put audio hardware into standby after short delay
2502 if UNLIKELY((!activeTracks.size() && systemTime() > standbyTime) ||
2503 mSuspended) {
2504 if (!mStandby) {
2505 for (size_t i = 0; i < outputTracks.size(); i++) {
2506 outputTracks[i]->stop();
2507 }
2508 mStandby = true;
2509 mBytesWritten = 0;
2510 }
2511
2512 if (!activeTracks.size() && mConfigEvents.isEmpty()) {
2513 // we're about to wait, flush the binder command buffer
2514 IPCThreadState::self()->flushCommands();
2515 outputTracks.clear();
2516
2517 if (exitPending()) break;
2518
2519 LOGV("DuplicatingThread %p TID %d going to sleep\n", this, gettid());
2520 mWaitWorkCV.wait(mLock);
2521 LOGV("DuplicatingThread %p TID %d waking up\n", this, gettid());
2522 if (mMasterMute == false) {
2523 char value[PROPERTY_VALUE_MAX];
2524 property_get("ro.audio.silent", value, "0");
2525 if (atoi(value)) {
2526 LOGD("Silence is golden");
2527 setMasterMute(true);
2528 }
2529 }
2530
2531 standbyTime = systemTime() + kStandbyTimeInNsecs;
2532 sleepTime = idleSleepTime;
2533 continue;
2534 }
2535 }
2536
2537 mixerStatus = prepareTracks_l(activeTracks, &tracksToRemove);
2538
2539 // prevent any changes in effect chain list and in each effect chain
2540 // during mixing and effect process as the audio buffers could be deleted
2541 // or modified if an effect is created or deleted
Eric Laurentde070132010-07-13 04:45:46 -07002542 lockEffectChains_l(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002543 }
2544
2545 if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
2546 // mix buffers...
2547 if (outputsReady(outputTracks)) {
2548 mAudioMixer->process();
2549 } else {
2550 memset(mMixBuffer, 0, mixBufferSize);
2551 }
2552 sleepTime = 0;
2553 writeFrames = mFrameCount;
2554 } else {
2555 if (sleepTime == 0) {
2556 if (mixerStatus == MIXER_TRACKS_ENABLED) {
2557 sleepTime = activeSleepTime;
2558 } else {
2559 sleepTime = idleSleepTime;
2560 }
2561 } else if (mBytesWritten != 0) {
2562 // flush remaining overflow buffers in output tracks
2563 for (size_t i = 0; i < outputTracks.size(); i++) {
2564 if (outputTracks[i]->isActive()) {
2565 sleepTime = 0;
2566 writeFrames = 0;
2567 memset(mMixBuffer, 0, mixBufferSize);
2568 break;
2569 }
2570 }
2571 }
2572 }
2573
2574 if (mSuspended) {
Eric Laurent25cbe0e2010-08-18 18:13:17 -07002575 sleepTime = suspendSleepTimeUs();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002576 }
2577 // sleepTime == 0 means we must write to audio hardware
2578 if (sleepTime == 0) {
2579 for (size_t i = 0; i < effectChains.size(); i ++) {
2580 effectChains[i]->process_l();
2581 }
2582 // enable changes in effect chain
Eric Laurentde070132010-07-13 04:45:46 -07002583 unlockEffectChains(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002584
2585 standbyTime = systemTime() + kStandbyTimeInNsecs;
2586 for (size_t i = 0; i < outputTracks.size(); i++) {
2587 outputTracks[i]->write(mMixBuffer, writeFrames);
2588 }
2589 mStandby = false;
2590 mBytesWritten += mixBufferSize;
2591 } else {
2592 // enable changes in effect chain
Eric Laurentde070132010-07-13 04:45:46 -07002593 unlockEffectChains(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002594 usleep(sleepTime);
2595 }
2596
2597 // finally let go of all our tracks, without the lock held
2598 // since we can't guarantee the destructors won't acquire that
2599 // same lock.
2600 tracksToRemove.clear();
2601 outputTracks.clear();
2602
2603 // Effect chains will be actually deleted here if they were removed from
2604 // mEffectChains list during mixing or effects processing
2605 effectChains.clear();
2606 }
2607
2608 return false;
2609}
2610
2611void AudioFlinger::DuplicatingThread::addOutputTrack(MixerThread *thread)
2612{
2613 int frameCount = (3 * mFrameCount * mSampleRate) / thread->sampleRate();
2614 OutputTrack *outputTrack = new OutputTrack((ThreadBase *)thread,
2615 this,
2616 mSampleRate,
2617 mFormat,
2618 mChannelCount,
2619 frameCount);
2620 if (outputTrack->cblk() != NULL) {
Dima Zavinfce7a472011-04-19 22:30:36 -07002621 thread->setStreamVolume(AUDIO_STREAM_CNT, 1.0f);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002622 mOutputTracks.add(outputTrack);
2623 LOGV("addOutputTrack() track %p, on thread %p", outputTrack, thread);
2624 updateWaitTime();
2625 }
2626}
2627
2628void AudioFlinger::DuplicatingThread::removeOutputTrack(MixerThread *thread)
2629{
2630 Mutex::Autolock _l(mLock);
2631 for (size_t i = 0; i < mOutputTracks.size(); i++) {
2632 if (mOutputTracks[i]->thread() == (ThreadBase *)thread) {
2633 mOutputTracks[i]->destroy();
2634 mOutputTracks.removeAt(i);
2635 updateWaitTime();
2636 return;
2637 }
2638 }
2639 LOGV("removeOutputTrack(): unkonwn thread: %p", thread);
2640}
2641
2642void AudioFlinger::DuplicatingThread::updateWaitTime()
2643{
2644 mWaitTimeMs = UINT_MAX;
2645 for (size_t i = 0; i < mOutputTracks.size(); i++) {
2646 sp<ThreadBase> strong = mOutputTracks[i]->thread().promote();
2647 if (strong != NULL) {
2648 uint32_t waitTimeMs = (strong->frameCount() * 2 * 1000) / strong->sampleRate();
2649 if (waitTimeMs < mWaitTimeMs) {
2650 mWaitTimeMs = waitTimeMs;
2651 }
2652 }
2653 }
2654}
2655
2656
2657bool AudioFlinger::DuplicatingThread::outputsReady(SortedVector< sp<OutputTrack> > &outputTracks)
2658{
2659 for (size_t i = 0; i < outputTracks.size(); i++) {
2660 sp <ThreadBase> thread = outputTracks[i]->thread().promote();
2661 if (thread == 0) {
2662 LOGW("DuplicatingThread::outputsReady() could not promote thread on output track %p", outputTracks[i].get());
2663 return false;
2664 }
2665 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
2666 if (playbackThread->standby() && !playbackThread->isSuspended()) {
2667 LOGV("DuplicatingThread output track %p on thread %p Not Ready", outputTracks[i].get(), thread.get());
2668 return false;
2669 }
2670 }
2671 return true;
2672}
2673
2674uint32_t AudioFlinger::DuplicatingThread::activeSleepTimeUs()
2675{
2676 return (mWaitTimeMs * 1000) / 2;
2677}
2678
2679// ----------------------------------------------------------------------------
2680
2681// TrackBase constructor must be called with AudioFlinger::mLock held
2682AudioFlinger::ThreadBase::TrackBase::TrackBase(
2683 const wp<ThreadBase>& thread,
2684 const sp<Client>& client,
2685 uint32_t sampleRate,
2686 int format,
2687 int channelCount,
2688 int frameCount,
2689 uint32_t flags,
2690 const sp<IMemory>& sharedBuffer,
2691 int sessionId)
2692 : RefBase(),
2693 mThread(thread),
2694 mClient(client),
2695 mCblk(0),
2696 mFrameCount(0),
2697 mState(IDLE),
2698 mClientTid(-1),
2699 mFormat(format),
2700 mFlags(flags & ~SYSTEM_FLAGS_MASK),
2701 mSessionId(sessionId)
2702{
2703 LOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size());
2704
2705 // LOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
2706 size_t size = sizeof(audio_track_cblk_t);
2707 size_t bufferSize = frameCount*channelCount*sizeof(int16_t);
2708 if (sharedBuffer == 0) {
2709 size += bufferSize;
2710 }
2711
2712 if (client != NULL) {
2713 mCblkMemory = client->heap()->allocate(size);
2714 if (mCblkMemory != 0) {
2715 mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer());
2716 if (mCblk) { // construct the shared structure in-place.
2717 new(mCblk) audio_track_cblk_t();
2718 // clear all buffers
2719 mCblk->frameCount = frameCount;
2720 mCblk->sampleRate = sampleRate;
2721 mCblk->channelCount = (uint8_t)channelCount;
2722 if (sharedBuffer == 0) {
2723 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
2724 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
2725 // Force underrun condition to avoid false underrun callback until first data is
Eric Laurent44d98482010-09-30 16:12:31 -07002726 // written to buffer (other flags are cleared)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002727 mCblk->flags = CBLK_UNDERRUN_ON;
2728 } else {
2729 mBuffer = sharedBuffer->pointer();
2730 }
2731 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
2732 }
2733 } else {
2734 LOGE("not enough memory for AudioTrack size=%u", size);
2735 client->heap()->dump("AudioTrack");
2736 return;
2737 }
2738 } else {
2739 mCblk = (audio_track_cblk_t *)(new uint8_t[size]);
2740 if (mCblk) { // construct the shared structure in-place.
2741 new(mCblk) audio_track_cblk_t();
2742 // clear all buffers
2743 mCblk->frameCount = frameCount;
2744 mCblk->sampleRate = sampleRate;
2745 mCblk->channelCount = (uint8_t)channelCount;
2746 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
2747 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
2748 // Force underrun condition to avoid false underrun callback until first data is
Eric Laurent44d98482010-09-30 16:12:31 -07002749 // written to buffer (other flags are cleared)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002750 mCblk->flags = CBLK_UNDERRUN_ON;
2751 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
2752 }
2753 }
2754}
2755
2756AudioFlinger::ThreadBase::TrackBase::~TrackBase()
2757{
2758 if (mCblk) {
2759 mCblk->~audio_track_cblk_t(); // destroy our shared-structure.
2760 if (mClient == NULL) {
2761 delete mCblk;
2762 }
2763 }
2764 mCblkMemory.clear(); // and free the shared memory
2765 if (mClient != NULL) {
2766 Mutex::Autolock _l(mClient->audioFlinger()->mLock);
2767 mClient.clear();
2768 }
2769}
2770
2771void AudioFlinger::ThreadBase::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
2772{
2773 buffer->raw = 0;
2774 mFrameCount = buffer->frameCount;
2775 step();
2776 buffer->frameCount = 0;
2777}
2778
2779bool AudioFlinger::ThreadBase::TrackBase::step() {
2780 bool result;
2781 audio_track_cblk_t* cblk = this->cblk();
2782
2783 result = cblk->stepServer(mFrameCount);
2784 if (!result) {
2785 LOGV("stepServer failed acquiring cblk mutex");
2786 mFlags |= STEPSERVER_FAILED;
2787 }
2788 return result;
2789}
2790
2791void AudioFlinger::ThreadBase::TrackBase::reset() {
2792 audio_track_cblk_t* cblk = this->cblk();
2793
2794 cblk->user = 0;
2795 cblk->server = 0;
2796 cblk->userBase = 0;
2797 cblk->serverBase = 0;
2798 mFlags &= (uint32_t)(~SYSTEM_FLAGS_MASK);
2799 LOGV("TrackBase::reset");
2800}
2801
2802sp<IMemory> AudioFlinger::ThreadBase::TrackBase::getCblk() const
2803{
2804 return mCblkMemory;
2805}
2806
2807int AudioFlinger::ThreadBase::TrackBase::sampleRate() const {
2808 return (int)mCblk->sampleRate;
2809}
2810
2811int AudioFlinger::ThreadBase::TrackBase::channelCount() const {
2812 return (int)mCblk->channelCount;
2813}
2814
2815void* AudioFlinger::ThreadBase::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
2816 audio_track_cblk_t* cblk = this->cblk();
2817 int8_t *bufferStart = (int8_t *)mBuffer + (offset-cblk->serverBase)*cblk->frameSize;
2818 int8_t *bufferEnd = bufferStart + frames * cblk->frameSize;
2819
2820 // Check validity of returned pointer in case the track control block would have been corrupted.
2821 if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd ||
2822 ((unsigned long)bufferStart & (unsigned long)(cblk->frameSize - 1))) {
2823 LOGE("TrackBase::getBuffer buffer out of range:\n start: %p, end %p , mBuffer %p mBufferEnd %p\n \
2824 server %d, serverBase %d, user %d, userBase %d, channelCount %d",
2825 bufferStart, bufferEnd, mBuffer, mBufferEnd,
2826 cblk->server, cblk->serverBase, cblk->user, cblk->userBase, cblk->channelCount);
2827 return 0;
2828 }
2829
2830 return bufferStart;
2831}
2832
2833// ----------------------------------------------------------------------------
2834
2835// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
2836AudioFlinger::PlaybackThread::Track::Track(
2837 const wp<ThreadBase>& thread,
2838 const sp<Client>& client,
2839 int streamType,
2840 uint32_t sampleRate,
2841 int format,
2842 int channelCount,
2843 int frameCount,
2844 const sp<IMemory>& sharedBuffer,
2845 int sessionId)
2846 : TrackBase(thread, client, sampleRate, format, channelCount, frameCount, 0, sharedBuffer, sessionId),
Eric Laurent8f45bd72010-08-31 13:50:07 -07002847 mMute(false), mSharedBuffer(sharedBuffer), mName(-1), mMainBuffer(NULL), mAuxBuffer(NULL),
2848 mAuxEffectId(0), mHasVolumeController(false)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002849{
2850 if (mCblk != NULL) {
2851 sp<ThreadBase> baseThread = thread.promote();
2852 if (baseThread != 0) {
2853 PlaybackThread *playbackThread = (PlaybackThread *)baseThread.get();
2854 mName = playbackThread->getTrackName_l();
2855 mMainBuffer = playbackThread->mixBuffer();
2856 }
2857 LOGV("Track constructor name %d, calling thread %d", mName, IPCThreadState::self()->getCallingPid());
2858 if (mName < 0) {
2859 LOGE("no more track names available");
2860 }
2861 mVolume[0] = 1.0f;
2862 mVolume[1] = 1.0f;
2863 mStreamType = streamType;
2864 // NOTE: audio_track_cblk_t::frameSize for 8 bit PCM data is based on a sample size of
2865 // 16 bit because data is converted to 16 bit before being stored in buffer by AudioTrack
Dima Zavinfce7a472011-04-19 22:30:36 -07002866 mCblk->frameSize = audio_is_linear_pcm(format) ? channelCount * sizeof(int16_t) : sizeof(int8_t);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002867 }
2868}
2869
2870AudioFlinger::PlaybackThread::Track::~Track()
2871{
2872 LOGV("PlaybackThread::Track destructor");
2873 sp<ThreadBase> thread = mThread.promote();
2874 if (thread != 0) {
2875 Mutex::Autolock _l(thread->mLock);
2876 mState = TERMINATED;
2877 }
2878}
2879
2880void AudioFlinger::PlaybackThread::Track::destroy()
2881{
2882 // NOTE: destroyTrack_l() can remove a strong reference to this Track
2883 // by removing it from mTracks vector, so there is a risk that this Tracks's
2884 // desctructor is called. As the destructor needs to lock mLock,
2885 // we must acquire a strong reference on this Track before locking mLock
2886 // here so that the destructor is called only when exiting this function.
2887 // On the other hand, as long as Track::destroy() is only called by
2888 // TrackHandle destructor, the TrackHandle still holds a strong ref on
2889 // this Track with its member mTrack.
2890 sp<Track> keep(this);
2891 { // scope for mLock
2892 sp<ThreadBase> thread = mThread.promote();
2893 if (thread != 0) {
2894 if (!isOutputTrack()) {
2895 if (mState == ACTIVE || mState == RESUMING) {
Eric Laurentde070132010-07-13 04:45:46 -07002896 AudioSystem::stopOutput(thread->id(),
Dima Zavinfce7a472011-04-19 22:30:36 -07002897 (audio_stream_type_t)mStreamType,
Eric Laurentde070132010-07-13 04:45:46 -07002898 mSessionId);
Gloria Wang9ee159b2011-02-24 14:51:45 -08002899
2900 // to track the speaker usage
2901 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002902 }
2903 AudioSystem::releaseOutput(thread->id());
2904 }
2905 Mutex::Autolock _l(thread->mLock);
2906 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
2907 playbackThread->destroyTrack_l(this);
2908 }
2909 }
2910}
2911
2912void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size)
2913{
2914 snprintf(buffer, size, " %05d %05d %03u %03u %03u %05u %04u %1d %1d %1d %05u %05u %05u 0x%08x 0x%08x 0x%08x 0x%08x\n",
2915 mName - AudioMixer::TRACK0,
2916 (mClient == NULL) ? getpid() : mClient->pid(),
2917 mStreamType,
2918 mFormat,
2919 mCblk->channelCount,
2920 mSessionId,
2921 mFrameCount,
2922 mState,
2923 mMute,
2924 mFillingUpStatus,
2925 mCblk->sampleRate,
2926 mCblk->volume[0],
2927 mCblk->volume[1],
2928 mCblk->server,
2929 mCblk->user,
2930 (int)mMainBuffer,
2931 (int)mAuxBuffer);
2932}
2933
2934status_t AudioFlinger::PlaybackThread::Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
2935{
2936 audio_track_cblk_t* cblk = this->cblk();
2937 uint32_t framesReady;
2938 uint32_t framesReq = buffer->frameCount;
2939
2940 // Check if last stepServer failed, try to step now
2941 if (mFlags & TrackBase::STEPSERVER_FAILED) {
2942 if (!step()) goto getNextBuffer_exit;
2943 LOGV("stepServer recovered");
2944 mFlags &= ~TrackBase::STEPSERVER_FAILED;
2945 }
2946
2947 framesReady = cblk->framesReady();
2948
2949 if (LIKELY(framesReady)) {
2950 uint32_t s = cblk->server;
2951 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
2952
2953 bufferEnd = (cblk->loopEnd < bufferEnd) ? cblk->loopEnd : bufferEnd;
2954 if (framesReq > framesReady) {
2955 framesReq = framesReady;
2956 }
2957 if (s + framesReq > bufferEnd) {
2958 framesReq = bufferEnd - s;
2959 }
2960
2961 buffer->raw = getBuffer(s, framesReq);
2962 if (buffer->raw == 0) goto getNextBuffer_exit;
2963
2964 buffer->frameCount = framesReq;
2965 return NO_ERROR;
2966 }
2967
2968getNextBuffer_exit:
2969 buffer->raw = 0;
2970 buffer->frameCount = 0;
2971 LOGV("getNextBuffer() no more data for track %d on thread %p", mName, mThread.unsafe_get());
2972 return NOT_ENOUGH_DATA;
2973}
2974
2975bool AudioFlinger::PlaybackThread::Track::isReady() const {
Eric Laurentaf59ce22010-10-05 14:41:42 -07002976 if (mFillingUpStatus != FS_FILLING || isStopped() || isPausing()) return true;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002977
2978 if (mCblk->framesReady() >= mCblk->frameCount ||
2979 (mCblk->flags & CBLK_FORCEREADY_MSK)) {
2980 mFillingUpStatus = FS_FILLED;
Eric Laurent38ccae22011-03-28 18:37:07 -07002981 android_atomic_and(~CBLK_FORCEREADY_MSK, &mCblk->flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002982 return true;
2983 }
2984 return false;
2985}
2986
2987status_t AudioFlinger::PlaybackThread::Track::start()
2988{
2989 status_t status = NO_ERROR;
Eric Laurentf997cab2010-07-19 06:24:46 -07002990 LOGV("start(%d), calling thread %d session %d",
2991 mName, IPCThreadState::self()->getCallingPid(), mSessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002992 sp<ThreadBase> thread = mThread.promote();
2993 if (thread != 0) {
2994 Mutex::Autolock _l(thread->mLock);
2995 int state = mState;
2996 // here the track could be either new, or restarted
2997 // in both cases "unstop" the track
2998 if (mState == PAUSED) {
2999 mState = TrackBase::RESUMING;
3000 LOGV("PAUSED => RESUMING (%d) on thread %p", mName, this);
3001 } else {
3002 mState = TrackBase::ACTIVE;
3003 LOGV("? => ACTIVE (%d) on thread %p", mName, this);
3004 }
3005
3006 if (!isOutputTrack() && state != ACTIVE && state != RESUMING) {
3007 thread->mLock.unlock();
Eric Laurentde070132010-07-13 04:45:46 -07003008 status = AudioSystem::startOutput(thread->id(),
Dima Zavinfce7a472011-04-19 22:30:36 -07003009 (audio_stream_type_t)mStreamType,
Eric Laurentde070132010-07-13 04:45:46 -07003010 mSessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003011 thread->mLock.lock();
Gloria Wang9ee159b2011-02-24 14:51:45 -08003012
3013 // to track the speaker usage
3014 if (status == NO_ERROR) {
3015 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStart);
3016 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003017 }
3018 if (status == NO_ERROR) {
3019 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3020 playbackThread->addTrack_l(this);
3021 } else {
3022 mState = state;
3023 }
3024 } else {
3025 status = BAD_VALUE;
3026 }
3027 return status;
3028}
3029
3030void AudioFlinger::PlaybackThread::Track::stop()
3031{
3032 LOGV("stop(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
3033 sp<ThreadBase> thread = mThread.promote();
3034 if (thread != 0) {
3035 Mutex::Autolock _l(thread->mLock);
3036 int state = mState;
3037 if (mState > STOPPED) {
3038 mState = STOPPED;
3039 // If the track is not active (PAUSED and buffers full), flush buffers
3040 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3041 if (playbackThread->mActiveTracks.indexOf(this) < 0) {
3042 reset();
3043 }
3044 LOGV("(> STOPPED) => STOPPED (%d) on thread %p", mName, playbackThread);
3045 }
3046 if (!isOutputTrack() && (state == ACTIVE || state == RESUMING)) {
3047 thread->mLock.unlock();
Eric Laurentde070132010-07-13 04:45:46 -07003048 AudioSystem::stopOutput(thread->id(),
Dima Zavinfce7a472011-04-19 22:30:36 -07003049 (audio_stream_type_t)mStreamType,
Eric Laurentde070132010-07-13 04:45:46 -07003050 mSessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003051 thread->mLock.lock();
Gloria Wang9ee159b2011-02-24 14:51:45 -08003052
3053 // to track the speaker usage
3054 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003055 }
3056 }
3057}
3058
3059void AudioFlinger::PlaybackThread::Track::pause()
3060{
3061 LOGV("pause(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
3062 sp<ThreadBase> thread = mThread.promote();
3063 if (thread != 0) {
3064 Mutex::Autolock _l(thread->mLock);
3065 if (mState == ACTIVE || mState == RESUMING) {
3066 mState = PAUSING;
3067 LOGV("ACTIVE/RESUMING => PAUSING (%d) on thread %p", mName, thread.get());
3068 if (!isOutputTrack()) {
3069 thread->mLock.unlock();
Eric Laurentde070132010-07-13 04:45:46 -07003070 AudioSystem::stopOutput(thread->id(),
Dima Zavinfce7a472011-04-19 22:30:36 -07003071 (audio_stream_type_t)mStreamType,
Eric Laurentde070132010-07-13 04:45:46 -07003072 mSessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003073 thread->mLock.lock();
Gloria Wang9ee159b2011-02-24 14:51:45 -08003074
3075 // to track the speaker usage
3076 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003077 }
3078 }
3079 }
3080}
3081
3082void AudioFlinger::PlaybackThread::Track::flush()
3083{
3084 LOGV("flush(%d)", mName);
3085 sp<ThreadBase> thread = mThread.promote();
3086 if (thread != 0) {
3087 Mutex::Autolock _l(thread->mLock);
3088 if (mState != STOPPED && mState != PAUSED && mState != PAUSING) {
3089 return;
3090 }
3091 // No point remaining in PAUSED state after a flush => go to
3092 // STOPPED state
3093 mState = STOPPED;
3094
Eric Laurent38ccae22011-03-28 18:37:07 -07003095 // do not reset the track if it is still in the process of being stopped or paused.
3096 // this will be done by prepareTracks_l() when the track is stopped.
3097 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3098 if (playbackThread->mActiveTracks.indexOf(this) < 0) {
3099 reset();
3100 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003101 }
3102}
3103
3104void AudioFlinger::PlaybackThread::Track::reset()
3105{
3106 // Do not reset twice to avoid discarding data written just after a flush and before
3107 // the audioflinger thread detects the track is stopped.
3108 if (!mResetDone) {
3109 TrackBase::reset();
3110 // Force underrun condition to avoid false underrun callback until first data is
3111 // written to buffer
Eric Laurent38ccae22011-03-28 18:37:07 -07003112 android_atomic_and(~CBLK_FORCEREADY_MSK, &mCblk->flags);
3113 android_atomic_or(CBLK_UNDERRUN_ON, &mCblk->flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003114 mFillingUpStatus = FS_FILLING;
3115 mResetDone = true;
3116 }
3117}
3118
3119void AudioFlinger::PlaybackThread::Track::mute(bool muted)
3120{
3121 mMute = muted;
3122}
3123
3124void AudioFlinger::PlaybackThread::Track::setVolume(float left, float right)
3125{
3126 mVolume[0] = left;
3127 mVolume[1] = right;
3128}
3129
3130status_t AudioFlinger::PlaybackThread::Track::attachAuxEffect(int EffectId)
3131{
3132 status_t status = DEAD_OBJECT;
3133 sp<ThreadBase> thread = mThread.promote();
3134 if (thread != 0) {
3135 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3136 status = playbackThread->attachAuxEffect(this, EffectId);
3137 }
3138 return status;
3139}
3140
3141void AudioFlinger::PlaybackThread::Track::setAuxBuffer(int EffectId, int32_t *buffer)
3142{
3143 mAuxEffectId = EffectId;
3144 mAuxBuffer = buffer;
3145}
3146
3147// ----------------------------------------------------------------------------
3148
3149// RecordTrack constructor must be called with AudioFlinger::mLock held
3150AudioFlinger::RecordThread::RecordTrack::RecordTrack(
3151 const wp<ThreadBase>& thread,
3152 const sp<Client>& client,
3153 uint32_t sampleRate,
3154 int format,
3155 int channelCount,
3156 int frameCount,
3157 uint32_t flags,
3158 int sessionId)
3159 : TrackBase(thread, client, sampleRate, format,
3160 channelCount, frameCount, flags, 0, sessionId),
3161 mOverflow(false)
3162{
3163 if (mCblk != NULL) {
3164 LOGV("RecordTrack constructor, size %d", (int)mBufferEnd - (int)mBuffer);
Dima Zavinfce7a472011-04-19 22:30:36 -07003165 if (format == AUDIO_FORMAT_PCM_16_BIT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003166 mCblk->frameSize = channelCount * sizeof(int16_t);
Dima Zavinfce7a472011-04-19 22:30:36 -07003167 } else if (format == AUDIO_FORMAT_PCM_8_BIT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003168 mCblk->frameSize = channelCount * sizeof(int8_t);
3169 } else {
3170 mCblk->frameSize = sizeof(int8_t);
3171 }
3172 }
3173}
3174
3175AudioFlinger::RecordThread::RecordTrack::~RecordTrack()
3176{
3177 sp<ThreadBase> thread = mThread.promote();
3178 if (thread != 0) {
3179 AudioSystem::releaseInput(thread->id());
3180 }
3181}
3182
3183status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
3184{
3185 audio_track_cblk_t* cblk = this->cblk();
3186 uint32_t framesAvail;
3187 uint32_t framesReq = buffer->frameCount;
3188
3189 // Check if last stepServer failed, try to step now
3190 if (mFlags & TrackBase::STEPSERVER_FAILED) {
3191 if (!step()) goto getNextBuffer_exit;
3192 LOGV("stepServer recovered");
3193 mFlags &= ~TrackBase::STEPSERVER_FAILED;
3194 }
3195
3196 framesAvail = cblk->framesAvailable_l();
3197
3198 if (LIKELY(framesAvail)) {
3199 uint32_t s = cblk->server;
3200 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
3201
3202 if (framesReq > framesAvail) {
3203 framesReq = framesAvail;
3204 }
3205 if (s + framesReq > bufferEnd) {
3206 framesReq = bufferEnd - s;
3207 }
3208
3209 buffer->raw = getBuffer(s, framesReq);
3210 if (buffer->raw == 0) goto getNextBuffer_exit;
3211
3212 buffer->frameCount = framesReq;
3213 return NO_ERROR;
3214 }
3215
3216getNextBuffer_exit:
3217 buffer->raw = 0;
3218 buffer->frameCount = 0;
3219 return NOT_ENOUGH_DATA;
3220}
3221
3222status_t AudioFlinger::RecordThread::RecordTrack::start()
3223{
3224 sp<ThreadBase> thread = mThread.promote();
3225 if (thread != 0) {
3226 RecordThread *recordThread = (RecordThread *)thread.get();
3227 return recordThread->start(this);
3228 } else {
3229 return BAD_VALUE;
3230 }
3231}
3232
3233void AudioFlinger::RecordThread::RecordTrack::stop()
3234{
3235 sp<ThreadBase> thread = mThread.promote();
3236 if (thread != 0) {
3237 RecordThread *recordThread = (RecordThread *)thread.get();
3238 recordThread->stop(this);
Eric Laurent38ccae22011-03-28 18:37:07 -07003239 TrackBase::reset();
3240 // Force overerrun condition to avoid false overrun callback until first data is
3241 // read from buffer
3242 android_atomic_or(CBLK_UNDERRUN_ON, &mCblk->flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003243 }
3244}
3245
3246void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size)
3247{
3248 snprintf(buffer, size, " %05d %03u %03u %05d %04u %01d %05u %08x %08x\n",
3249 (mClient == NULL) ? getpid() : mClient->pid(),
3250 mFormat,
3251 mCblk->channelCount,
3252 mSessionId,
3253 mFrameCount,
3254 mState,
3255 mCblk->sampleRate,
3256 mCblk->server,
3257 mCblk->user);
3258}
3259
3260
3261// ----------------------------------------------------------------------------
3262
3263AudioFlinger::PlaybackThread::OutputTrack::OutputTrack(
3264 const wp<ThreadBase>& thread,
3265 DuplicatingThread *sourceThread,
3266 uint32_t sampleRate,
3267 int format,
3268 int channelCount,
3269 int frameCount)
Dima Zavinfce7a472011-04-19 22:30:36 -07003270 : Track(thread, NULL, AUDIO_STREAM_CNT, sampleRate, format, channelCount, frameCount, NULL, 0),
Mathias Agopian65ab4712010-07-14 17:59:35 -07003271 mActive(false), mSourceThread(sourceThread)
3272{
3273
3274 PlaybackThread *playbackThread = (PlaybackThread *)thread.unsafe_get();
3275 if (mCblk != NULL) {
3276 mCblk->flags |= CBLK_DIRECTION_OUT;
3277 mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
3278 mCblk->volume[0] = mCblk->volume[1] = 0x1000;
3279 mOutBuffer.frameCount = 0;
3280 playbackThread->mTracks.add(this);
3281 LOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, mCblk->frameCount %d, mCblk->sampleRate %d, mCblk->channelCount %d mBufferEnd %p",
3282 mCblk, mBuffer, mCblk->buffers, mCblk->frameCount, mCblk->sampleRate, mCblk->channelCount, mBufferEnd);
3283 } else {
3284 LOGW("Error creating output track on thread %p", playbackThread);
3285 }
3286}
3287
3288AudioFlinger::PlaybackThread::OutputTrack::~OutputTrack()
3289{
3290 clearBufferQueue();
3291}
3292
3293status_t AudioFlinger::PlaybackThread::OutputTrack::start()
3294{
3295 status_t status = Track::start();
3296 if (status != NO_ERROR) {
3297 return status;
3298 }
3299
3300 mActive = true;
3301 mRetryCount = 127;
3302 return status;
3303}
3304
3305void AudioFlinger::PlaybackThread::OutputTrack::stop()
3306{
3307 Track::stop();
3308 clearBufferQueue();
3309 mOutBuffer.frameCount = 0;
3310 mActive = false;
3311}
3312
3313bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t frames)
3314{
3315 Buffer *pInBuffer;
3316 Buffer inBuffer;
3317 uint32_t channelCount = mCblk->channelCount;
3318 bool outputBufferFull = false;
3319 inBuffer.frameCount = frames;
3320 inBuffer.i16 = data;
3321
3322 uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
3323
3324 if (!mActive && frames != 0) {
3325 start();
3326 sp<ThreadBase> thread = mThread.promote();
3327 if (thread != 0) {
3328 MixerThread *mixerThread = (MixerThread *)thread.get();
3329 if (mCblk->frameCount > frames){
3330 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
3331 uint32_t startFrames = (mCblk->frameCount - frames);
3332 pInBuffer = new Buffer;
3333 pInBuffer->mBuffer = new int16_t[startFrames * channelCount];
3334 pInBuffer->frameCount = startFrames;
3335 pInBuffer->i16 = pInBuffer->mBuffer;
3336 memset(pInBuffer->raw, 0, startFrames * channelCount * sizeof(int16_t));
3337 mBufferQueue.add(pInBuffer);
3338 } else {
3339 LOGW ("OutputTrack::write() %p no more buffers in queue", this);
3340 }
3341 }
3342 }
3343 }
3344
3345 while (waitTimeLeftMs) {
3346 // First write pending buffers, then new data
3347 if (mBufferQueue.size()) {
3348 pInBuffer = mBufferQueue.itemAt(0);
3349 } else {
3350 pInBuffer = &inBuffer;
3351 }
3352
3353 if (pInBuffer->frameCount == 0) {
3354 break;
3355 }
3356
3357 if (mOutBuffer.frameCount == 0) {
3358 mOutBuffer.frameCount = pInBuffer->frameCount;
3359 nsecs_t startTime = systemTime();
3360 if (obtainBuffer(&mOutBuffer, waitTimeLeftMs) == (status_t)AudioTrack::NO_MORE_BUFFERS) {
3361 LOGV ("OutputTrack::write() %p thread %p no more output buffers", this, mThread.unsafe_get());
3362 outputBufferFull = true;
3363 break;
3364 }
3365 uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
3366 if (waitTimeLeftMs >= waitTimeMs) {
3367 waitTimeLeftMs -= waitTimeMs;
3368 } else {
3369 waitTimeLeftMs = 0;
3370 }
3371 }
3372
3373 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount : pInBuffer->frameCount;
3374 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * channelCount * sizeof(int16_t));
3375 mCblk->stepUser(outFrames);
3376 pInBuffer->frameCount -= outFrames;
3377 pInBuffer->i16 += outFrames * channelCount;
3378 mOutBuffer.frameCount -= outFrames;
3379 mOutBuffer.i16 += outFrames * channelCount;
3380
3381 if (pInBuffer->frameCount == 0) {
3382 if (mBufferQueue.size()) {
3383 mBufferQueue.removeAt(0);
3384 delete [] pInBuffer->mBuffer;
3385 delete pInBuffer;
3386 LOGV("OutputTrack::write() %p thread %p released overflow buffer %d", this, mThread.unsafe_get(), mBufferQueue.size());
3387 } else {
3388 break;
3389 }
3390 }
3391 }
3392
3393 // If we could not write all frames, allocate a buffer and queue it for next time.
3394 if (inBuffer.frameCount) {
3395 sp<ThreadBase> thread = mThread.promote();
3396 if (thread != 0 && !thread->standby()) {
3397 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
3398 pInBuffer = new Buffer;
3399 pInBuffer->mBuffer = new int16_t[inBuffer.frameCount * channelCount];
3400 pInBuffer->frameCount = inBuffer.frameCount;
3401 pInBuffer->i16 = pInBuffer->mBuffer;
3402 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * channelCount * sizeof(int16_t));
3403 mBufferQueue.add(pInBuffer);
3404 LOGV("OutputTrack::write() %p thread %p adding overflow buffer %d", this, mThread.unsafe_get(), mBufferQueue.size());
3405 } else {
3406 LOGW("OutputTrack::write() %p thread %p no more overflow buffers", mThread.unsafe_get(), this);
3407 }
3408 }
3409 }
3410
3411 // Calling write() with a 0 length buffer, means that no more data will be written:
3412 // If no more buffers are pending, fill output track buffer to make sure it is started
3413 // by output mixer.
3414 if (frames == 0 && mBufferQueue.size() == 0) {
3415 if (mCblk->user < mCblk->frameCount) {
3416 frames = mCblk->frameCount - mCblk->user;
3417 pInBuffer = new Buffer;
3418 pInBuffer->mBuffer = new int16_t[frames * channelCount];
3419 pInBuffer->frameCount = frames;
3420 pInBuffer->i16 = pInBuffer->mBuffer;
3421 memset(pInBuffer->raw, 0, frames * channelCount * sizeof(int16_t));
3422 mBufferQueue.add(pInBuffer);
3423 } else if (mActive) {
3424 stop();
3425 }
3426 }
3427
3428 return outputBufferFull;
3429}
3430
3431status_t AudioFlinger::PlaybackThread::OutputTrack::obtainBuffer(AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
3432{
3433 int active;
3434 status_t result;
3435 audio_track_cblk_t* cblk = mCblk;
3436 uint32_t framesReq = buffer->frameCount;
3437
3438// LOGV("OutputTrack::obtainBuffer user %d, server %d", cblk->user, cblk->server);
3439 buffer->frameCount = 0;
3440
3441 uint32_t framesAvail = cblk->framesAvailable();
3442
3443
3444 if (framesAvail == 0) {
3445 Mutex::Autolock _l(cblk->lock);
3446 goto start_loop_here;
3447 while (framesAvail == 0) {
3448 active = mActive;
3449 if (UNLIKELY(!active)) {
3450 LOGV("Not active and NO_MORE_BUFFERS");
3451 return AudioTrack::NO_MORE_BUFFERS;
3452 }
3453 result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
3454 if (result != NO_ERROR) {
3455 return AudioTrack::NO_MORE_BUFFERS;
3456 }
3457 // read the server count again
3458 start_loop_here:
3459 framesAvail = cblk->framesAvailable_l();
3460 }
3461 }
3462
3463// if (framesAvail < framesReq) {
3464// return AudioTrack::NO_MORE_BUFFERS;
3465// }
3466
3467 if (framesReq > framesAvail) {
3468 framesReq = framesAvail;
3469 }
3470
3471 uint32_t u = cblk->user;
3472 uint32_t bufferEnd = cblk->userBase + cblk->frameCount;
3473
3474 if (u + framesReq > bufferEnd) {
3475 framesReq = bufferEnd - u;
3476 }
3477
3478 buffer->frameCount = framesReq;
3479 buffer->raw = (void *)cblk->buffer(u);
3480 return NO_ERROR;
3481}
3482
3483
3484void AudioFlinger::PlaybackThread::OutputTrack::clearBufferQueue()
3485{
3486 size_t size = mBufferQueue.size();
3487 Buffer *pBuffer;
3488
3489 for (size_t i = 0; i < size; i++) {
3490 pBuffer = mBufferQueue.itemAt(i);
3491 delete [] pBuffer->mBuffer;
3492 delete pBuffer;
3493 }
3494 mBufferQueue.clear();
3495}
3496
3497// ----------------------------------------------------------------------------
3498
3499AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
3500 : RefBase(),
3501 mAudioFlinger(audioFlinger),
3502 mMemoryDealer(new MemoryDealer(1024*1024, "AudioFlinger::Client")),
3503 mPid(pid)
3504{
3505 // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
3506}
3507
3508// Client destructor must be called with AudioFlinger::mLock held
3509AudioFlinger::Client::~Client()
3510{
3511 mAudioFlinger->removeClient_l(mPid);
3512}
3513
3514const sp<MemoryDealer>& AudioFlinger::Client::heap() const
3515{
3516 return mMemoryDealer;
3517}
3518
3519// ----------------------------------------------------------------------------
3520
3521AudioFlinger::NotificationClient::NotificationClient(const sp<AudioFlinger>& audioFlinger,
3522 const sp<IAudioFlingerClient>& client,
3523 pid_t pid)
3524 : mAudioFlinger(audioFlinger), mPid(pid), mClient(client)
3525{
3526}
3527
3528AudioFlinger::NotificationClient::~NotificationClient()
3529{
3530 mClient.clear();
3531}
3532
3533void AudioFlinger::NotificationClient::binderDied(const wp<IBinder>& who)
3534{
3535 sp<NotificationClient> keep(this);
3536 {
3537 mAudioFlinger->removeNotificationClient(mPid);
3538 }
3539}
3540
3541// ----------------------------------------------------------------------------
3542
3543AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::PlaybackThread::Track>& track)
3544 : BnAudioTrack(),
3545 mTrack(track)
3546{
3547}
3548
3549AudioFlinger::TrackHandle::~TrackHandle() {
3550 // just stop the track on deletion, associated resources
3551 // will be freed from the main thread once all pending buffers have
3552 // been played. Unless it's not in the active track list, in which
3553 // case we free everything now...
3554 mTrack->destroy();
3555}
3556
3557status_t AudioFlinger::TrackHandle::start() {
3558 return mTrack->start();
3559}
3560
3561void AudioFlinger::TrackHandle::stop() {
3562 mTrack->stop();
3563}
3564
3565void AudioFlinger::TrackHandle::flush() {
3566 mTrack->flush();
3567}
3568
3569void AudioFlinger::TrackHandle::mute(bool e) {
3570 mTrack->mute(e);
3571}
3572
3573void AudioFlinger::TrackHandle::pause() {
3574 mTrack->pause();
3575}
3576
3577void AudioFlinger::TrackHandle::setVolume(float left, float right) {
3578 mTrack->setVolume(left, right);
3579}
3580
3581sp<IMemory> AudioFlinger::TrackHandle::getCblk() const {
3582 return mTrack->getCblk();
3583}
3584
3585status_t AudioFlinger::TrackHandle::attachAuxEffect(int EffectId)
3586{
3587 return mTrack->attachAuxEffect(EffectId);
3588}
3589
3590status_t AudioFlinger::TrackHandle::onTransact(
3591 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
3592{
3593 return BnAudioTrack::onTransact(code, data, reply, flags);
3594}
3595
3596// ----------------------------------------------------------------------------
3597
3598sp<IAudioRecord> AudioFlinger::openRecord(
3599 pid_t pid,
3600 int input,
3601 uint32_t sampleRate,
3602 int format,
3603 int channelCount,
3604 int frameCount,
3605 uint32_t flags,
3606 int *sessionId,
3607 status_t *status)
3608{
3609 sp<RecordThread::RecordTrack> recordTrack;
3610 sp<RecordHandle> recordHandle;
3611 sp<Client> client;
3612 wp<Client> wclient;
3613 status_t lStatus;
3614 RecordThread *thread;
3615 size_t inFrameCount;
3616 int lSessionId;
3617
3618 // check calling permissions
3619 if (!recordingAllowed()) {
3620 lStatus = PERMISSION_DENIED;
3621 goto Exit;
3622 }
3623
3624 // add client to list
3625 { // scope for mLock
3626 Mutex::Autolock _l(mLock);
3627 thread = checkRecordThread_l(input);
3628 if (thread == NULL) {
3629 lStatus = BAD_VALUE;
3630 goto Exit;
3631 }
3632
3633 wclient = mClients.valueFor(pid);
3634 if (wclient != NULL) {
3635 client = wclient.promote();
3636 } else {
3637 client = new Client(this, pid);
3638 mClients.add(pid, client);
3639 }
3640
3641 // If no audio session id is provided, create one here
Dima Zavinfce7a472011-04-19 22:30:36 -07003642 if (sessionId != NULL && *sessionId != AUDIO_SESSION_OUTPUT_MIX) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003643 lSessionId = *sessionId;
3644 } else {
Eric Laurentf5aafb22010-11-18 08:40:16 -08003645 lSessionId = nextUniqueId_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07003646 if (sessionId != NULL) {
3647 *sessionId = lSessionId;
3648 }
3649 }
3650 // create new record track. The record track uses one track in mHardwareMixerThread by convention.
3651 recordTrack = new RecordThread::RecordTrack(thread, client, sampleRate,
3652 format, channelCount, frameCount, flags, lSessionId);
3653 }
3654 if (recordTrack->getCblk() == NULL) {
3655 // remove local strong reference to Client before deleting the RecordTrack so that the Client
3656 // destructor is called by the TrackBase destructor with mLock held
3657 client.clear();
3658 recordTrack.clear();
3659 lStatus = NO_MEMORY;
3660 goto Exit;
3661 }
3662
3663 // return to handle to client
3664 recordHandle = new RecordHandle(recordTrack);
3665 lStatus = NO_ERROR;
3666
3667Exit:
3668 if (status) {
3669 *status = lStatus;
3670 }
3671 return recordHandle;
3672}
3673
3674// ----------------------------------------------------------------------------
3675
3676AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::RecordThread::RecordTrack>& recordTrack)
3677 : BnAudioRecord(),
3678 mRecordTrack(recordTrack)
3679{
3680}
3681
3682AudioFlinger::RecordHandle::~RecordHandle() {
3683 stop();
3684}
3685
3686status_t AudioFlinger::RecordHandle::start() {
3687 LOGV("RecordHandle::start()");
3688 return mRecordTrack->start();
3689}
3690
3691void AudioFlinger::RecordHandle::stop() {
3692 LOGV("RecordHandle::stop()");
3693 mRecordTrack->stop();
3694}
3695
3696sp<IMemory> AudioFlinger::RecordHandle::getCblk() const {
3697 return mRecordTrack->getCblk();
3698}
3699
3700status_t AudioFlinger::RecordHandle::onTransact(
3701 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
3702{
3703 return BnAudioRecord::onTransact(code, data, reply, flags);
3704}
3705
3706// ----------------------------------------------------------------------------
3707
Dima Zavinfce7a472011-04-19 22:30:36 -07003708AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, struct audio_stream_in *input, uint32_t sampleRate, uint32_t channels, int id) :
Mathias Agopian65ab4712010-07-14 17:59:35 -07003709 ThreadBase(audioFlinger, id),
3710 mInput(input), mResampler(0), mRsmpOutBuffer(0), mRsmpInBuffer(0)
3711{
Dima Zavinfce7a472011-04-19 22:30:36 -07003712 mReqChannelCount = popcount(channels);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003713 mReqSampleRate = sampleRate;
3714 readInputParameters();
3715}
3716
3717
3718AudioFlinger::RecordThread::~RecordThread()
3719{
3720 delete[] mRsmpInBuffer;
3721 if (mResampler != 0) {
3722 delete mResampler;
3723 delete[] mRsmpOutBuffer;
3724 }
3725}
3726
3727void AudioFlinger::RecordThread::onFirstRef()
3728{
3729 const size_t SIZE = 256;
3730 char buffer[SIZE];
3731
3732 snprintf(buffer, SIZE, "Record Thread %p", this);
3733
3734 run(buffer, PRIORITY_URGENT_AUDIO);
3735}
3736
3737bool AudioFlinger::RecordThread::threadLoop()
3738{
3739 AudioBufferProvider::Buffer buffer;
3740 sp<RecordTrack> activeTrack;
3741
Eric Laurent44d98482010-09-30 16:12:31 -07003742 nsecs_t lastWarning = 0;
3743
Mathias Agopian65ab4712010-07-14 17:59:35 -07003744 // start recording
3745 while (!exitPending()) {
3746
3747 processConfigEvents();
3748
3749 { // scope for mLock
3750 Mutex::Autolock _l(mLock);
3751 checkForNewParameters_l();
3752 if (mActiveTrack == 0 && mConfigEvents.isEmpty()) {
3753 if (!mStandby) {
Dima Zavinfce7a472011-04-19 22:30:36 -07003754 mInput->common.standby(&mInput->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003755 mStandby = true;
3756 }
3757
3758 if (exitPending()) break;
3759
3760 LOGV("RecordThread: loop stopping");
3761 // go to sleep
3762 mWaitWorkCV.wait(mLock);
3763 LOGV("RecordThread: loop starting");
3764 continue;
3765 }
3766 if (mActiveTrack != 0) {
3767 if (mActiveTrack->mState == TrackBase::PAUSING) {
3768 if (!mStandby) {
Dima Zavinfce7a472011-04-19 22:30:36 -07003769 mInput->common.standby(&mInput->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003770 mStandby = true;
3771 }
3772 mActiveTrack.clear();
3773 mStartStopCond.broadcast();
3774 } else if (mActiveTrack->mState == TrackBase::RESUMING) {
3775 if (mReqChannelCount != mActiveTrack->channelCount()) {
3776 mActiveTrack.clear();
3777 mStartStopCond.broadcast();
3778 } else if (mBytesRead != 0) {
3779 // record start succeeds only if first read from audio input
3780 // succeeds
3781 if (mBytesRead > 0) {
3782 mActiveTrack->mState = TrackBase::ACTIVE;
3783 } else {
3784 mActiveTrack.clear();
3785 }
3786 mStartStopCond.broadcast();
3787 }
3788 mStandby = false;
3789 }
3790 }
3791 }
3792
3793 if (mActiveTrack != 0) {
3794 if (mActiveTrack->mState != TrackBase::ACTIVE &&
3795 mActiveTrack->mState != TrackBase::RESUMING) {
3796 usleep(5000);
3797 continue;
3798 }
3799 buffer.frameCount = mFrameCount;
3800 if (LIKELY(mActiveTrack->getNextBuffer(&buffer) == NO_ERROR)) {
3801 size_t framesOut = buffer.frameCount;
3802 if (mResampler == 0) {
3803 // no resampling
3804 while (framesOut) {
3805 size_t framesIn = mFrameCount - mRsmpInIndex;
3806 if (framesIn) {
3807 int8_t *src = (int8_t *)mRsmpInBuffer + mRsmpInIndex * mFrameSize;
3808 int8_t *dst = buffer.i8 + (buffer.frameCount - framesOut) * mActiveTrack->mCblk->frameSize;
3809 if (framesIn > framesOut)
3810 framesIn = framesOut;
3811 mRsmpInIndex += framesIn;
3812 framesOut -= framesIn;
3813 if ((int)mChannelCount == mReqChannelCount ||
Dima Zavinfce7a472011-04-19 22:30:36 -07003814 mFormat != AUDIO_FORMAT_PCM_16_BIT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003815 memcpy(dst, src, framesIn * mFrameSize);
3816 } else {
3817 int16_t *src16 = (int16_t *)src;
3818 int16_t *dst16 = (int16_t *)dst;
3819 if (mChannelCount == 1) {
3820 while (framesIn--) {
3821 *dst16++ = *src16;
3822 *dst16++ = *src16++;
3823 }
3824 } else {
3825 while (framesIn--) {
3826 *dst16++ = (int16_t)(((int32_t)*src16 + (int32_t)*(src16 + 1)) >> 1);
3827 src16 += 2;
3828 }
3829 }
3830 }
3831 }
3832 if (framesOut && mFrameCount == mRsmpInIndex) {
3833 if (framesOut == mFrameCount &&
Dima Zavinfce7a472011-04-19 22:30:36 -07003834 ((int)mChannelCount == mReqChannelCount || mFormat != AUDIO_FORMAT_PCM_16_BIT)) {
3835 mBytesRead = mInput->read(mInput, buffer.raw, mInputBytes);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003836 framesOut = 0;
3837 } else {
Dima Zavinfce7a472011-04-19 22:30:36 -07003838 mBytesRead = mInput->read(mInput, mRsmpInBuffer, mInputBytes);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003839 mRsmpInIndex = 0;
3840 }
3841 if (mBytesRead < 0) {
3842 LOGE("Error reading audio input");
3843 if (mActiveTrack->mState == TrackBase::ACTIVE) {
3844 // Force input into standby so that it tries to
3845 // recover at next read attempt
Dima Zavinfce7a472011-04-19 22:30:36 -07003846 mInput->common.standby(&mInput->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003847 usleep(5000);
3848 }
3849 mRsmpInIndex = mFrameCount;
3850 framesOut = 0;
3851 buffer.frameCount = 0;
3852 }
3853 }
3854 }
3855 } else {
3856 // resampling
3857
3858 memset(mRsmpOutBuffer, 0, framesOut * 2 * sizeof(int32_t));
3859 // alter output frame count as if we were expecting stereo samples
3860 if (mChannelCount == 1 && mReqChannelCount == 1) {
3861 framesOut >>= 1;
3862 }
3863 mResampler->resample(mRsmpOutBuffer, framesOut, this);
3864 // ditherAndClamp() works as long as all buffers returned by mActiveTrack->getNextBuffer()
3865 // are 32 bit aligned which should be always true.
3866 if (mChannelCount == 2 && mReqChannelCount == 1) {
3867 AudioMixer::ditherAndClamp(mRsmpOutBuffer, mRsmpOutBuffer, framesOut);
3868 // the resampler always outputs stereo samples: do post stereo to mono conversion
3869 int16_t *src = (int16_t *)mRsmpOutBuffer;
3870 int16_t *dst = buffer.i16;
3871 while (framesOut--) {
3872 *dst++ = (int16_t)(((int32_t)*src + (int32_t)*(src + 1)) >> 1);
3873 src += 2;
3874 }
3875 } else {
3876 AudioMixer::ditherAndClamp((int32_t *)buffer.raw, mRsmpOutBuffer, framesOut);
3877 }
3878
3879 }
3880 mActiveTrack->releaseBuffer(&buffer);
3881 mActiveTrack->overflow();
3882 }
3883 // client isn't retrieving buffers fast enough
3884 else {
Eric Laurent44d98482010-09-30 16:12:31 -07003885 if (!mActiveTrack->setOverflow()) {
3886 nsecs_t now = systemTime();
3887 if ((now - lastWarning) > kWarningThrottle) {
3888 LOGW("RecordThread: buffer overflow");
3889 lastWarning = now;
3890 }
3891 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003892 // Release the processor for a while before asking for a new buffer.
3893 // This will give the application more chance to read from the buffer and
3894 // clear the overflow.
3895 usleep(5000);
3896 }
3897 }
3898 }
3899
3900 if (!mStandby) {
Dima Zavinfce7a472011-04-19 22:30:36 -07003901 mInput->common.standby(&mInput->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003902 }
3903 mActiveTrack.clear();
3904
3905 mStartStopCond.broadcast();
3906
3907 LOGV("RecordThread %p exiting", this);
3908 return false;
3909}
3910
3911status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack)
3912{
3913 LOGV("RecordThread::start");
3914 sp <ThreadBase> strongMe = this;
3915 status_t status = NO_ERROR;
3916 {
3917 AutoMutex lock(&mLock);
3918 if (mActiveTrack != 0) {
3919 if (recordTrack != mActiveTrack.get()) {
3920 status = -EBUSY;
3921 } else if (mActiveTrack->mState == TrackBase::PAUSING) {
3922 mActiveTrack->mState = TrackBase::ACTIVE;
3923 }
3924 return status;
3925 }
3926
3927 recordTrack->mState = TrackBase::IDLE;
3928 mActiveTrack = recordTrack;
3929 mLock.unlock();
3930 status_t status = AudioSystem::startInput(mId);
3931 mLock.lock();
3932 if (status != NO_ERROR) {
3933 mActiveTrack.clear();
3934 return status;
3935 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003936 mRsmpInIndex = mFrameCount;
3937 mBytesRead = 0;
Eric Laurent243f5f92011-02-28 16:52:51 -08003938 if (mResampler != NULL) {
3939 mResampler->reset();
3940 }
3941 mActiveTrack->mState = TrackBase::RESUMING;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003942 // signal thread to start
3943 LOGV("Signal record thread");
3944 mWaitWorkCV.signal();
3945 // do not wait for mStartStopCond if exiting
3946 if (mExiting) {
3947 mActiveTrack.clear();
3948 status = INVALID_OPERATION;
3949 goto startError;
3950 }
3951 mStartStopCond.wait(mLock);
3952 if (mActiveTrack == 0) {
3953 LOGV("Record failed to start");
3954 status = BAD_VALUE;
3955 goto startError;
3956 }
3957 LOGV("Record started OK");
3958 return status;
3959 }
3960startError:
3961 AudioSystem::stopInput(mId);
3962 return status;
3963}
3964
3965void AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) {
3966 LOGV("RecordThread::stop");
3967 sp <ThreadBase> strongMe = this;
3968 {
3969 AutoMutex lock(&mLock);
3970 if (mActiveTrack != 0 && recordTrack == mActiveTrack.get()) {
3971 mActiveTrack->mState = TrackBase::PAUSING;
3972 // do not wait for mStartStopCond if exiting
3973 if (mExiting) {
3974 return;
3975 }
3976 mStartStopCond.wait(mLock);
3977 // if we have been restarted, recordTrack == mActiveTrack.get() here
3978 if (mActiveTrack == 0 || recordTrack != mActiveTrack.get()) {
3979 mLock.unlock();
3980 AudioSystem::stopInput(mId);
3981 mLock.lock();
3982 LOGV("Record stopped OK");
3983 }
3984 }
3985 }
3986}
3987
3988status_t AudioFlinger::RecordThread::dump(int fd, const Vector<String16>& args)
3989{
3990 const size_t SIZE = 256;
3991 char buffer[SIZE];
3992 String8 result;
3993 pid_t pid = 0;
3994
3995 snprintf(buffer, SIZE, "\nInput thread %p internals\n", this);
3996 result.append(buffer);
3997
3998 if (mActiveTrack != 0) {
3999 result.append("Active Track:\n");
4000 result.append(" Clien Fmt Chn Session Buf S SRate Serv User\n");
4001 mActiveTrack->dump(buffer, SIZE);
4002 result.append(buffer);
4003
4004 snprintf(buffer, SIZE, "In index: %d\n", mRsmpInIndex);
4005 result.append(buffer);
4006 snprintf(buffer, SIZE, "In size: %d\n", mInputBytes);
4007 result.append(buffer);
4008 snprintf(buffer, SIZE, "Resampling: %d\n", (mResampler != 0));
4009 result.append(buffer);
4010 snprintf(buffer, SIZE, "Out channel count: %d\n", mReqChannelCount);
4011 result.append(buffer);
4012 snprintf(buffer, SIZE, "Out sample rate: %d\n", mReqSampleRate);
4013 result.append(buffer);
4014
4015
4016 } else {
4017 result.append("No record client\n");
4018 }
4019 write(fd, result.string(), result.size());
4020
4021 dumpBase(fd, args);
4022
4023 return NO_ERROR;
4024}
4025
4026status_t AudioFlinger::RecordThread::getNextBuffer(AudioBufferProvider::Buffer* buffer)
4027{
4028 size_t framesReq = buffer->frameCount;
4029 size_t framesReady = mFrameCount - mRsmpInIndex;
4030 int channelCount;
4031
4032 if (framesReady == 0) {
Dima Zavinfce7a472011-04-19 22:30:36 -07004033 mBytesRead = mInput->read(mInput, mRsmpInBuffer, mInputBytes);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004034 if (mBytesRead < 0) {
4035 LOGE("RecordThread::getNextBuffer() Error reading audio input");
4036 if (mActiveTrack->mState == TrackBase::ACTIVE) {
4037 // Force input into standby so that it tries to
4038 // recover at next read attempt
Dima Zavinfce7a472011-04-19 22:30:36 -07004039 mInput->common.standby(&mInput->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004040 usleep(5000);
4041 }
4042 buffer->raw = 0;
4043 buffer->frameCount = 0;
4044 return NOT_ENOUGH_DATA;
4045 }
4046 mRsmpInIndex = 0;
4047 framesReady = mFrameCount;
4048 }
4049
4050 if (framesReq > framesReady) {
4051 framesReq = framesReady;
4052 }
4053
4054 if (mChannelCount == 1 && mReqChannelCount == 2) {
4055 channelCount = 1;
4056 } else {
4057 channelCount = 2;
4058 }
4059 buffer->raw = mRsmpInBuffer + mRsmpInIndex * channelCount;
4060 buffer->frameCount = framesReq;
4061 return NO_ERROR;
4062}
4063
4064void AudioFlinger::RecordThread::releaseBuffer(AudioBufferProvider::Buffer* buffer)
4065{
4066 mRsmpInIndex += buffer->frameCount;
4067 buffer->frameCount = 0;
4068}
4069
4070bool AudioFlinger::RecordThread::checkForNewParameters_l()
4071{
4072 bool reconfig = false;
4073
4074 while (!mNewParameters.isEmpty()) {
4075 status_t status = NO_ERROR;
4076 String8 keyValuePair = mNewParameters[0];
4077 AudioParameter param = AudioParameter(keyValuePair);
4078 int value;
4079 int reqFormat = mFormat;
4080 int reqSamplingRate = mReqSampleRate;
4081 int reqChannelCount = mReqChannelCount;
4082
4083 if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
4084 reqSamplingRate = value;
4085 reconfig = true;
4086 }
4087 if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
4088 reqFormat = value;
4089 reconfig = true;
4090 }
4091 if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
Dima Zavinfce7a472011-04-19 22:30:36 -07004092 reqChannelCount = popcount(value);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004093 reconfig = true;
4094 }
4095 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
4096 // do not accept frame count changes if tracks are open as the track buffer
4097 // size depends on frame count and correct behavior would not be garantied
4098 // if frame count is changed after track creation
4099 if (mActiveTrack != 0) {
4100 status = INVALID_OPERATION;
4101 } else {
4102 reconfig = true;
4103 }
4104 }
4105 if (status == NO_ERROR) {
Dima Zavinfce7a472011-04-19 22:30:36 -07004106 status = mInput->common.set_parameters(&mInput->common, keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07004107 if (status == INVALID_OPERATION) {
Dima Zavinfce7a472011-04-19 22:30:36 -07004108 mInput->common.standby(&mInput->common);
4109 status = mInput->common.set_parameters(&mInput->common, keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07004110 }
4111 if (reconfig) {
4112 if (status == BAD_VALUE &&
Dima Zavinfce7a472011-04-19 22:30:36 -07004113 reqFormat == mInput->common.get_format(&mInput->common) &&
4114 reqFormat == AUDIO_FORMAT_PCM_16_BIT &&
4115 ((int)mInput->common.get_sample_rate(&mInput->common) <= (2 * reqSamplingRate)) &&
4116 (popcount(mInput->common.get_channels(&mInput->common)) < 3) &&
4117 (reqChannelCount < 3)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004118 status = NO_ERROR;
4119 }
4120 if (status == NO_ERROR) {
4121 readInputParameters();
4122 sendConfigEvent_l(AudioSystem::INPUT_CONFIG_CHANGED);
4123 }
4124 }
4125 }
4126
4127 mNewParameters.removeAt(0);
4128
4129 mParamStatus = status;
4130 mParamCond.signal();
4131 mWaitWorkCV.wait(mLock);
4132 }
4133 return reconfig;
4134}
4135
4136String8 AudioFlinger::RecordThread::getParameters(const String8& keys)
4137{
Dima Zavinfce7a472011-04-19 22:30:36 -07004138 char *s;
4139 String8 out_s8;
4140
4141 s = mInput->common.get_parameters(&mInput->common, keys.string());
4142 out_s8 = String8(s);
4143 free(s);
4144 return out_s8;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004145}
4146
4147void AudioFlinger::RecordThread::audioConfigChanged_l(int event, int param) {
4148 AudioSystem::OutputDescriptor desc;
4149 void *param2 = 0;
4150
4151 switch (event) {
4152 case AudioSystem::INPUT_OPENED:
4153 case AudioSystem::INPUT_CONFIG_CHANGED:
4154 desc.channels = mChannels;
4155 desc.samplingRate = mSampleRate;
4156 desc.format = mFormat;
4157 desc.frameCount = mFrameCount;
4158 desc.latency = 0;
4159 param2 = &desc;
4160 break;
4161
4162 case AudioSystem::INPUT_CLOSED:
4163 default:
4164 break;
4165 }
4166 mAudioFlinger->audioConfigChanged_l(event, mId, param2);
4167}
4168
4169void AudioFlinger::RecordThread::readInputParameters()
4170{
4171 if (mRsmpInBuffer) delete mRsmpInBuffer;
4172 if (mRsmpOutBuffer) delete mRsmpOutBuffer;
4173 if (mResampler) delete mResampler;
4174 mResampler = 0;
4175
Dima Zavinfce7a472011-04-19 22:30:36 -07004176 mSampleRate = mInput->common.get_sample_rate(&mInput->common);
4177 mChannels = mInput->common.get_channels(&mInput->common);
4178 mChannelCount = (uint16_t)popcount(mChannels);
4179 mFormat = mInput->common.get_format(&mInput->common);
4180 mFrameSize = (uint16_t)audio_stream_frame_size(&mInput->common);
4181 mInputBytes = mInput->common.get_buffer_size(&mInput->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004182 mFrameCount = mInputBytes / mFrameSize;
4183 mRsmpInBuffer = new int16_t[mFrameCount * mChannelCount];
4184
4185 if (mSampleRate != mReqSampleRate && mChannelCount < 3 && mReqChannelCount < 3)
4186 {
4187 int channelCount;
4188 // optmization: if mono to mono, use the resampler in stereo to stereo mode to avoid
4189 // stereo to mono post process as the resampler always outputs stereo.
4190 if (mChannelCount == 1 && mReqChannelCount == 2) {
4191 channelCount = 1;
4192 } else {
4193 channelCount = 2;
4194 }
4195 mResampler = AudioResampler::create(16, channelCount, mReqSampleRate);
4196 mResampler->setSampleRate(mSampleRate);
4197 mResampler->setVolume(AudioMixer::UNITY_GAIN, AudioMixer::UNITY_GAIN);
4198 mRsmpOutBuffer = new int32_t[mFrameCount * 2];
4199
4200 // optmization: if mono to mono, alter input frame count as if we were inputing stereo samples
4201 if (mChannelCount == 1 && mReqChannelCount == 1) {
4202 mFrameCount >>= 1;
4203 }
4204
4205 }
4206 mRsmpInIndex = mFrameCount;
4207}
4208
4209unsigned int AudioFlinger::RecordThread::getInputFramesLost()
4210{
Dima Zavinfce7a472011-04-19 22:30:36 -07004211 return mInput->get_input_frames_lost(mInput);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004212}
4213
4214// ----------------------------------------------------------------------------
4215
4216int AudioFlinger::openOutput(uint32_t *pDevices,
4217 uint32_t *pSamplingRate,
4218 uint32_t *pFormat,
4219 uint32_t *pChannels,
4220 uint32_t *pLatencyMs,
4221 uint32_t flags)
4222{
4223 status_t status;
4224 PlaybackThread *thread = NULL;
4225 mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
4226 uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
4227 uint32_t format = pFormat ? *pFormat : 0;
4228 uint32_t channels = pChannels ? *pChannels : 0;
4229 uint32_t latency = pLatencyMs ? *pLatencyMs : 0;
Dima Zavinfce7a472011-04-19 22:30:36 -07004230 struct audio_stream_out *output;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004231
4232 LOGV("openOutput(), Device %x, SamplingRate %d, Format %d, Channels %x, flags %x",
4233 pDevices ? *pDevices : 0,
4234 samplingRate,
4235 format,
4236 channels,
4237 flags);
4238
4239 if (pDevices == NULL || *pDevices == 0) {
4240 return 0;
4241 }
4242 Mutex::Autolock _l(mLock);
4243
Dima Zavinfce7a472011-04-19 22:30:36 -07004244 status = mAudioHardwareDev->open_output_stream(mAudioHardwareDev, *pDevices,
4245 (int *)&format,
4246 &channels,
4247 &samplingRate,
4248 &output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004249 LOGV("openOutput() openOutputStream returned output %p, SamplingRate %d, Format %d, Channels %x, status %d",
4250 output,
4251 samplingRate,
4252 format,
4253 channels,
4254 status);
4255
4256 mHardwareStatus = AUDIO_HW_IDLE;
4257 if (output != 0) {
Eric Laurentf5aafb22010-11-18 08:40:16 -08004258 int id = nextUniqueId_l();
Dima Zavinfce7a472011-04-19 22:30:36 -07004259 if ((flags & AUDIO_POLICY_OUTPUT_FLAG_DIRECT) ||
4260 (format != AUDIO_FORMAT_PCM_16_BIT) ||
4261 (channels != AUDIO_CHANNEL_OUT_STEREO)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004262 thread = new DirectOutputThread(this, output, id, *pDevices);
4263 LOGV("openOutput() created direct output: ID %d thread %p", id, thread);
4264 } else {
4265 thread = new MixerThread(this, output, id, *pDevices);
4266 LOGV("openOutput() created mixer output: ID %d thread %p", id, thread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004267 }
4268 mPlaybackThreads.add(id, thread);
4269
4270 if (pSamplingRate) *pSamplingRate = samplingRate;
4271 if (pFormat) *pFormat = format;
4272 if (pChannels) *pChannels = channels;
4273 if (pLatencyMs) *pLatencyMs = thread->latency();
4274
4275 // notify client processes of the new output creation
4276 thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
4277 return id;
4278 }
4279
4280 return 0;
4281}
4282
4283int AudioFlinger::openDuplicateOutput(int output1, int output2)
4284{
4285 Mutex::Autolock _l(mLock);
4286 MixerThread *thread1 = checkMixerThread_l(output1);
4287 MixerThread *thread2 = checkMixerThread_l(output2);
4288
4289 if (thread1 == NULL || thread2 == NULL) {
4290 LOGW("openDuplicateOutput() wrong output mixer type for output %d or %d", output1, output2);
4291 return 0;
4292 }
4293
Eric Laurentf5aafb22010-11-18 08:40:16 -08004294 int id = nextUniqueId_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07004295 DuplicatingThread *thread = new DuplicatingThread(this, thread1, id);
4296 thread->addOutputTrack(thread2);
4297 mPlaybackThreads.add(id, thread);
4298 // notify client processes of the new output creation
4299 thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
4300 return id;
4301}
4302
4303status_t AudioFlinger::closeOutput(int output)
4304{
4305 // keep strong reference on the playback thread so that
4306 // it is not destroyed while exit() is executed
4307 sp <PlaybackThread> thread;
4308 {
4309 Mutex::Autolock _l(mLock);
4310 thread = checkPlaybackThread_l(output);
4311 if (thread == NULL) {
4312 return BAD_VALUE;
4313 }
4314
4315 LOGV("closeOutput() %d", output);
4316
4317 if (thread->type() == PlaybackThread::MIXER) {
4318 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
4319 if (mPlaybackThreads.valueAt(i)->type() == PlaybackThread::DUPLICATING) {
4320 DuplicatingThread *dupThread = (DuplicatingThread *)mPlaybackThreads.valueAt(i).get();
4321 dupThread->removeOutputTrack((MixerThread *)thread.get());
4322 }
4323 }
4324 }
4325 void *param2 = 0;
4326 audioConfigChanged_l(AudioSystem::OUTPUT_CLOSED, output, param2);
4327 mPlaybackThreads.removeItem(output);
4328 }
4329 thread->exit();
4330
4331 if (thread->type() != PlaybackThread::DUPLICATING) {
Dima Zavinfce7a472011-04-19 22:30:36 -07004332 mAudioHardwareDev->close_output_stream(mAudioHardwareDev, thread->getOutput());
Mathias Agopian65ab4712010-07-14 17:59:35 -07004333 }
4334 return NO_ERROR;
4335}
4336
4337status_t AudioFlinger::suspendOutput(int output)
4338{
4339 Mutex::Autolock _l(mLock);
4340 PlaybackThread *thread = checkPlaybackThread_l(output);
4341
4342 if (thread == NULL) {
4343 return BAD_VALUE;
4344 }
4345
4346 LOGV("suspendOutput() %d", output);
4347 thread->suspend();
4348
4349 return NO_ERROR;
4350}
4351
4352status_t AudioFlinger::restoreOutput(int output)
4353{
4354 Mutex::Autolock _l(mLock);
4355 PlaybackThread *thread = checkPlaybackThread_l(output);
4356
4357 if (thread == NULL) {
4358 return BAD_VALUE;
4359 }
4360
4361 LOGV("restoreOutput() %d", output);
4362
4363 thread->restore();
4364
4365 return NO_ERROR;
4366}
4367
4368int AudioFlinger::openInput(uint32_t *pDevices,
4369 uint32_t *pSamplingRate,
4370 uint32_t *pFormat,
4371 uint32_t *pChannels,
4372 uint32_t acoustics)
4373{
4374 status_t status;
4375 RecordThread *thread = NULL;
4376 uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
4377 uint32_t format = pFormat ? *pFormat : 0;
4378 uint32_t channels = pChannels ? *pChannels : 0;
4379 uint32_t reqSamplingRate = samplingRate;
4380 uint32_t reqFormat = format;
4381 uint32_t reqChannels = channels;
Dima Zavinfce7a472011-04-19 22:30:36 -07004382 struct audio_stream_in *input;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004383
4384 if (pDevices == NULL || *pDevices == 0) {
4385 return 0;
4386 }
4387 Mutex::Autolock _l(mLock);
4388
Dima Zavinfce7a472011-04-19 22:30:36 -07004389 status = mAudioHardwareDev->open_input_stream(mAudioHardwareDev,
4390 *pDevices,
4391 (int *)&format,
4392 &channels,
4393 &samplingRate,
4394 (audio_in_acoustics_t)acoustics,
4395 &input);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004396 LOGV("openInput() openInputStream returned input %p, SamplingRate %d, Format %d, Channels %x, acoustics %x, status %d",
4397 input,
4398 samplingRate,
4399 format,
4400 channels,
4401 acoustics,
4402 status);
4403
4404 // If the input could not be opened with the requested parameters and we can handle the conversion internally,
4405 // try to open again with the proposed parameters. The AudioFlinger can resample the input and do mono to stereo
4406 // or stereo to mono conversions on 16 bit PCM inputs.
4407 if (input == 0 && status == BAD_VALUE &&
Dima Zavinfce7a472011-04-19 22:30:36 -07004408 reqFormat == format && format == AUDIO_FORMAT_PCM_16_BIT &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07004409 (samplingRate <= 2 * reqSamplingRate) &&
Dima Zavinfce7a472011-04-19 22:30:36 -07004410 (popcount(channels) < 3) && (popcount(reqChannels) < 3)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004411 LOGV("openInput() reopening with proposed sampling rate and channels");
Dima Zavinfce7a472011-04-19 22:30:36 -07004412 status = mAudioHardwareDev->open_input_stream(mAudioHardwareDev,
4413 *pDevices,
4414 (int *)&format,
4415 &channels,
4416 &samplingRate,
4417 (audio_in_acoustics_t)acoustics,
4418 &input);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004419 }
4420
4421 if (input != 0) {
Eric Laurentf5aafb22010-11-18 08:40:16 -08004422 int id = nextUniqueId_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07004423 // Start record thread
4424 thread = new RecordThread(this, input, reqSamplingRate, reqChannels, id);
4425 mRecordThreads.add(id, thread);
4426 LOGV("openInput() created record thread: ID %d thread %p", id, thread);
4427 if (pSamplingRate) *pSamplingRate = reqSamplingRate;
4428 if (pFormat) *pFormat = format;
4429 if (pChannels) *pChannels = reqChannels;
4430
Dima Zavinfce7a472011-04-19 22:30:36 -07004431 input->common.standby(&input->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004432
4433 // notify client processes of the new input creation
4434 thread->audioConfigChanged_l(AudioSystem::INPUT_OPENED);
4435 return id;
4436 }
4437
4438 return 0;
4439}
4440
4441status_t AudioFlinger::closeInput(int input)
4442{
4443 // keep strong reference on the record thread so that
4444 // it is not destroyed while exit() is executed
4445 sp <RecordThread> thread;
4446 {
4447 Mutex::Autolock _l(mLock);
4448 thread = checkRecordThread_l(input);
4449 if (thread == NULL) {
4450 return BAD_VALUE;
4451 }
4452
4453 LOGV("closeInput() %d", input);
4454 void *param2 = 0;
4455 audioConfigChanged_l(AudioSystem::INPUT_CLOSED, input, param2);
4456 mRecordThreads.removeItem(input);
4457 }
4458 thread->exit();
4459
Dima Zavinfce7a472011-04-19 22:30:36 -07004460 mAudioHardwareDev->close_input_stream(mAudioHardwareDev, thread->getInput());
Mathias Agopian65ab4712010-07-14 17:59:35 -07004461
4462 return NO_ERROR;
4463}
4464
4465status_t AudioFlinger::setStreamOutput(uint32_t stream, int output)
4466{
4467 Mutex::Autolock _l(mLock);
4468 MixerThread *dstThread = checkMixerThread_l(output);
4469 if (dstThread == NULL) {
4470 LOGW("setStreamOutput() bad output id %d", output);
4471 return BAD_VALUE;
4472 }
4473
4474 LOGV("setStreamOutput() stream %d to output %d", stream, output);
4475 audioConfigChanged_l(AudioSystem::STREAM_CONFIG_CHANGED, output, &stream);
4476
4477 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
4478 PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
4479 if (thread != dstThread &&
4480 thread->type() != PlaybackThread::DIRECT) {
4481 MixerThread *srcThread = (MixerThread *)thread;
4482 srcThread->invalidateTracks(stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004483 }
Eric Laurentde070132010-07-13 04:45:46 -07004484 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07004485
4486 return NO_ERROR;
4487}
4488
4489
4490int AudioFlinger::newAudioSessionId()
4491{
Eric Laurentf5aafb22010-11-18 08:40:16 -08004492 AutoMutex _l(mLock);
4493 return nextUniqueId_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07004494}
4495
4496// checkPlaybackThread_l() must be called with AudioFlinger::mLock held
4497AudioFlinger::PlaybackThread *AudioFlinger::checkPlaybackThread_l(int output) const
4498{
4499 PlaybackThread *thread = NULL;
4500 if (mPlaybackThreads.indexOfKey(output) >= 0) {
4501 thread = (PlaybackThread *)mPlaybackThreads.valueFor(output).get();
4502 }
4503 return thread;
4504}
4505
4506// checkMixerThread_l() must be called with AudioFlinger::mLock held
4507AudioFlinger::MixerThread *AudioFlinger::checkMixerThread_l(int output) const
4508{
4509 PlaybackThread *thread = checkPlaybackThread_l(output);
4510 if (thread != NULL) {
4511 if (thread->type() == PlaybackThread::DIRECT) {
4512 thread = NULL;
4513 }
4514 }
4515 return (MixerThread *)thread;
4516}
4517
4518// checkRecordThread_l() must be called with AudioFlinger::mLock held
4519AudioFlinger::RecordThread *AudioFlinger::checkRecordThread_l(int input) const
4520{
4521 RecordThread *thread = NULL;
4522 if (mRecordThreads.indexOfKey(input) >= 0) {
4523 thread = (RecordThread *)mRecordThreads.valueFor(input).get();
4524 }
4525 return thread;
4526}
4527
Eric Laurentf5aafb22010-11-18 08:40:16 -08004528// nextUniqueId_l() must be called with AudioFlinger::mLock held
4529int AudioFlinger::nextUniqueId_l()
Mathias Agopian65ab4712010-07-14 17:59:35 -07004530{
Eric Laurentf5aafb22010-11-18 08:40:16 -08004531 return mNextUniqueId++;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004532}
4533
4534// ----------------------------------------------------------------------------
4535// Effect management
4536// ----------------------------------------------------------------------------
4537
4538
4539status_t AudioFlinger::loadEffectLibrary(const char *libPath, int *handle)
4540{
Eric Laurentde070132010-07-13 04:45:46 -07004541 // check calling permissions
4542 if (!settingsAllowed()) {
4543 return PERMISSION_DENIED;
4544 }
4545 // only allow libraries loaded from /system/lib/soundfx for now
4546 if (strncmp(gEffectLibPath, libPath, strlen(gEffectLibPath)) != 0) {
4547 return PERMISSION_DENIED;
4548 }
4549
Mathias Agopian65ab4712010-07-14 17:59:35 -07004550 Mutex::Autolock _l(mLock);
4551 return EffectLoadLibrary(libPath, handle);
4552}
4553
4554status_t AudioFlinger::unloadEffectLibrary(int handle)
4555{
Eric Laurentde070132010-07-13 04:45:46 -07004556 // check calling permissions
4557 if (!settingsAllowed()) {
4558 return PERMISSION_DENIED;
4559 }
4560
Mathias Agopian65ab4712010-07-14 17:59:35 -07004561 Mutex::Autolock _l(mLock);
4562 return EffectUnloadLibrary(handle);
4563}
4564
4565status_t AudioFlinger::queryNumberEffects(uint32_t *numEffects)
4566{
4567 Mutex::Autolock _l(mLock);
4568 return EffectQueryNumberEffects(numEffects);
4569}
4570
4571status_t AudioFlinger::queryEffect(uint32_t index, effect_descriptor_t *descriptor)
4572{
4573 Mutex::Autolock _l(mLock);
4574 return EffectQueryEffect(index, descriptor);
4575}
4576
4577status_t AudioFlinger::getEffectDescriptor(effect_uuid_t *pUuid, effect_descriptor_t *descriptor)
4578{
4579 Mutex::Autolock _l(mLock);
4580 return EffectGetDescriptor(pUuid, descriptor);
4581}
4582
4583
4584// this UUID must match the one defined in media/libeffects/EffectVisualizer.cpp
4585static const effect_uuid_t VISUALIZATION_UUID_ =
4586 {0xd069d9e0, 0x8329, 0x11df, 0x9168, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
4587
4588sp<IEffect> AudioFlinger::createEffect(pid_t pid,
4589 effect_descriptor_t *pDesc,
4590 const sp<IEffectClient>& effectClient,
4591 int32_t priority,
4592 int output,
4593 int sessionId,
4594 status_t *status,
4595 int *id,
4596 int *enabled)
4597{
4598 status_t lStatus = NO_ERROR;
4599 sp<EffectHandle> handle;
4600 effect_interface_t itfe;
4601 effect_descriptor_t desc;
4602 sp<Client> client;
4603 wp<Client> wclient;
4604
Eric Laurentde070132010-07-13 04:45:46 -07004605 LOGV("createEffect pid %d, client %p, priority %d, sessionId %d, output %d",
4606 pid, effectClient.get(), priority, sessionId, output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004607
4608 if (pDesc == NULL) {
4609 lStatus = BAD_VALUE;
4610 goto Exit;
4611 }
4612
Eric Laurent84e9a102010-09-23 16:10:16 -07004613 // check audio settings permission for global effects
Dima Zavinfce7a472011-04-19 22:30:36 -07004614 if (sessionId == AUDIO_SESSION_OUTPUT_MIX && !settingsAllowed()) {
Eric Laurent84e9a102010-09-23 16:10:16 -07004615 lStatus = PERMISSION_DENIED;
4616 goto Exit;
4617 }
4618
Dima Zavinfce7a472011-04-19 22:30:36 -07004619 // Session AUDIO_SESSION_OUTPUT_STAGE is reserved for output stage effects
Eric Laurent84e9a102010-09-23 16:10:16 -07004620 // that can only be created by audio policy manager (running in same process)
Dima Zavinfce7a472011-04-19 22:30:36 -07004621 if (sessionId == AUDIO_SESSION_OUTPUT_STAGE && getpid() != pid) {
Eric Laurent84e9a102010-09-23 16:10:16 -07004622 lStatus = PERMISSION_DENIED;
4623 goto Exit;
4624 }
4625
4626 // check recording permission for visualizer
4627 if ((memcmp(&pDesc->type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0 ||
4628 memcmp(&pDesc->uuid, &VISUALIZATION_UUID_, sizeof(effect_uuid_t)) == 0) &&
4629 !recordingAllowed()) {
4630 lStatus = PERMISSION_DENIED;
4631 goto Exit;
4632 }
4633
4634 if (output == 0) {
Dima Zavinfce7a472011-04-19 22:30:36 -07004635 if (sessionId == AUDIO_SESSION_OUTPUT_STAGE) {
Eric Laurent84e9a102010-09-23 16:10:16 -07004636 // output must be specified by AudioPolicyManager when using session
Dima Zavinfce7a472011-04-19 22:30:36 -07004637 // AUDIO_SESSION_OUTPUT_STAGE
Eric Laurent84e9a102010-09-23 16:10:16 -07004638 lStatus = BAD_VALUE;
4639 goto Exit;
Dima Zavinfce7a472011-04-19 22:30:36 -07004640 } else if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
Eric Laurent84e9a102010-09-23 16:10:16 -07004641 // if the output returned by getOutputForEffect() is removed before we lock the
4642 // mutex below, the call to checkPlaybackThread_l(output) below will detect it
4643 // and we will exit safely
4644 output = AudioSystem::getOutputForEffect(&desc);
4645 }
4646 }
4647
Mathias Agopian65ab4712010-07-14 17:59:35 -07004648 {
4649 Mutex::Autolock _l(mLock);
4650
Mathias Agopian65ab4712010-07-14 17:59:35 -07004651
4652 if (!EffectIsNullUuid(&pDesc->uuid)) {
4653 // if uuid is specified, request effect descriptor
4654 lStatus = EffectGetDescriptor(&pDesc->uuid, &desc);
4655 if (lStatus < 0) {
4656 LOGW("createEffect() error %d from EffectGetDescriptor", lStatus);
4657 goto Exit;
4658 }
4659 } else {
4660 // if uuid is not specified, look for an available implementation
4661 // of the required type in effect factory
4662 if (EffectIsNullUuid(&pDesc->type)) {
4663 LOGW("createEffect() no effect type");
4664 lStatus = BAD_VALUE;
4665 goto Exit;
4666 }
4667 uint32_t numEffects = 0;
4668 effect_descriptor_t d;
4669 bool found = false;
4670
4671 lStatus = EffectQueryNumberEffects(&numEffects);
4672 if (lStatus < 0) {
4673 LOGW("createEffect() error %d from EffectQueryNumberEffects", lStatus);
4674 goto Exit;
4675 }
4676 for (uint32_t i = 0; i < numEffects; i++) {
4677 lStatus = EffectQueryEffect(i, &desc);
4678 if (lStatus < 0) {
4679 LOGW("createEffect() error %d from EffectQueryEffect", lStatus);
4680 continue;
4681 }
4682 if (memcmp(&desc.type, &pDesc->type, sizeof(effect_uuid_t)) == 0) {
4683 // If matching type found save effect descriptor. If the session is
4684 // 0 and the effect is not auxiliary, continue enumeration in case
4685 // an auxiliary version of this effect type is available
4686 found = true;
4687 memcpy(&d, &desc, sizeof(effect_descriptor_t));
Dima Zavinfce7a472011-04-19 22:30:36 -07004688 if (sessionId != AUDIO_SESSION_OUTPUT_MIX ||
Mathias Agopian65ab4712010-07-14 17:59:35 -07004689 (desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
4690 break;
4691 }
4692 }
4693 }
4694 if (!found) {
4695 lStatus = BAD_VALUE;
4696 LOGW("createEffect() effect not found");
4697 goto Exit;
4698 }
4699 // For same effect type, chose auxiliary version over insert version if
4700 // connect to output mix (Compliance to OpenSL ES)
Dima Zavinfce7a472011-04-19 22:30:36 -07004701 if (sessionId == AUDIO_SESSION_OUTPUT_MIX &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07004702 (d.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_AUXILIARY) {
4703 memcpy(&desc, &d, sizeof(effect_descriptor_t));
4704 }
4705 }
4706
4707 // Do not allow auxiliary effects on a session different from 0 (output mix)
Dima Zavinfce7a472011-04-19 22:30:36 -07004708 if (sessionId != AUDIO_SESSION_OUTPUT_MIX &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07004709 (desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
4710 lStatus = INVALID_OPERATION;
4711 goto Exit;
4712 }
4713
Mathias Agopian65ab4712010-07-14 17:59:35 -07004714 // return effect descriptor
4715 memcpy(pDesc, &desc, sizeof(effect_descriptor_t));
4716
4717 // If output is not specified try to find a matching audio session ID in one of the
4718 // output threads.
Eric Laurent84e9a102010-09-23 16:10:16 -07004719 // If output is 0 here, sessionId is neither SESSION_OUTPUT_STAGE nor SESSION_OUTPUT_MIX
4720 // because of code checking output when entering the function.
Mathias Agopian65ab4712010-07-14 17:59:35 -07004721 if (output == 0) {
Eric Laurent84e9a102010-09-23 16:10:16 -07004722 // look for the thread where the specified audio session is present
4723 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
4724 if (mPlaybackThreads.valueAt(i)->hasAudioSession(sessionId) != 0) {
4725 output = mPlaybackThreads.keyAt(i);
4726 break;
Eric Laurent39e94f82010-07-28 01:32:47 -07004727 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07004728 }
Eric Laurent84e9a102010-09-23 16:10:16 -07004729 // If no output thread contains the requested session ID, default to
4730 // first output. The effect chain will be moved to the correct output
4731 // thread when a track with the same session ID is created
4732 if (output == 0 && mPlaybackThreads.size()) {
4733 output = mPlaybackThreads.keyAt(0);
4734 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07004735 }
Eric Laurent84e9a102010-09-23 16:10:16 -07004736 LOGV("createEffect() got output %d for effect %s", output, desc.name);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004737 PlaybackThread *thread = checkPlaybackThread_l(output);
4738 if (thread == NULL) {
Eric Laurentde070132010-07-13 04:45:46 -07004739 LOGE("createEffect() unknown output thread");
Mathias Agopian65ab4712010-07-14 17:59:35 -07004740 lStatus = BAD_VALUE;
4741 goto Exit;
4742 }
4743
Eric Laurent84e9a102010-09-23 16:10:16 -07004744 // TODO: allow attachment of effect to inputs
4745
Mathias Agopian65ab4712010-07-14 17:59:35 -07004746 wclient = mClients.valueFor(pid);
4747
4748 if (wclient != NULL) {
4749 client = wclient.promote();
4750 } else {
4751 client = new Client(this, pid);
4752 mClients.add(pid, client);
4753 }
4754
4755 // create effect on selected output trhead
Eric Laurentde070132010-07-13 04:45:46 -07004756 handle = thread->createEffect_l(client, effectClient, priority, sessionId,
4757 &desc, enabled, &lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004758 if (handle != 0 && id != NULL) {
4759 *id = handle->id();
4760 }
4761 }
4762
4763Exit:
4764 if(status) {
4765 *status = lStatus;
4766 }
4767 return handle;
4768}
4769
Eric Laurentde070132010-07-13 04:45:46 -07004770status_t AudioFlinger::moveEffects(int session, int srcOutput, int dstOutput)
4771{
4772 LOGV("moveEffects() session %d, srcOutput %d, dstOutput %d",
4773 session, srcOutput, dstOutput);
4774 Mutex::Autolock _l(mLock);
4775 if (srcOutput == dstOutput) {
4776 LOGW("moveEffects() same dst and src outputs %d", dstOutput);
4777 return NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004778 }
Eric Laurentde070132010-07-13 04:45:46 -07004779 PlaybackThread *srcThread = checkPlaybackThread_l(srcOutput);
4780 if (srcThread == NULL) {
4781 LOGW("moveEffects() bad srcOutput %d", srcOutput);
4782 return BAD_VALUE;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004783 }
Eric Laurentde070132010-07-13 04:45:46 -07004784 PlaybackThread *dstThread = checkPlaybackThread_l(dstOutput);
4785 if (dstThread == NULL) {
4786 LOGW("moveEffects() bad dstOutput %d", dstOutput);
4787 return BAD_VALUE;
4788 }
4789
4790 Mutex::Autolock _dl(dstThread->mLock);
4791 Mutex::Autolock _sl(srcThread->mLock);
Eric Laurent39e94f82010-07-28 01:32:47 -07004792 moveEffectChain_l(session, srcThread, dstThread, false);
Eric Laurentde070132010-07-13 04:45:46 -07004793
Mathias Agopian65ab4712010-07-14 17:59:35 -07004794 return NO_ERROR;
4795}
4796
Eric Laurentde070132010-07-13 04:45:46 -07004797// moveEffectChain_l mustbe called with both srcThread and dstThread mLocks held
4798status_t AudioFlinger::moveEffectChain_l(int session,
4799 AudioFlinger::PlaybackThread *srcThread,
Eric Laurent39e94f82010-07-28 01:32:47 -07004800 AudioFlinger::PlaybackThread *dstThread,
4801 bool reRegister)
Eric Laurentde070132010-07-13 04:45:46 -07004802{
4803 LOGV("moveEffectChain_l() session %d from thread %p to thread %p",
4804 session, srcThread, dstThread);
4805
4806 sp<EffectChain> chain = srcThread->getEffectChain_l(session);
4807 if (chain == 0) {
4808 LOGW("moveEffectChain_l() effect chain for session %d not on source thread %p",
4809 session, srcThread);
4810 return INVALID_OPERATION;
4811 }
4812
Eric Laurent39e94f82010-07-28 01:32:47 -07004813 // remove chain first. This is useful only if reconfiguring effect chain on same output thread,
Eric Laurentde070132010-07-13 04:45:46 -07004814 // so that a new chain is created with correct parameters when first effect is added. This is
4815 // otherwise unecessary as removeEffect_l() will remove the chain when last effect is
4816 // removed.
4817 srcThread->removeEffectChain_l(chain);
4818
4819 // transfer all effects one by one so that new effect chain is created on new thread with
4820 // correct buffer sizes and audio parameters and effect engines reconfigured accordingly
Eric Laurent39e94f82010-07-28 01:32:47 -07004821 int dstOutput = dstThread->id();
4822 sp<EffectChain> dstChain;
4823 uint32_t strategy;
Eric Laurentde070132010-07-13 04:45:46 -07004824 sp<EffectModule> effect = chain->getEffectFromId_l(0);
4825 while (effect != 0) {
4826 srcThread->removeEffect_l(effect);
4827 dstThread->addEffect_l(effect);
Eric Laurent39e94f82010-07-28 01:32:47 -07004828 // if the move request is not received from audio policy manager, the effect must be
4829 // re-registered with the new strategy and output
4830 if (dstChain == 0) {
4831 dstChain = effect->chain().promote();
4832 if (dstChain == 0) {
4833 LOGW("moveEffectChain_l() cannot get chain from effect %p", effect.get());
4834 srcThread->addEffect_l(effect);
4835 return NO_INIT;
4836 }
4837 strategy = dstChain->strategy();
4838 }
4839 if (reRegister) {
4840 AudioSystem::unregisterEffect(effect->id());
4841 AudioSystem::registerEffect(&effect->desc(),
4842 dstOutput,
4843 strategy,
4844 session,
4845 effect->id());
4846 }
Eric Laurentde070132010-07-13 04:45:46 -07004847 effect = chain->getEffectFromId_l(0);
4848 }
4849
4850 return NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004851}
4852
4853// PlaybackThread::createEffect_l() must be called with AudioFlinger::mLock held
4854sp<AudioFlinger::EffectHandle> AudioFlinger::PlaybackThread::createEffect_l(
4855 const sp<AudioFlinger::Client>& client,
4856 const sp<IEffectClient>& effectClient,
4857 int32_t priority,
4858 int sessionId,
4859 effect_descriptor_t *desc,
4860 int *enabled,
4861 status_t *status
4862 )
4863{
4864 sp<EffectModule> effect;
4865 sp<EffectHandle> handle;
4866 status_t lStatus;
4867 sp<Track> track;
4868 sp<EffectChain> chain;
Eric Laurentde070132010-07-13 04:45:46 -07004869 bool chainCreated = false;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004870 bool effectCreated = false;
4871 bool effectRegistered = false;
4872
4873 if (mOutput == 0) {
4874 LOGW("createEffect_l() Audio driver not initialized.");
4875 lStatus = NO_INIT;
4876 goto Exit;
4877 }
4878
4879 // Do not allow auxiliary effect on session other than 0
4880 if ((desc->flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY &&
Dima Zavinfce7a472011-04-19 22:30:36 -07004881 sessionId != AUDIO_SESSION_OUTPUT_MIX) {
Eric Laurentde070132010-07-13 04:45:46 -07004882 LOGW("createEffect_l() Cannot add auxiliary effect %s to session %d",
4883 desc->name, sessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004884 lStatus = BAD_VALUE;
4885 goto Exit;
4886 }
4887
4888 // Do not allow effects with session ID 0 on direct output or duplicating threads
4889 // TODO: add rule for hw accelerated effects on direct outputs with non PCM format
Dima Zavinfce7a472011-04-19 22:30:36 -07004890 if (sessionId == AUDIO_SESSION_OUTPUT_MIX && mType != MIXER) {
Eric Laurentde070132010-07-13 04:45:46 -07004891 LOGW("createEffect_l() Cannot add auxiliary effect %s to session %d",
4892 desc->name, sessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004893 lStatus = BAD_VALUE;
4894 goto Exit;
4895 }
4896
4897 LOGV("createEffect_l() thread %p effect %s on session %d", this, desc->name, sessionId);
4898
4899 { // scope for mLock
4900 Mutex::Autolock _l(mLock);
4901
4902 // check for existing effect chain with the requested audio session
4903 chain = getEffectChain_l(sessionId);
4904 if (chain == 0) {
4905 // create a new chain for this session
4906 LOGV("createEffect_l() new effect chain for session %d", sessionId);
4907 chain = new EffectChain(this, sessionId);
4908 addEffectChain_l(chain);
Eric Laurentde070132010-07-13 04:45:46 -07004909 chain->setStrategy(getStrategyForSession_l(sessionId));
4910 chainCreated = true;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004911 } else {
Eric Laurentcab11242010-07-15 12:50:15 -07004912 effect = chain->getEffectFromDesc_l(desc);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004913 }
4914
4915 LOGV("createEffect_l() got effect %p on chain %p", effect == 0 ? 0 : effect.get(), chain.get());
4916
4917 if (effect == 0) {
Eric Laurentf5aafb22010-11-18 08:40:16 -08004918 int id = mAudioFlinger->nextUniqueId_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07004919 // Check CPU and memory usage
Eric Laurentde070132010-07-13 04:45:46 -07004920 lStatus = AudioSystem::registerEffect(desc, mId, chain->strategy(), sessionId, id);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004921 if (lStatus != NO_ERROR) {
4922 goto Exit;
4923 }
4924 effectRegistered = true;
4925 // create a new effect module if none present in the chain
Eric Laurentde070132010-07-13 04:45:46 -07004926 effect = new EffectModule(this, chain, desc, id, sessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004927 lStatus = effect->status();
4928 if (lStatus != NO_ERROR) {
4929 goto Exit;
4930 }
Eric Laurentcab11242010-07-15 12:50:15 -07004931 lStatus = chain->addEffect_l(effect);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004932 if (lStatus != NO_ERROR) {
4933 goto Exit;
4934 }
4935 effectCreated = true;
4936
4937 effect->setDevice(mDevice);
4938 effect->setMode(mAudioFlinger->getMode());
4939 }
4940 // create effect handle and connect it to effect module
4941 handle = new EffectHandle(effect, client, effectClient, priority);
4942 lStatus = effect->addHandle(handle);
4943 if (enabled) {
4944 *enabled = (int)effect->isEnabled();
4945 }
4946 }
4947
4948Exit:
4949 if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
Eric Laurentde070132010-07-13 04:45:46 -07004950 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004951 if (effectCreated) {
Eric Laurentde070132010-07-13 04:45:46 -07004952 chain->removeEffect_l(effect);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004953 }
4954 if (effectRegistered) {
Eric Laurentde070132010-07-13 04:45:46 -07004955 AudioSystem::unregisterEffect(effect->id());
4956 }
4957 if (chainCreated) {
4958 removeEffectChain_l(chain);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004959 }
4960 handle.clear();
4961 }
4962
4963 if(status) {
4964 *status = lStatus;
4965 }
4966 return handle;
4967}
4968
Eric Laurentde070132010-07-13 04:45:46 -07004969// PlaybackThread::addEffect_l() must be called with AudioFlinger::mLock and
4970// PlaybackThread::mLock held
4971status_t AudioFlinger::PlaybackThread::addEffect_l(const sp<EffectModule>& effect)
4972{
4973 // check for existing effect chain with the requested audio session
4974 int sessionId = effect->sessionId();
4975 sp<EffectChain> chain = getEffectChain_l(sessionId);
4976 bool chainCreated = false;
4977
4978 if (chain == 0) {
4979 // create a new chain for this session
4980 LOGV("addEffect_l() new effect chain for session %d", sessionId);
4981 chain = new EffectChain(this, sessionId);
4982 addEffectChain_l(chain);
4983 chain->setStrategy(getStrategyForSession_l(sessionId));
4984 chainCreated = true;
4985 }
4986 LOGV("addEffect_l() %p chain %p effect %p", this, chain.get(), effect.get());
4987
4988 if (chain->getEffectFromId_l(effect->id()) != 0) {
4989 LOGW("addEffect_l() %p effect %s already present in chain %p",
4990 this, effect->desc().name, chain.get());
4991 return BAD_VALUE;
4992 }
4993
4994 status_t status = chain->addEffect_l(effect);
4995 if (status != NO_ERROR) {
4996 if (chainCreated) {
4997 removeEffectChain_l(chain);
4998 }
4999 return status;
5000 }
5001
5002 effect->setDevice(mDevice);
5003 effect->setMode(mAudioFlinger->getMode());
5004 return NO_ERROR;
5005}
5006
5007void AudioFlinger::PlaybackThread::removeEffect_l(const sp<EffectModule>& effect) {
5008
5009 LOGV("removeEffect_l() %p effect %p", this, effect.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07005010 effect_descriptor_t desc = effect->desc();
Eric Laurentde070132010-07-13 04:45:46 -07005011 if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
5012 detachAuxEffect_l(effect->id());
5013 }
5014
5015 sp<EffectChain> chain = effect->chain().promote();
5016 if (chain != 0) {
5017 // remove effect chain if removing last effect
5018 if (chain->removeEffect_l(effect) == 0) {
5019 removeEffectChain_l(chain);
5020 }
5021 } else {
5022 LOGW("removeEffect_l() %p cannot promote chain for effect %p", this, effect.get());
5023 }
5024}
5025
5026void AudioFlinger::PlaybackThread::disconnectEffect(const sp<EffectModule>& effect,
5027 const wp<EffectHandle>& handle) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005028 Mutex::Autolock _l(mLock);
Eric Laurentde070132010-07-13 04:45:46 -07005029 LOGV("disconnectEffect() %p effect %p", this, effect.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07005030 // delete the effect module if removing last handle on it
5031 if (effect->removeHandle(handle) == 0) {
Eric Laurentde070132010-07-13 04:45:46 -07005032 removeEffect_l(effect);
5033 AudioSystem::unregisterEffect(effect->id());
Mathias Agopian65ab4712010-07-14 17:59:35 -07005034 }
5035}
5036
5037status_t AudioFlinger::PlaybackThread::addEffectChain_l(const sp<EffectChain>& chain)
5038{
5039 int session = chain->sessionId();
5040 int16_t *buffer = mMixBuffer;
5041 bool ownsBuffer = false;
5042
5043 LOGV("addEffectChain_l() %p on thread %p for session %d", chain.get(), this, session);
5044 if (session > 0) {
5045 // Only one effect chain can be present in direct output thread and it uses
5046 // the mix buffer as input
5047 if (mType != DIRECT) {
5048 size_t numSamples = mFrameCount * mChannelCount;
5049 buffer = new int16_t[numSamples];
5050 memset(buffer, 0, numSamples * sizeof(int16_t));
5051 LOGV("addEffectChain_l() creating new input buffer %p session %d", buffer, session);
5052 ownsBuffer = true;
5053 }
5054
5055 // Attach all tracks with same session ID to this chain.
5056 for (size_t i = 0; i < mTracks.size(); ++i) {
5057 sp<Track> track = mTracks[i];
5058 if (session == track->sessionId()) {
5059 LOGV("addEffectChain_l() track->setMainBuffer track %p buffer %p", track.get(), buffer);
5060 track->setMainBuffer(buffer);
5061 }
5062 }
5063
5064 // indicate all active tracks in the chain
5065 for (size_t i = 0 ; i < mActiveTracks.size() ; ++i) {
5066 sp<Track> track = mActiveTracks[i].promote();
5067 if (track == 0) continue;
5068 if (session == track->sessionId()) {
5069 LOGV("addEffectChain_l() activating track %p on session %d", track.get(), session);
5070 chain->startTrack();
5071 }
5072 }
5073 }
5074
5075 chain->setInBuffer(buffer, ownsBuffer);
5076 chain->setOutBuffer(mMixBuffer);
Dima Zavinfce7a472011-04-19 22:30:36 -07005077 // Effect chain for session AUDIO_SESSION_OUTPUT_STAGE is inserted at end of effect
Eric Laurentde070132010-07-13 04:45:46 -07005078 // chains list in order to be processed last as it contains output stage effects
Dima Zavinfce7a472011-04-19 22:30:36 -07005079 // Effect chain for session AUDIO_SESSION_OUTPUT_MIX is inserted before
5080 // session AUDIO_SESSION_OUTPUT_STAGE to be processed
Mathias Agopian65ab4712010-07-14 17:59:35 -07005081 // after track specific effects and before output stage
Dima Zavinfce7a472011-04-19 22:30:36 -07005082 // It is therefore mandatory that AUDIO_SESSION_OUTPUT_MIX == 0 and
5083 // that AUDIO_SESSION_OUTPUT_STAGE < AUDIO_SESSION_OUTPUT_MIX
Eric Laurentde070132010-07-13 04:45:46 -07005084 // Effect chain for other sessions are inserted at beginning of effect
5085 // chains list to be processed before output mix effects. Relative order between other
5086 // sessions is not important
Mathias Agopian65ab4712010-07-14 17:59:35 -07005087 size_t size = mEffectChains.size();
5088 size_t i = 0;
5089 for (i = 0; i < size; i++) {
5090 if (mEffectChains[i]->sessionId() < session) break;
5091 }
5092 mEffectChains.insertAt(chain, i);
5093
5094 return NO_ERROR;
5095}
5096
5097size_t AudioFlinger::PlaybackThread::removeEffectChain_l(const sp<EffectChain>& chain)
5098{
5099 int session = chain->sessionId();
5100
5101 LOGV("removeEffectChain_l() %p from thread %p for session %d", chain.get(), this, session);
5102
5103 for (size_t i = 0; i < mEffectChains.size(); i++) {
5104 if (chain == mEffectChains[i]) {
5105 mEffectChains.removeAt(i);
5106 // detach all tracks with same session ID from this chain
5107 for (size_t i = 0; i < mTracks.size(); ++i) {
5108 sp<Track> track = mTracks[i];
5109 if (session == track->sessionId()) {
5110 track->setMainBuffer(mMixBuffer);
5111 }
5112 }
Eric Laurentde070132010-07-13 04:45:46 -07005113 break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005114 }
5115 }
5116 return mEffectChains.size();
5117}
5118
Eric Laurentde070132010-07-13 04:45:46 -07005119void AudioFlinger::PlaybackThread::lockEffectChains_l(
5120 Vector<sp <AudioFlinger::EffectChain> >& effectChains)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005121{
Eric Laurentde070132010-07-13 04:45:46 -07005122 effectChains = mEffectChains;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005123 for (size_t i = 0; i < mEffectChains.size(); i++) {
5124 mEffectChains[i]->lock();
5125 }
5126}
5127
Eric Laurentde070132010-07-13 04:45:46 -07005128void AudioFlinger::PlaybackThread::unlockEffectChains(
5129 Vector<sp <AudioFlinger::EffectChain> >& effectChains)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005130{
Eric Laurentde070132010-07-13 04:45:46 -07005131 for (size_t i = 0; i < effectChains.size(); i++) {
5132 effectChains[i]->unlock();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005133 }
5134}
5135
Eric Laurentde070132010-07-13 04:45:46 -07005136
Mathias Agopian65ab4712010-07-14 17:59:35 -07005137sp<AudioFlinger::EffectModule> AudioFlinger::PlaybackThread::getEffect_l(int sessionId, int effectId)
5138{
5139 sp<EffectModule> effect;
5140
5141 sp<EffectChain> chain = getEffectChain_l(sessionId);
5142 if (chain != 0) {
Eric Laurentcab11242010-07-15 12:50:15 -07005143 effect = chain->getEffectFromId_l(effectId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005144 }
5145 return effect;
5146}
5147
Eric Laurentde070132010-07-13 04:45:46 -07005148status_t AudioFlinger::PlaybackThread::attachAuxEffect(
5149 const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005150{
5151 Mutex::Autolock _l(mLock);
5152 return attachAuxEffect_l(track, EffectId);
5153}
5154
Eric Laurentde070132010-07-13 04:45:46 -07005155status_t AudioFlinger::PlaybackThread::attachAuxEffect_l(
5156 const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005157{
5158 status_t status = NO_ERROR;
5159
5160 if (EffectId == 0) {
5161 track->setAuxBuffer(0, NULL);
5162 } else {
Dima Zavinfce7a472011-04-19 22:30:36 -07005163 // Auxiliary effects are always in audio session AUDIO_SESSION_OUTPUT_MIX
5164 sp<EffectModule> effect = getEffect_l(AUDIO_SESSION_OUTPUT_MIX, EffectId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005165 if (effect != 0) {
5166 if ((effect->desc().flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
5167 track->setAuxBuffer(EffectId, (int32_t *)effect->inBuffer());
5168 } else {
5169 status = INVALID_OPERATION;
5170 }
5171 } else {
5172 status = BAD_VALUE;
5173 }
5174 }
5175 return status;
5176}
5177
5178void AudioFlinger::PlaybackThread::detachAuxEffect_l(int effectId)
5179{
5180 for (size_t i = 0; i < mTracks.size(); ++i) {
5181 sp<Track> track = mTracks[i];
5182 if (track->auxEffectId() == effectId) {
5183 attachAuxEffect_l(track, 0);
5184 }
5185 }
5186}
5187
5188// ----------------------------------------------------------------------------
5189// EffectModule implementation
5190// ----------------------------------------------------------------------------
5191
5192#undef LOG_TAG
5193#define LOG_TAG "AudioFlinger::EffectModule"
5194
5195AudioFlinger::EffectModule::EffectModule(const wp<ThreadBase>& wThread,
5196 const wp<AudioFlinger::EffectChain>& chain,
5197 effect_descriptor_t *desc,
5198 int id,
5199 int sessionId)
5200 : mThread(wThread), mChain(chain), mId(id), mSessionId(sessionId), mEffectInterface(NULL),
5201 mStatus(NO_INIT), mState(IDLE)
5202{
5203 LOGV("Constructor %p", this);
5204 int lStatus;
5205 sp<ThreadBase> thread = mThread.promote();
5206 if (thread == 0) {
5207 return;
5208 }
5209 PlaybackThread *p = (PlaybackThread *)thread.get();
5210
5211 memcpy(&mDescriptor, desc, sizeof(effect_descriptor_t));
5212
5213 // create effect engine from effect factory
5214 mStatus = EffectCreate(&desc->uuid, sessionId, p->id(), &mEffectInterface);
5215
5216 if (mStatus != NO_ERROR) {
5217 return;
5218 }
5219 lStatus = init();
5220 if (lStatus < 0) {
5221 mStatus = lStatus;
5222 goto Error;
5223 }
5224
5225 LOGV("Constructor success name %s, Interface %p", mDescriptor.name, mEffectInterface);
5226 return;
5227Error:
5228 EffectRelease(mEffectInterface);
5229 mEffectInterface = NULL;
5230 LOGV("Constructor Error %d", mStatus);
5231}
5232
5233AudioFlinger::EffectModule::~EffectModule()
5234{
5235 LOGV("Destructor %p", this);
5236 if (mEffectInterface != NULL) {
5237 // release effect engine
5238 EffectRelease(mEffectInterface);
5239 }
5240}
5241
5242status_t AudioFlinger::EffectModule::addHandle(sp<EffectHandle>& handle)
5243{
5244 status_t status;
5245
5246 Mutex::Autolock _l(mLock);
5247 // First handle in mHandles has highest priority and controls the effect module
5248 int priority = handle->priority();
5249 size_t size = mHandles.size();
5250 sp<EffectHandle> h;
5251 size_t i;
5252 for (i = 0; i < size; i++) {
5253 h = mHandles[i].promote();
5254 if (h == 0) continue;
5255 if (h->priority() <= priority) break;
5256 }
5257 // if inserted in first place, move effect control from previous owner to this handle
5258 if (i == 0) {
5259 if (h != 0) {
5260 h->setControl(false, true);
5261 }
5262 handle->setControl(true, false);
5263 status = NO_ERROR;
5264 } else {
5265 status = ALREADY_EXISTS;
5266 }
5267 mHandles.insertAt(handle, i);
5268 return status;
5269}
5270
5271size_t AudioFlinger::EffectModule::removeHandle(const wp<EffectHandle>& handle)
5272{
5273 Mutex::Autolock _l(mLock);
5274 size_t size = mHandles.size();
5275 size_t i;
5276 for (i = 0; i < size; i++) {
5277 if (mHandles[i] == handle) break;
5278 }
5279 if (i == size) {
5280 return size;
5281 }
5282 mHandles.removeAt(i);
5283 size = mHandles.size();
5284 // if removed from first place, move effect control from this handle to next in line
5285 if (i == 0 && size != 0) {
5286 sp<EffectHandle> h = mHandles[0].promote();
5287 if (h != 0) {
5288 h->setControl(true, true);
5289 }
5290 }
5291
Eric Laurentdac69112010-09-28 14:09:57 -07005292 // Release effect engine here so that it is done immediately. Otherwise it will be released
5293 // by the destructor when the last strong reference on the this object is released which can
5294 // happen after next process is called on this effect.
5295 if (size == 0 && mEffectInterface != NULL) {
5296 // release effect engine
5297 EffectRelease(mEffectInterface);
5298 mEffectInterface = NULL;
5299 }
5300
Mathias Agopian65ab4712010-07-14 17:59:35 -07005301 return size;
5302}
5303
5304void AudioFlinger::EffectModule::disconnect(const wp<EffectHandle>& handle)
5305{
5306 // keep a strong reference on this EffectModule to avoid calling the
5307 // destructor before we exit
5308 sp<EffectModule> keep(this);
5309 {
5310 sp<ThreadBase> thread = mThread.promote();
5311 if (thread != 0) {
5312 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
5313 playbackThread->disconnectEffect(keep, handle);
5314 }
5315 }
5316}
5317
5318void AudioFlinger::EffectModule::updateState() {
5319 Mutex::Autolock _l(mLock);
5320
5321 switch (mState) {
5322 case RESTART:
5323 reset_l();
5324 // FALL THROUGH
5325
5326 case STARTING:
5327 // clear auxiliary effect input buffer for next accumulation
5328 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
5329 memset(mConfig.inputCfg.buffer.raw,
5330 0,
5331 mConfig.inputCfg.buffer.frameCount*sizeof(int32_t));
5332 }
5333 start_l();
5334 mState = ACTIVE;
5335 break;
5336 case STOPPING:
5337 stop_l();
5338 mDisableWaitCnt = mMaxDisableWaitCnt;
5339 mState = STOPPED;
5340 break;
5341 case STOPPED:
5342 // mDisableWaitCnt is forced to 1 by process() when the engine indicates the end of the
5343 // turn off sequence.
5344 if (--mDisableWaitCnt == 0) {
5345 reset_l();
5346 mState = IDLE;
5347 }
5348 break;
5349 default: //IDLE , ACTIVE
5350 break;
5351 }
5352}
5353
5354void AudioFlinger::EffectModule::process()
5355{
5356 Mutex::Autolock _l(mLock);
5357
5358 if (mEffectInterface == NULL ||
5359 mConfig.inputCfg.buffer.raw == NULL ||
5360 mConfig.outputCfg.buffer.raw == NULL) {
5361 return;
5362 }
5363
Eric Laurent8f45bd72010-08-31 13:50:07 -07005364 if (isProcessEnabled()) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005365 // do 32 bit to 16 bit conversion for auxiliary effect input buffer
5366 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
5367 AudioMixer::ditherAndClamp(mConfig.inputCfg.buffer.s32,
5368 mConfig.inputCfg.buffer.s32,
Eric Laurentde070132010-07-13 04:45:46 -07005369 mConfig.inputCfg.buffer.frameCount/2);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005370 }
5371
5372 // do the actual processing in the effect engine
5373 int ret = (*mEffectInterface)->process(mEffectInterface,
5374 &mConfig.inputCfg.buffer,
5375 &mConfig.outputCfg.buffer);
5376
5377 // force transition to IDLE state when engine is ready
5378 if (mState == STOPPED && ret == -ENODATA) {
5379 mDisableWaitCnt = 1;
5380 }
5381
5382 // clear auxiliary effect input buffer for next accumulation
5383 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
Eric Laurent73337482011-01-19 18:36:13 -08005384 memset(mConfig.inputCfg.buffer.raw, 0,
5385 mConfig.inputCfg.buffer.frameCount*sizeof(int32_t));
Mathias Agopian65ab4712010-07-14 17:59:35 -07005386 }
5387 } else if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_INSERT &&
Eric Laurent73337482011-01-19 18:36:13 -08005388 mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
5389 // If an insert effect is idle and input buffer is different from output buffer,
5390 // accumulate input onto output
Mathias Agopian65ab4712010-07-14 17:59:35 -07005391 sp<EffectChain> chain = mChain.promote();
5392 if (chain != 0 && chain->activeTracks() != 0) {
Eric Laurent73337482011-01-19 18:36:13 -08005393 size_t frameCnt = mConfig.inputCfg.buffer.frameCount * 2; //always stereo here
5394 int16_t *in = mConfig.inputCfg.buffer.s16;
5395 int16_t *out = mConfig.outputCfg.buffer.s16;
5396 for (size_t i = 0; i < frameCnt; i++) {
5397 out[i] = clamp16((int32_t)out[i] + (int32_t)in[i]);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005398 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07005399 }
5400 }
5401}
5402
5403void AudioFlinger::EffectModule::reset_l()
5404{
5405 if (mEffectInterface == NULL) {
5406 return;
5407 }
5408 (*mEffectInterface)->command(mEffectInterface, EFFECT_CMD_RESET, 0, NULL, 0, NULL);
5409}
5410
5411status_t AudioFlinger::EffectModule::configure()
5412{
5413 uint32_t channels;
5414 if (mEffectInterface == NULL) {
5415 return NO_INIT;
5416 }
5417
5418 sp<ThreadBase> thread = mThread.promote();
5419 if (thread == 0) {
5420 return DEAD_OBJECT;
5421 }
5422
5423 // TODO: handle configuration of effects replacing track process
5424 if (thread->channelCount() == 1) {
5425 channels = CHANNEL_MONO;
5426 } else {
5427 channels = CHANNEL_STEREO;
5428 }
5429
5430 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
5431 mConfig.inputCfg.channels = CHANNEL_MONO;
5432 } else {
5433 mConfig.inputCfg.channels = channels;
5434 }
5435 mConfig.outputCfg.channels = channels;
5436 mConfig.inputCfg.format = SAMPLE_FORMAT_PCM_S15;
5437 mConfig.outputCfg.format = SAMPLE_FORMAT_PCM_S15;
5438 mConfig.inputCfg.samplingRate = thread->sampleRate();
5439 mConfig.outputCfg.samplingRate = mConfig.inputCfg.samplingRate;
5440 mConfig.inputCfg.bufferProvider.cookie = NULL;
5441 mConfig.inputCfg.bufferProvider.getBuffer = NULL;
5442 mConfig.inputCfg.bufferProvider.releaseBuffer = NULL;
5443 mConfig.outputCfg.bufferProvider.cookie = NULL;
5444 mConfig.outputCfg.bufferProvider.getBuffer = NULL;
5445 mConfig.outputCfg.bufferProvider.releaseBuffer = NULL;
5446 mConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
5447 // Insert effect:
Dima Zavinfce7a472011-04-19 22:30:36 -07005448 // - in session AUDIO_SESSION_OUTPUT_MIX or AUDIO_SESSION_OUTPUT_STAGE,
Eric Laurentde070132010-07-13 04:45:46 -07005449 // always overwrites output buffer: input buffer == output buffer
Mathias Agopian65ab4712010-07-14 17:59:35 -07005450 // - in other sessions:
5451 // last effect in the chain accumulates in output buffer: input buffer != output buffer
5452 // other effect: overwrites output buffer: input buffer == output buffer
5453 // Auxiliary effect:
5454 // accumulates in output buffer: input buffer != output buffer
5455 // Therefore: accumulate <=> input buffer != output buffer
5456 if (mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
5457 mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
5458 } else {
5459 mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_WRITE;
5460 }
5461 mConfig.inputCfg.mask = EFFECT_CONFIG_ALL;
5462 mConfig.outputCfg.mask = EFFECT_CONFIG_ALL;
5463 mConfig.inputCfg.buffer.frameCount = thread->frameCount();
5464 mConfig.outputCfg.buffer.frameCount = mConfig.inputCfg.buffer.frameCount;
5465
Eric Laurentde070132010-07-13 04:45:46 -07005466 LOGV("configure() %p thread %p buffer %p framecount %d",
5467 this, thread.get(), mConfig.inputCfg.buffer.raw, mConfig.inputCfg.buffer.frameCount);
5468
Mathias Agopian65ab4712010-07-14 17:59:35 -07005469 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07005470 uint32_t size = sizeof(int);
5471 status_t status = (*mEffectInterface)->command(mEffectInterface,
5472 EFFECT_CMD_CONFIGURE,
5473 sizeof(effect_config_t),
5474 &mConfig,
5475 &size,
5476 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005477 if (status == 0) {
5478 status = cmdStatus;
5479 }
5480
5481 mMaxDisableWaitCnt = (MAX_DISABLE_TIME_MS * mConfig.outputCfg.samplingRate) /
5482 (1000 * mConfig.outputCfg.buffer.frameCount);
5483
5484 return status;
5485}
5486
5487status_t AudioFlinger::EffectModule::init()
5488{
5489 Mutex::Autolock _l(mLock);
5490 if (mEffectInterface == NULL) {
5491 return NO_INIT;
5492 }
5493 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07005494 uint32_t size = sizeof(status_t);
5495 status_t status = (*mEffectInterface)->command(mEffectInterface,
5496 EFFECT_CMD_INIT,
5497 0,
5498 NULL,
5499 &size,
5500 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005501 if (status == 0) {
5502 status = cmdStatus;
5503 }
5504 return status;
5505}
5506
5507status_t AudioFlinger::EffectModule::start_l()
5508{
5509 if (mEffectInterface == NULL) {
5510 return NO_INIT;
5511 }
5512 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07005513 uint32_t size = sizeof(status_t);
5514 status_t status = (*mEffectInterface)->command(mEffectInterface,
5515 EFFECT_CMD_ENABLE,
5516 0,
5517 NULL,
5518 &size,
5519 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005520 if (status == 0) {
5521 status = cmdStatus;
5522 }
5523 return status;
5524}
5525
5526status_t AudioFlinger::EffectModule::stop_l()
5527{
5528 if (mEffectInterface == NULL) {
5529 return NO_INIT;
5530 }
5531 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07005532 uint32_t size = sizeof(status_t);
5533 status_t status = (*mEffectInterface)->command(mEffectInterface,
5534 EFFECT_CMD_DISABLE,
5535 0,
5536 NULL,
5537 &size,
5538 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005539 if (status == 0) {
5540 status = cmdStatus;
5541 }
5542 return status;
5543}
5544
Eric Laurent25f43952010-07-28 05:40:18 -07005545status_t AudioFlinger::EffectModule::command(uint32_t cmdCode,
5546 uint32_t cmdSize,
5547 void *pCmdData,
5548 uint32_t *replySize,
5549 void *pReplyData)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005550{
5551 Mutex::Autolock _l(mLock);
5552// LOGV("command(), cmdCode: %d, mEffectInterface: %p", cmdCode, mEffectInterface);
5553
5554 if (mEffectInterface == NULL) {
5555 return NO_INIT;
5556 }
Eric Laurent25f43952010-07-28 05:40:18 -07005557 status_t status = (*mEffectInterface)->command(mEffectInterface,
5558 cmdCode,
5559 cmdSize,
5560 pCmdData,
5561 replySize,
5562 pReplyData);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005563 if (cmdCode != EFFECT_CMD_GET_PARAM && status == NO_ERROR) {
Eric Laurent25f43952010-07-28 05:40:18 -07005564 uint32_t size = (replySize == NULL) ? 0 : *replySize;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005565 for (size_t i = 1; i < mHandles.size(); i++) {
5566 sp<EffectHandle> h = mHandles[i].promote();
5567 if (h != 0) {
5568 h->commandExecuted(cmdCode, cmdSize, pCmdData, size, pReplyData);
5569 }
5570 }
5571 }
5572 return status;
5573}
5574
5575status_t AudioFlinger::EffectModule::setEnabled(bool enabled)
5576{
5577 Mutex::Autolock _l(mLock);
5578 LOGV("setEnabled %p enabled %d", this, enabled);
5579
5580 if (enabled != isEnabled()) {
5581 switch (mState) {
5582 // going from disabled to enabled
5583 case IDLE:
5584 mState = STARTING;
5585 break;
5586 case STOPPED:
5587 mState = RESTART;
5588 break;
5589 case STOPPING:
5590 mState = ACTIVE;
5591 break;
5592
5593 // going from enabled to disabled
5594 case RESTART:
Eric Laurent8f45bd72010-08-31 13:50:07 -07005595 mState = STOPPED;
5596 break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005597 case STARTING:
5598 mState = IDLE;
5599 break;
5600 case ACTIVE:
5601 mState = STOPPING;
5602 break;
5603 }
5604 for (size_t i = 1; i < mHandles.size(); i++) {
5605 sp<EffectHandle> h = mHandles[i].promote();
5606 if (h != 0) {
5607 h->setEnabled(enabled);
5608 }
5609 }
5610 }
5611 return NO_ERROR;
5612}
5613
5614bool AudioFlinger::EffectModule::isEnabled()
5615{
5616 switch (mState) {
5617 case RESTART:
5618 case STARTING:
5619 case ACTIVE:
5620 return true;
5621 case IDLE:
5622 case STOPPING:
5623 case STOPPED:
5624 default:
5625 return false;
5626 }
5627}
5628
Eric Laurent8f45bd72010-08-31 13:50:07 -07005629bool AudioFlinger::EffectModule::isProcessEnabled()
5630{
5631 switch (mState) {
5632 case RESTART:
5633 case ACTIVE:
5634 case STOPPING:
5635 case STOPPED:
5636 return true;
5637 case IDLE:
5638 case STARTING:
5639 default:
5640 return false;
5641 }
5642}
5643
Mathias Agopian65ab4712010-07-14 17:59:35 -07005644status_t AudioFlinger::EffectModule::setVolume(uint32_t *left, uint32_t *right, bool controller)
5645{
5646 Mutex::Autolock _l(mLock);
5647 status_t status = NO_ERROR;
5648
5649 // Send volume indication if EFFECT_FLAG_VOLUME_IND is set and read back altered volume
5650 // if controller flag is set (Note that controller == TRUE => EFFECT_FLAG_VOLUME_CTRL set)
Eric Laurent8f45bd72010-08-31 13:50:07 -07005651 if (isProcessEnabled() &&
Eric Laurentf997cab2010-07-19 06:24:46 -07005652 ((mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL ||
5653 (mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_IND)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005654 status_t cmdStatus;
5655 uint32_t volume[2];
5656 uint32_t *pVolume = NULL;
Eric Laurent25f43952010-07-28 05:40:18 -07005657 uint32_t size = sizeof(volume);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005658 volume[0] = *left;
5659 volume[1] = *right;
5660 if (controller) {
5661 pVolume = volume;
5662 }
Eric Laurent25f43952010-07-28 05:40:18 -07005663 status = (*mEffectInterface)->command(mEffectInterface,
5664 EFFECT_CMD_SET_VOLUME,
5665 size,
5666 volume,
5667 &size,
5668 pVolume);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005669 if (controller && status == NO_ERROR && size == sizeof(volume)) {
5670 *left = volume[0];
5671 *right = volume[1];
5672 }
5673 }
5674 return status;
5675}
5676
5677status_t AudioFlinger::EffectModule::setDevice(uint32_t device)
5678{
5679 Mutex::Autolock _l(mLock);
5680 status_t status = NO_ERROR;
5681 if ((mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_IND) {
5682 // convert device bit field from AudioSystem to EffectApi format.
5683 device = deviceAudioSystemToEffectApi(device);
5684 if (device == 0) {
5685 return BAD_VALUE;
5686 }
5687 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07005688 uint32_t size = sizeof(status_t);
5689 status = (*mEffectInterface)->command(mEffectInterface,
5690 EFFECT_CMD_SET_DEVICE,
5691 sizeof(uint32_t),
5692 &device,
5693 &size,
5694 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005695 if (status == NO_ERROR) {
5696 status = cmdStatus;
5697 }
5698 }
5699 return status;
5700}
5701
5702status_t AudioFlinger::EffectModule::setMode(uint32_t mode)
5703{
5704 Mutex::Autolock _l(mLock);
5705 status_t status = NO_ERROR;
5706 if ((mDescriptor.flags & EFFECT_FLAG_AUDIO_MODE_MASK) == EFFECT_FLAG_AUDIO_MODE_IND) {
5707 // convert audio mode from AudioSystem to EffectApi format.
5708 int effectMode = modeAudioSystemToEffectApi(mode);
5709 if (effectMode < 0) {
5710 return BAD_VALUE;
5711 }
5712 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07005713 uint32_t size = sizeof(status_t);
5714 status = (*mEffectInterface)->command(mEffectInterface,
5715 EFFECT_CMD_SET_AUDIO_MODE,
5716 sizeof(int),
5717 &effectMode,
5718 &size,
5719 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005720 if (status == NO_ERROR) {
5721 status = cmdStatus;
5722 }
5723 }
5724 return status;
5725}
5726
5727// update this table when AudioSystem::audio_devices or audio_device_e (in EffectApi.h) are modified
5728const uint32_t AudioFlinger::EffectModule::sDeviceConvTable[] = {
Dima Zavinfce7a472011-04-19 22:30:36 -07005729 DEVICE_EARPIECE, // AUDIO_DEVICE_OUT_EARPIECE
5730 DEVICE_SPEAKER, // AUDIO_DEVICE_OUT_SPEAKER
5731 DEVICE_WIRED_HEADSET, // case AUDIO_DEVICE_OUT_WIRED_HEADSET
5732 DEVICE_WIRED_HEADPHONE, // AUDIO_DEVICE_OUT_WIRED_HEADPHONE
5733 DEVICE_BLUETOOTH_SCO, // AUDIO_DEVICE_OUT_BLUETOOTH_SCO
5734 DEVICE_BLUETOOTH_SCO_HEADSET, // AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET
5735 DEVICE_BLUETOOTH_SCO_CARKIT, // AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT
5736 DEVICE_BLUETOOTH_A2DP, // AUDIO_DEVICE_OUT_BLUETOOTH_A2DP
5737 DEVICE_BLUETOOTH_A2DP_HEADPHONES, // AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES
5738 DEVICE_BLUETOOTH_A2DP_SPEAKER, // AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER
5739 DEVICE_AUX_DIGITAL // AUDIO_DEVICE_OUT_AUX_DIGITAL
Mathias Agopian65ab4712010-07-14 17:59:35 -07005740};
5741
5742uint32_t AudioFlinger::EffectModule::deviceAudioSystemToEffectApi(uint32_t device)
5743{
5744 uint32_t deviceOut = 0;
5745 while (device) {
5746 const uint32_t i = 31 - __builtin_clz(device);
5747 device &= ~(1 << i);
5748 if (i >= sizeof(sDeviceConvTable)/sizeof(uint32_t)) {
Glenn Kasten4bcae822011-04-04 10:50:50 -07005749 LOGE("device conversion error for AudioSystem device 0x%08x", device);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005750 return 0;
5751 }
5752 deviceOut |= (uint32_t)sDeviceConvTable[i];
5753 }
5754 return deviceOut;
5755}
5756
5757// update this table when AudioSystem::audio_mode or audio_mode_e (in EffectApi.h) are modified
5758const uint32_t AudioFlinger::EffectModule::sModeConvTable[] = {
Dima Zavinfce7a472011-04-19 22:30:36 -07005759 AUDIO_EFFECT_MODE_NORMAL, // AUDIO_MODE_NORMAL
5760 AUDIO_EFFECT_MODE_RINGTONE, // AUDIO_MODE_RINGTONE
5761 AUDIO_EFFECT_MODE_IN_CALL, // AUDIO_MODE_IN_CALL
5762 AUDIO_EFFECT_MODE_IN_CALL // AUDIO_MODE_IN_COMMUNICATION, same conversion as for AUDIO_MODE_IN_CALL
Mathias Agopian65ab4712010-07-14 17:59:35 -07005763};
5764
5765int AudioFlinger::EffectModule::modeAudioSystemToEffectApi(uint32_t mode)
5766{
5767 int modeOut = -1;
5768 if (mode < sizeof(sModeConvTable) / sizeof(uint32_t)) {
5769 modeOut = (int)sModeConvTable[mode];
5770 }
5771 return modeOut;
5772}
5773
5774status_t AudioFlinger::EffectModule::dump(int fd, const Vector<String16>& args)
5775{
5776 const size_t SIZE = 256;
5777 char buffer[SIZE];
5778 String8 result;
5779
5780 snprintf(buffer, SIZE, "\tEffect ID %d:\n", mId);
5781 result.append(buffer);
5782
5783 bool locked = tryLock(mLock);
5784 // failed to lock - AudioFlinger is probably deadlocked
5785 if (!locked) {
5786 result.append("\t\tCould not lock Fx mutex:\n");
5787 }
5788
5789 result.append("\t\tSession Status State Engine:\n");
5790 snprintf(buffer, SIZE, "\t\t%05d %03d %03d 0x%08x\n",
5791 mSessionId, mStatus, mState, (uint32_t)mEffectInterface);
5792 result.append(buffer);
5793
5794 result.append("\t\tDescriptor:\n");
5795 snprintf(buffer, SIZE, "\t\t- UUID: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
5796 mDescriptor.uuid.timeLow, mDescriptor.uuid.timeMid, mDescriptor.uuid.timeHiAndVersion,
5797 mDescriptor.uuid.clockSeq, mDescriptor.uuid.node[0], mDescriptor.uuid.node[1],mDescriptor.uuid.node[2],
5798 mDescriptor.uuid.node[3],mDescriptor.uuid.node[4],mDescriptor.uuid.node[5]);
5799 result.append(buffer);
5800 snprintf(buffer, SIZE, "\t\t- TYPE: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
5801 mDescriptor.type.timeLow, mDescriptor.type.timeMid, mDescriptor.type.timeHiAndVersion,
5802 mDescriptor.type.clockSeq, mDescriptor.type.node[0], mDescriptor.type.node[1],mDescriptor.type.node[2],
5803 mDescriptor.type.node[3],mDescriptor.type.node[4],mDescriptor.type.node[5]);
5804 result.append(buffer);
5805 snprintf(buffer, SIZE, "\t\t- apiVersion: %04X\n\t\t- flags: %08X\n",
5806 mDescriptor.apiVersion,
5807 mDescriptor.flags);
5808 result.append(buffer);
5809 snprintf(buffer, SIZE, "\t\t- name: %s\n",
5810 mDescriptor.name);
5811 result.append(buffer);
5812 snprintf(buffer, SIZE, "\t\t- implementor: %s\n",
5813 mDescriptor.implementor);
5814 result.append(buffer);
5815
5816 result.append("\t\t- Input configuration:\n");
5817 result.append("\t\t\tBuffer Frames Smp rate Channels Format\n");
5818 snprintf(buffer, SIZE, "\t\t\t0x%08x %05d %05d %08x %d\n",
5819 (uint32_t)mConfig.inputCfg.buffer.raw,
5820 mConfig.inputCfg.buffer.frameCount,
5821 mConfig.inputCfg.samplingRate,
5822 mConfig.inputCfg.channels,
5823 mConfig.inputCfg.format);
5824 result.append(buffer);
5825
5826 result.append("\t\t- Output configuration:\n");
5827 result.append("\t\t\tBuffer Frames Smp rate Channels Format\n");
5828 snprintf(buffer, SIZE, "\t\t\t0x%08x %05d %05d %08x %d\n",
5829 (uint32_t)mConfig.outputCfg.buffer.raw,
5830 mConfig.outputCfg.buffer.frameCount,
5831 mConfig.outputCfg.samplingRate,
5832 mConfig.outputCfg.channels,
5833 mConfig.outputCfg.format);
5834 result.append(buffer);
5835
5836 snprintf(buffer, SIZE, "\t\t%d Clients:\n", mHandles.size());
5837 result.append(buffer);
5838 result.append("\t\t\tPid Priority Ctrl Locked client server\n");
5839 for (size_t i = 0; i < mHandles.size(); ++i) {
5840 sp<EffectHandle> handle = mHandles[i].promote();
5841 if (handle != 0) {
5842 handle->dump(buffer, SIZE);
5843 result.append(buffer);
5844 }
5845 }
5846
5847 result.append("\n");
5848
5849 write(fd, result.string(), result.length());
5850
5851 if (locked) {
5852 mLock.unlock();
5853 }
5854
5855 return NO_ERROR;
5856}
5857
5858// ----------------------------------------------------------------------------
5859// EffectHandle implementation
5860// ----------------------------------------------------------------------------
5861
5862#undef LOG_TAG
5863#define LOG_TAG "AudioFlinger::EffectHandle"
5864
5865AudioFlinger::EffectHandle::EffectHandle(const sp<EffectModule>& effect,
5866 const sp<AudioFlinger::Client>& client,
5867 const sp<IEffectClient>& effectClient,
5868 int32_t priority)
5869 : BnEffect(),
5870 mEffect(effect), mEffectClient(effectClient), mClient(client), mPriority(priority), mHasControl(false)
5871{
5872 LOGV("constructor %p", this);
5873
5874 int bufOffset = ((sizeof(effect_param_cblk_t) - 1) / sizeof(int) + 1) * sizeof(int);
5875 mCblkMemory = client->heap()->allocate(EFFECT_PARAM_BUFFER_SIZE + bufOffset);
5876 if (mCblkMemory != 0) {
5877 mCblk = static_cast<effect_param_cblk_t *>(mCblkMemory->pointer());
5878
5879 if (mCblk) {
5880 new(mCblk) effect_param_cblk_t();
5881 mBuffer = (uint8_t *)mCblk + bufOffset;
5882 }
5883 } else {
5884 LOGE("not enough memory for Effect size=%u", EFFECT_PARAM_BUFFER_SIZE + sizeof(effect_param_cblk_t));
5885 return;
5886 }
5887}
5888
5889AudioFlinger::EffectHandle::~EffectHandle()
5890{
5891 LOGV("Destructor %p", this);
5892 disconnect();
5893}
5894
5895status_t AudioFlinger::EffectHandle::enable()
5896{
5897 if (!mHasControl) return INVALID_OPERATION;
5898 if (mEffect == 0) return DEAD_OBJECT;
5899
5900 return mEffect->setEnabled(true);
5901}
5902
5903status_t AudioFlinger::EffectHandle::disable()
5904{
5905 if (!mHasControl) return INVALID_OPERATION;
5906 if (mEffect == NULL) return DEAD_OBJECT;
5907
5908 return mEffect->setEnabled(false);
5909}
5910
5911void AudioFlinger::EffectHandle::disconnect()
5912{
5913 if (mEffect == 0) {
5914 return;
5915 }
5916 mEffect->disconnect(this);
5917 // release sp on module => module destructor can be called now
5918 mEffect.clear();
5919 if (mCblk) {
5920 mCblk->~effect_param_cblk_t(); // destroy our shared-structure.
5921 }
5922 mCblkMemory.clear(); // and free the shared memory
5923 if (mClient != 0) {
5924 Mutex::Autolock _l(mClient->audioFlinger()->mLock);
5925 mClient.clear();
5926 }
5927}
5928
Eric Laurent25f43952010-07-28 05:40:18 -07005929status_t AudioFlinger::EffectHandle::command(uint32_t cmdCode,
5930 uint32_t cmdSize,
5931 void *pCmdData,
5932 uint32_t *replySize,
5933 void *pReplyData)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005934{
Eric Laurent25f43952010-07-28 05:40:18 -07005935// LOGV("command(), cmdCode: %d, mHasControl: %d, mEffect: %p",
5936// cmdCode, mHasControl, (mEffect == 0) ? 0 : mEffect.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07005937
5938 // only get parameter command is permitted for applications not controlling the effect
5939 if (!mHasControl && cmdCode != EFFECT_CMD_GET_PARAM) {
5940 return INVALID_OPERATION;
5941 }
5942 if (mEffect == 0) return DEAD_OBJECT;
5943
5944 // handle commands that are not forwarded transparently to effect engine
5945 if (cmdCode == EFFECT_CMD_SET_PARAM_COMMIT) {
5946 // No need to trylock() here as this function is executed in the binder thread serving a particular client process:
5947 // no risk to block the whole media server process or mixer threads is we are stuck here
5948 Mutex::Autolock _l(mCblk->lock);
5949 if (mCblk->clientIndex > EFFECT_PARAM_BUFFER_SIZE ||
5950 mCblk->serverIndex > EFFECT_PARAM_BUFFER_SIZE) {
5951 mCblk->serverIndex = 0;
5952 mCblk->clientIndex = 0;
5953 return BAD_VALUE;
5954 }
5955 status_t status = NO_ERROR;
5956 while (mCblk->serverIndex < mCblk->clientIndex) {
5957 int reply;
Eric Laurent25f43952010-07-28 05:40:18 -07005958 uint32_t rsize = sizeof(int);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005959 int *p = (int *)(mBuffer + mCblk->serverIndex);
5960 int size = *p++;
5961 if (((uint8_t *)p + size) > mBuffer + mCblk->clientIndex) {
5962 LOGW("command(): invalid parameter block size");
5963 break;
5964 }
5965 effect_param_t *param = (effect_param_t *)p;
5966 if (param->psize == 0 || param->vsize == 0) {
5967 LOGW("command(): null parameter or value size");
5968 mCblk->serverIndex += size;
5969 continue;
5970 }
Eric Laurent25f43952010-07-28 05:40:18 -07005971 uint32_t psize = sizeof(effect_param_t) +
5972 ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) +
5973 param->vsize;
5974 status_t ret = mEffect->command(EFFECT_CMD_SET_PARAM,
5975 psize,
5976 p,
5977 &rsize,
5978 &reply);
Eric Laurentaeae3de2010-09-02 11:56:55 -07005979 // stop at first error encountered
5980 if (ret != NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005981 status = ret;
Eric Laurentaeae3de2010-09-02 11:56:55 -07005982 *(int *)pReplyData = reply;
5983 break;
5984 } else if (reply != NO_ERROR) {
5985 *(int *)pReplyData = reply;
5986 break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005987 }
5988 mCblk->serverIndex += size;
5989 }
5990 mCblk->serverIndex = 0;
5991 mCblk->clientIndex = 0;
5992 return status;
5993 } else if (cmdCode == EFFECT_CMD_ENABLE) {
Eric Laurentaeae3de2010-09-02 11:56:55 -07005994 *(int *)pReplyData = NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005995 return enable();
5996 } else if (cmdCode == EFFECT_CMD_DISABLE) {
Eric Laurentaeae3de2010-09-02 11:56:55 -07005997 *(int *)pReplyData = NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005998 return disable();
5999 }
6000
6001 return mEffect->command(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
6002}
6003
6004sp<IMemory> AudioFlinger::EffectHandle::getCblk() const {
6005 return mCblkMemory;
6006}
6007
6008void AudioFlinger::EffectHandle::setControl(bool hasControl, bool signal)
6009{
6010 LOGV("setControl %p control %d", this, hasControl);
6011
6012 mHasControl = hasControl;
6013 if (signal && mEffectClient != 0) {
6014 mEffectClient->controlStatusChanged(hasControl);
6015 }
6016}
6017
Eric Laurent25f43952010-07-28 05:40:18 -07006018void AudioFlinger::EffectHandle::commandExecuted(uint32_t cmdCode,
6019 uint32_t cmdSize,
6020 void *pCmdData,
6021 uint32_t replySize,
6022 void *pReplyData)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006023{
6024 if (mEffectClient != 0) {
6025 mEffectClient->commandExecuted(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
6026 }
6027}
6028
6029
6030
6031void AudioFlinger::EffectHandle::setEnabled(bool enabled)
6032{
6033 if (mEffectClient != 0) {
6034 mEffectClient->enableStatusChanged(enabled);
6035 }
6036}
6037
6038status_t AudioFlinger::EffectHandle::onTransact(
6039 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
6040{
6041 return BnEffect::onTransact(code, data, reply, flags);
6042}
6043
6044
6045void AudioFlinger::EffectHandle::dump(char* buffer, size_t size)
6046{
6047 bool locked = tryLock(mCblk->lock);
6048
6049 snprintf(buffer, size, "\t\t\t%05d %05d %01u %01u %05u %05u\n",
6050 (mClient == NULL) ? getpid() : mClient->pid(),
6051 mPriority,
6052 mHasControl,
6053 !locked,
6054 mCblk->clientIndex,
6055 mCblk->serverIndex
6056 );
6057
6058 if (locked) {
6059 mCblk->lock.unlock();
6060 }
6061}
6062
6063#undef LOG_TAG
6064#define LOG_TAG "AudioFlinger::EffectChain"
6065
6066AudioFlinger::EffectChain::EffectChain(const wp<ThreadBase>& wThread,
6067 int sessionId)
Eric Laurentcab11242010-07-15 12:50:15 -07006068 : mThread(wThread), mSessionId(sessionId), mActiveTrackCnt(0), mOwnInBuffer(false),
Eric Laurent8569f0d2010-07-29 23:43:43 -07006069 mVolumeCtrlIdx(-1), mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX),
6070 mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006071{
Dima Zavinfce7a472011-04-19 22:30:36 -07006072 mStrategy = AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006073}
6074
6075AudioFlinger::EffectChain::~EffectChain()
6076{
6077 if (mOwnInBuffer) {
6078 delete mInBuffer;
6079 }
6080
6081}
6082
Eric Laurentcab11242010-07-15 12:50:15 -07006083// getEffectFromDesc_l() must be called with PlaybackThread::mLock held
6084sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromDesc_l(effect_descriptor_t *descriptor)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006085{
6086 sp<EffectModule> effect;
6087 size_t size = mEffects.size();
6088
6089 for (size_t i = 0; i < size; i++) {
6090 if (memcmp(&mEffects[i]->desc().uuid, &descriptor->uuid, sizeof(effect_uuid_t)) == 0) {
6091 effect = mEffects[i];
6092 break;
6093 }
6094 }
6095 return effect;
6096}
6097
Eric Laurentcab11242010-07-15 12:50:15 -07006098// getEffectFromId_l() must be called with PlaybackThread::mLock held
6099sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromId_l(int id)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006100{
6101 sp<EffectModule> effect;
6102 size_t size = mEffects.size();
6103
6104 for (size_t i = 0; i < size; i++) {
Eric Laurentde070132010-07-13 04:45:46 -07006105 // by convention, return first effect if id provided is 0 (0 is never a valid id)
6106 if (id == 0 || mEffects[i]->id() == id) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006107 effect = mEffects[i];
6108 break;
6109 }
6110 }
6111 return effect;
6112}
6113
6114// Must be called with EffectChain::mLock locked
6115void AudioFlinger::EffectChain::process_l()
6116{
Eric Laurentdac69112010-09-28 14:09:57 -07006117 sp<ThreadBase> thread = mThread.promote();
6118 if (thread == 0) {
6119 LOGW("process_l(): cannot promote mixer thread");
6120 return;
6121 }
6122 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
Dima Zavinfce7a472011-04-19 22:30:36 -07006123 bool isGlobalSession = (mSessionId == AUDIO_SESSION_OUTPUT_MIX) ||
6124 (mSessionId == AUDIO_SESSION_OUTPUT_STAGE);
Eric Laurentdac69112010-09-28 14:09:57 -07006125 bool tracksOnSession = false;
6126 if (!isGlobalSession) {
6127 tracksOnSession =
6128 playbackThread->hasAudioSession(mSessionId) & PlaybackThread::TRACK_SESSION;
6129 }
6130
Mathias Agopian65ab4712010-07-14 17:59:35 -07006131 size_t size = mEffects.size();
Eric Laurentdac69112010-09-28 14:09:57 -07006132 // do not process effect if no track is present in same audio session
6133 if (isGlobalSession || tracksOnSession) {
6134 for (size_t i = 0; i < size; i++) {
6135 mEffects[i]->process();
6136 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006137 }
6138 for (size_t i = 0; i < size; i++) {
6139 mEffects[i]->updateState();
6140 }
6141 // if no track is active, input buffer must be cleared here as the mixer process
6142 // will not do it
Eric Laurentdac69112010-09-28 14:09:57 -07006143 if (tracksOnSession &&
6144 activeTracks() == 0) {
6145 size_t numSamples = playbackThread->frameCount() * playbackThread->channelCount();
6146 memset(mInBuffer, 0, numSamples * sizeof(int16_t));
Mathias Agopian65ab4712010-07-14 17:59:35 -07006147 }
6148}
6149
Eric Laurentcab11242010-07-15 12:50:15 -07006150// addEffect_l() must be called with PlaybackThread::mLock held
Eric Laurentde070132010-07-13 04:45:46 -07006151status_t AudioFlinger::EffectChain::addEffect_l(const sp<EffectModule>& effect)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006152{
6153 effect_descriptor_t desc = effect->desc();
6154 uint32_t insertPref = desc.flags & EFFECT_FLAG_INSERT_MASK;
6155
6156 Mutex::Autolock _l(mLock);
Eric Laurentde070132010-07-13 04:45:46 -07006157 effect->setChain(this);
6158 sp<ThreadBase> thread = mThread.promote();
6159 if (thread == 0) {
6160 return NO_INIT;
6161 }
6162 effect->setThread(thread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006163
6164 if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
6165 // Auxiliary effects are inserted at the beginning of mEffects vector as
6166 // they are processed first and accumulated in chain input buffer
6167 mEffects.insertAt(effect, 0);
Eric Laurentde070132010-07-13 04:45:46 -07006168
Mathias Agopian65ab4712010-07-14 17:59:35 -07006169 // the input buffer for auxiliary effect contains mono samples in
6170 // 32 bit format. This is to avoid saturation in AudoMixer
6171 // accumulation stage. Saturation is done in EffectModule::process() before
6172 // calling the process in effect engine
6173 size_t numSamples = thread->frameCount();
6174 int32_t *buffer = new int32_t[numSamples];
6175 memset(buffer, 0, numSamples * sizeof(int32_t));
6176 effect->setInBuffer((int16_t *)buffer);
6177 // auxiliary effects output samples to chain input buffer for further processing
6178 // by insert effects
6179 effect->setOutBuffer(mInBuffer);
6180 } else {
6181 // Insert effects are inserted at the end of mEffects vector as they are processed
6182 // after track and auxiliary effects.
6183 // Insert effect order as a function of indicated preference:
6184 // if EFFECT_FLAG_INSERT_EXCLUSIVE, insert in first position or reject if
6185 // another effect is present
6186 // else if EFFECT_FLAG_INSERT_FIRST, insert in first position or after the
6187 // last effect claiming first position
6188 // else if EFFECT_FLAG_INSERT_LAST, insert in last position or before the
6189 // first effect claiming last position
6190 // else if EFFECT_FLAG_INSERT_ANY insert after first or before last
6191 // Reject insertion if an effect with EFFECT_FLAG_INSERT_EXCLUSIVE is
6192 // already present
6193
6194 int size = (int)mEffects.size();
6195 int idx_insert = size;
6196 int idx_insert_first = -1;
6197 int idx_insert_last = -1;
6198
6199 for (int i = 0; i < size; i++) {
6200 effect_descriptor_t d = mEffects[i]->desc();
6201 uint32_t iMode = d.flags & EFFECT_FLAG_TYPE_MASK;
6202 uint32_t iPref = d.flags & EFFECT_FLAG_INSERT_MASK;
6203 if (iMode == EFFECT_FLAG_TYPE_INSERT) {
6204 // check invalid effect chaining combinations
6205 if (insertPref == EFFECT_FLAG_INSERT_EXCLUSIVE ||
6206 iPref == EFFECT_FLAG_INSERT_EXCLUSIVE) {
Eric Laurentcab11242010-07-15 12:50:15 -07006207 LOGW("addEffect_l() could not insert effect %s: exclusive conflict with %s", desc.name, d.name);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006208 return INVALID_OPERATION;
6209 }
6210 // remember position of first insert effect and by default
6211 // select this as insert position for new effect
6212 if (idx_insert == size) {
6213 idx_insert = i;
6214 }
6215 // remember position of last insert effect claiming
6216 // first position
6217 if (iPref == EFFECT_FLAG_INSERT_FIRST) {
6218 idx_insert_first = i;
6219 }
6220 // remember position of first insert effect claiming
6221 // last position
6222 if (iPref == EFFECT_FLAG_INSERT_LAST &&
6223 idx_insert_last == -1) {
6224 idx_insert_last = i;
6225 }
6226 }
6227 }
6228
6229 // modify idx_insert from first position if needed
6230 if (insertPref == EFFECT_FLAG_INSERT_LAST) {
6231 if (idx_insert_last != -1) {
6232 idx_insert = idx_insert_last;
6233 } else {
6234 idx_insert = size;
6235 }
6236 } else {
6237 if (idx_insert_first != -1) {
6238 idx_insert = idx_insert_first + 1;
6239 }
6240 }
6241
6242 // always read samples from chain input buffer
6243 effect->setInBuffer(mInBuffer);
6244
6245 // if last effect in the chain, output samples to chain
6246 // output buffer, otherwise to chain input buffer
6247 if (idx_insert == size) {
6248 if (idx_insert != 0) {
6249 mEffects[idx_insert-1]->setOutBuffer(mInBuffer);
6250 mEffects[idx_insert-1]->configure();
6251 }
6252 effect->setOutBuffer(mOutBuffer);
6253 } else {
6254 effect->setOutBuffer(mInBuffer);
6255 }
6256 mEffects.insertAt(effect, idx_insert);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006257
Eric Laurentcab11242010-07-15 12:50:15 -07006258 LOGV("addEffect_l() effect %p, added in chain %p at rank %d", effect.get(), this, idx_insert);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006259 }
6260 effect->configure();
6261 return NO_ERROR;
6262}
6263
Eric Laurentcab11242010-07-15 12:50:15 -07006264// removeEffect_l() must be called with PlaybackThread::mLock held
6265size_t AudioFlinger::EffectChain::removeEffect_l(const sp<EffectModule>& effect)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006266{
6267 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006268 int size = (int)mEffects.size();
6269 int i;
6270 uint32_t type = effect->desc().flags & EFFECT_FLAG_TYPE_MASK;
6271
6272 for (i = 0; i < size; i++) {
6273 if (effect == mEffects[i]) {
6274 if (type == EFFECT_FLAG_TYPE_AUXILIARY) {
6275 delete[] effect->inBuffer();
6276 } else {
6277 if (i == size - 1 && i != 0) {
6278 mEffects[i - 1]->setOutBuffer(mOutBuffer);
6279 mEffects[i - 1]->configure();
6280 }
6281 }
6282 mEffects.removeAt(i);
Eric Laurentcab11242010-07-15 12:50:15 -07006283 LOGV("removeEffect_l() effect %p, removed from chain %p at rank %d", effect.get(), this, i);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006284 break;
6285 }
6286 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006287
6288 return mEffects.size();
6289}
6290
Eric Laurentcab11242010-07-15 12:50:15 -07006291// setDevice_l() must be called with PlaybackThread::mLock held
6292void AudioFlinger::EffectChain::setDevice_l(uint32_t device)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006293{
6294 size_t size = mEffects.size();
6295 for (size_t i = 0; i < size; i++) {
6296 mEffects[i]->setDevice(device);
6297 }
6298}
6299
Eric Laurentcab11242010-07-15 12:50:15 -07006300// setMode_l() must be called with PlaybackThread::mLock held
6301void AudioFlinger::EffectChain::setMode_l(uint32_t mode)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006302{
6303 size_t size = mEffects.size();
6304 for (size_t i = 0; i < size; i++) {
6305 mEffects[i]->setMode(mode);
6306 }
6307}
6308
Eric Laurentcab11242010-07-15 12:50:15 -07006309// setVolume_l() must be called with PlaybackThread::mLock held
6310bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006311{
6312 uint32_t newLeft = *left;
6313 uint32_t newRight = *right;
6314 bool hasControl = false;
Eric Laurentcab11242010-07-15 12:50:15 -07006315 int ctrlIdx = -1;
6316 size_t size = mEffects.size();
Mathias Agopian65ab4712010-07-14 17:59:35 -07006317
Eric Laurentcab11242010-07-15 12:50:15 -07006318 // first update volume controller
6319 for (size_t i = size; i > 0; i--) {
Eric Laurent8f45bd72010-08-31 13:50:07 -07006320 if (mEffects[i - 1]->isProcessEnabled() &&
Eric Laurentcab11242010-07-15 12:50:15 -07006321 (mEffects[i - 1]->desc().flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL) {
6322 ctrlIdx = i - 1;
Eric Laurentf997cab2010-07-19 06:24:46 -07006323 hasControl = true;
Eric Laurentcab11242010-07-15 12:50:15 -07006324 break;
6325 }
6326 }
6327
6328 if (ctrlIdx == mVolumeCtrlIdx && *left == mLeftVolume && *right == mRightVolume) {
Eric Laurentf997cab2010-07-19 06:24:46 -07006329 if (hasControl) {
6330 *left = mNewLeftVolume;
6331 *right = mNewRightVolume;
6332 }
6333 return hasControl;
Eric Laurentcab11242010-07-15 12:50:15 -07006334 }
6335
6336 mVolumeCtrlIdx = ctrlIdx;
Eric Laurentf997cab2010-07-19 06:24:46 -07006337 mLeftVolume = newLeft;
6338 mRightVolume = newRight;
Eric Laurentcab11242010-07-15 12:50:15 -07006339
6340 // second get volume update from volume controller
6341 if (ctrlIdx >= 0) {
6342 mEffects[ctrlIdx]->setVolume(&newLeft, &newRight, true);
Eric Laurentf997cab2010-07-19 06:24:46 -07006343 mNewLeftVolume = newLeft;
6344 mNewRightVolume = newRight;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006345 }
6346 // then indicate volume to all other effects in chain.
6347 // Pass altered volume to effects before volume controller
6348 // and requested volume to effects after controller
6349 uint32_t lVol = newLeft;
6350 uint32_t rVol = newRight;
Eric Laurentcab11242010-07-15 12:50:15 -07006351
Mathias Agopian65ab4712010-07-14 17:59:35 -07006352 for (size_t i = 0; i < size; i++) {
Eric Laurentcab11242010-07-15 12:50:15 -07006353 if ((int)i == ctrlIdx) continue;
6354 // this also works for ctrlIdx == -1 when there is no volume controller
6355 if ((int)i > ctrlIdx) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006356 lVol = *left;
6357 rVol = *right;
6358 }
6359 mEffects[i]->setVolume(&lVol, &rVol, false);
6360 }
6361 *left = newLeft;
6362 *right = newRight;
6363
6364 return hasControl;
6365}
6366
Mathias Agopian65ab4712010-07-14 17:59:35 -07006367status_t AudioFlinger::EffectChain::dump(int fd, const Vector<String16>& args)
6368{
6369 const size_t SIZE = 256;
6370 char buffer[SIZE];
6371 String8 result;
6372
6373 snprintf(buffer, SIZE, "Effects for session %d:\n", mSessionId);
6374 result.append(buffer);
6375
6376 bool locked = tryLock(mLock);
6377 // failed to lock - AudioFlinger is probably deadlocked
6378 if (!locked) {
6379 result.append("\tCould not lock mutex:\n");
6380 }
6381
Eric Laurentcab11242010-07-15 12:50:15 -07006382 result.append("\tNum fx In buffer Out buffer Active tracks:\n");
6383 snprintf(buffer, SIZE, "\t%02d 0x%08x 0x%08x %d\n",
Mathias Agopian65ab4712010-07-14 17:59:35 -07006384 mEffects.size(),
6385 (uint32_t)mInBuffer,
6386 (uint32_t)mOutBuffer,
Mathias Agopian65ab4712010-07-14 17:59:35 -07006387 mActiveTrackCnt);
6388 result.append(buffer);
6389 write(fd, result.string(), result.size());
6390
6391 for (size_t i = 0; i < mEffects.size(); ++i) {
6392 sp<EffectModule> effect = mEffects[i];
6393 if (effect != 0) {
6394 effect->dump(fd, args);
6395 }
6396 }
6397
6398 if (locked) {
6399 mLock.unlock();
6400 }
6401
6402 return NO_ERROR;
6403}
6404
6405#undef LOG_TAG
6406#define LOG_TAG "AudioFlinger"
6407
6408// ----------------------------------------------------------------------------
6409
6410status_t AudioFlinger::onTransact(
6411 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
6412{
6413 return BnAudioFlinger::onTransact(code, data, reply, flags);
6414}
6415
Mathias Agopian65ab4712010-07-14 17:59:35 -07006416}; // namespace android