blob: cef551c947b892a5e370269c3a7c71b60cd40d1b [file] [log] [blame]
Glenn Kasten99e53b82012-01-19 08:59:58 -08001/*
Alok Kediya601e9b52013-09-27 11:55:10 +05302** Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
3** Not a Contribution.
Mathias Agopian65ab4712010-07-14 17:59:35 -07004** Copyright 2007, The Android Open Source Project
5**
6** Licensed under the Apache License, Version 2.0 (the "License");
7** you may not use this file except in compliance with the License.
8** You may obtain a copy of the License at
9**
10** http://www.apache.org/licenses/LICENSE-2.0
11**
12** Unless required by applicable law or agreed to in writing, software
13** distributed under the License is distributed on an "AS IS" BASIS,
14** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15** See the License for the specific language governing permissions and
16** limitations under the License.
17*/
18
19
20#define LOG_TAG "AudioFlinger"
21//#define LOG_NDEBUG 0
22
Glenn Kasten153b9fe2013-07-15 11:23:36 -070023#include "Configuration.h"
Glenn Kastenda6ef132013-01-10 12:31:01 -080024#include <dirent.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070025#include <math.h>
26#include <signal.h>
27#include <sys/time.h>
28#include <sys/resource.h>
29
Gloria Wang9ee159b2011-02-24 14:51:45 -080030#include <binder/IPCThreadState.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070031#include <binder/IServiceManager.h>
32#include <utils/Log.h>
Glenn Kastend8e6fd32012-05-07 11:07:57 -070033#include <utils/Trace.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070034#include <binder/Parcel.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070035#include <utils/String16.h>
36#include <utils/threads.h>
Eric Laurent38ccae22011-03-28 18:37:07 -070037#include <utils/Atomic.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070038
Dima Zavinfce7a472011-04-19 22:30:36 -070039#include <cutils/bitops.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070040#include <cutils/properties.h>
41
Dima Zavin64760242011-05-11 14:15:23 -070042#include <system/audio.h>
Dima Zavin7394a4f2011-06-13 18:16:26 -070043#include <hardware/audio.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070044
45#include "AudioMixer.h"
46#include "AudioFlinger.h"
Glenn Kasten44deb052012-02-05 18:09:08 -080047#include "ServiceUtilities.h"
Mathias Agopian65ab4712010-07-14 17:59:35 -070048
Mathias Agopian65ab4712010-07-14 17:59:35 -070049#include <media/EffectsFactoryApi.h>
Eric Laurent6d8b6942011-06-24 07:01:31 -070050#include <audio_effects/effect_visualizer.h>
Eric Laurent59bd0da2011-08-01 09:52:20 -070051#include <audio_effects/effect_ns.h>
52#include <audio_effects/effect_aec.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070053
Glenn Kasten3b21c502011-12-15 09:52:39 -080054#include <audio_utils/primitives.h>
55
Eric Laurentfeb0db62011-07-22 09:04:31 -070056#include <powermanager/PowerManager.h>
Glenn Kasten190a46f2012-03-06 11:27:10 -080057
John Grossman4ff14ba2012-02-08 16:37:41 -080058#include <common_time/cc_helper.h>
Glenn Kasten58912562012-04-03 10:45:00 -070059
Glenn Kasten9e58b552013-01-18 15:09:48 -080060#include <media/IMediaLogService.h>
61
Glenn Kastenda6ef132013-01-10 12:31:01 -080062#include <media/nbaio/Pipe.h>
63#include <media/nbaio/PipeReader.h>
Glenn Kasten1ab85ec2013-05-31 09:18:43 -070064#include <media/AudioParameter.h>
Glenn Kasten4182c4e2013-07-15 14:45:07 -070065#include <private/android_filesystem_config.h>
Glenn Kastenda6ef132013-01-10 12:31:01 -080066
Alok Kediya601e9b52013-09-27 11:55:10 +053067#ifdef SRS_PROCESSING
68#include "srs_processing.h"
69#include "postpro_patch_ics.h"
70#endif
71
Mathias Agopian65ab4712010-07-14 17:59:35 -070072// ----------------------------------------------------------------------------
Mathias Agopian65ab4712010-07-14 17:59:35 -070073
John Grossman1c345192012-03-27 14:00:17 -070074// Note: the following macro is used for extremely verbose logging message. In
75// order to run with ALOG_ASSERT turned on, we need to have LOG_NDEBUG set to
76// 0; but one side effect of this is to turn all LOGV's as well. Some messages
77// are so verbose that we want to suppress them even when we have ALOG_ASSERT
78// turned on. Do not uncomment the #def below unless you really know what you
79// are doing and want to see all of the extremely verbose messages.
80//#define VERY_VERY_VERBOSE_LOGGING
81#ifdef VERY_VERY_VERBOSE_LOGGING
82#define ALOGVV ALOGV
83#else
84#define ALOGVV(a...) do { } while(0)
85#endif
Eric Laurentde070132010-07-13 04:45:46 -070086
Mathias Agopian65ab4712010-07-14 17:59:35 -070087namespace android {
88
Glenn Kastenec1d6b52011-12-12 09:04:45 -080089static const char kDeadlockedString[] = "AudioFlinger may be deadlocked\n";
90static const char kHardwareLockedString[] = "Hardware lock is taken\n";
Mathias Agopian65ab4712010-07-14 17:59:35 -070091
Glenn Kasten58912562012-04-03 10:45:00 -070092
John Grossman4ff14ba2012-02-08 16:37:41 -080093nsecs_t AudioFlinger::mStandbyTimeInNsecs = kDefaultStandbyTimeInNsecs;
Eric Laurent7cafbb32011-11-22 18:50:29 -080094
Eric Laurent81784c32012-11-19 14:55:58 -080095uint32_t AudioFlinger::mScreenState;
Glenn Kasten3ed29202012-08-07 15:24:44 -070096
Glenn Kasten46909e72013-02-26 09:20:22 -080097#ifdef TEE_SINK
Glenn Kastenda6ef132013-01-10 12:31:01 -080098bool AudioFlinger::mTeeSinkInputEnabled = false;
99bool AudioFlinger::mTeeSinkOutputEnabled = false;
100bool AudioFlinger::mTeeSinkTrackEnabled = false;
101
102size_t AudioFlinger::mTeeSinkInputFrames = kTeeSinkInputFramesDefault;
103size_t AudioFlinger::mTeeSinkOutputFrames = kTeeSinkOutputFramesDefault;
104size_t AudioFlinger::mTeeSinkTrackFrames = kTeeSinkTrackFramesDefault;
Glenn Kasten46909e72013-02-26 09:20:22 -0800105#endif
Glenn Kastenda6ef132013-01-10 12:31:01 -0800106
Eric Laurent813e2a72013-08-31 12:59:48 -0700107// In order to avoid invalidating offloaded tracks each time a Visualizer is turned on and off
108// we define a minimum time during which a global effect is considered enabled.
109static const nsecs_t kMinGlobalEffectEnabletimeNs = seconds(7200);
110
Mathias Agopian65ab4712010-07-14 17:59:35 -0700111// ----------------------------------------------------------------------------
112
Eric Laurentf7ffb8b2012-04-14 09:06:57 -0700113static int load_audio_interface(const char *if_name, audio_hw_device_t **dev)
Dima Zavin799a70e2011-04-18 16:57:27 -0700114{
Eric Laurentf7ffb8b2012-04-14 09:06:57 -0700115 const hw_module_t *mod;
Dima Zavin799a70e2011-04-18 16:57:27 -0700116 int rc;
117
Eric Laurentf7ffb8b2012-04-14 09:06:57 -0700118 rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, &mod);
119 ALOGE_IF(rc, "%s couldn't load audio hw module %s.%s (%s)", __func__,
120 AUDIO_HARDWARE_MODULE_ID, if_name, strerror(-rc));
121 if (rc) {
Dima Zavin799a70e2011-04-18 16:57:27 -0700122 goto out;
Eric Laurentf7ffb8b2012-04-14 09:06:57 -0700123 }
124 rc = audio_hw_device_open(mod, dev);
125 ALOGE_IF(rc, "%s couldn't open audio hw device in %s.%s (%s)", __func__,
126 AUDIO_HARDWARE_MODULE_ID, if_name, strerror(-rc));
127 if (rc) {
Dima Zavin799a70e2011-04-18 16:57:27 -0700128 goto out;
Eric Laurentf7ffb8b2012-04-14 09:06:57 -0700129 }
Ricardo Cerqueira0d44b5b2013-11-03 02:46:27 +0000130#if !defined(ICS_AUDIO_BLOB) && !defined(MR0_AUDIO_BLOB)
Eric Laurentf7ffb8b2012-04-14 09:06:57 -0700131 if ((*dev)->common.version != AUDIO_DEVICE_API_VERSION_CURRENT) {
132 ALOGE("%s wrong audio hw device version %04x", __func__, (*dev)->common.version);
133 rc = BAD_VALUE;
134 goto out;
135 }
Ricardo Cerqueira0d44b5b2013-11-03 02:46:27 +0000136#endif
Dima Zavin799a70e2011-04-18 16:57:27 -0700137 return 0;
138
139out:
Dima Zavin799a70e2011-04-18 16:57:27 -0700140 *dev = NULL;
141 return rc;
142}
143
Mathias Agopian65ab4712010-07-14 17:59:35 -0700144// ----------------------------------------------------------------------------
145
146AudioFlinger::AudioFlinger()
147 : BnAudioFlinger(),
John Grossman4ff14ba2012-02-08 16:37:41 -0800148 mPrimaryHardwareDev(NULL),
Glenn Kasten7d6c35b2012-07-02 12:45:10 -0700149 mHardwareStatus(AUDIO_HW_IDLE),
John Grossman4ff14ba2012-02-08 16:37:41 -0800150 mMasterVolume(1.0f),
John Grossman4ff14ba2012-02-08 16:37:41 -0800151 mMasterMute(false),
152 mNextUniqueId(1),
153 mMode(AUDIO_MODE_INVALID),
Glenn Kasten4182c4e2013-07-15 14:45:07 -0700154 mBtNrecIsOff(false),
155 mIsLowRamDevice(true),
Eric Laurent813e2a72013-08-31 12:59:48 -0700156 mIsDeviceTypeKnown(false),
Alok Kediya601e9b52013-09-27 11:55:10 +0530157 mGlobalEffectEnableTime(0),
158 mAllChainsLocked(false)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700159{
Glenn Kasten949a9262013-04-16 12:35:20 -0700160 getpid_cached = getpid();
Glenn Kasten9e58b552013-01-18 15:09:48 -0800161 char value[PROPERTY_VALUE_MAX];
162 bool doLog = (property_get("ro.test_harness", value, "0") > 0) && (atoi(value) == 1);
163 if (doLog) {
164 mLogMemoryDealer = new MemoryDealer(kLogMemorySize, "LogWriters");
165 }
Glenn Kasten46909e72013-02-26 09:20:22 -0800166#ifdef TEE_SINK
Glenn Kastenda6ef132013-01-10 12:31:01 -0800167 (void) property_get("ro.debuggable", value, "0");
168 int debuggable = atoi(value);
169 int teeEnabled = 0;
170 if (debuggable) {
171 (void) property_get("af.tee", value, "0");
172 teeEnabled = atoi(value);
173 }
174 if (teeEnabled & 1)
175 mTeeSinkInputEnabled = true;
176 if (teeEnabled & 2)
177 mTeeSinkOutputEnabled = true;
178 if (teeEnabled & 4)
179 mTeeSinkTrackEnabled = true;
Glenn Kasten46909e72013-02-26 09:20:22 -0800180#endif
Dima Zavin5a61d2f2011-04-19 19:04:32 -0700181}
182
183void AudioFlinger::onFirstRef()
184{
Dima Zavin799a70e2011-04-18 16:57:27 -0700185 int rc = 0;
Dima Zavinfce7a472011-04-19 22:30:36 -0700186
Eric Laurent93575202011-01-18 18:39:02 -0800187 Mutex::Autolock _l(mLock);
188
Dima Zavin799a70e2011-04-18 16:57:27 -0700189 /* TODO: move all this work into an Init() function */
John Grossman4ff14ba2012-02-08 16:37:41 -0800190 char val_str[PROPERTY_VALUE_MAX] = { 0 };
191 if (property_get("ro.audio.flinger_standbytime_ms", val_str, NULL) >= 0) {
192 uint32_t int_val;
193 if (1 == sscanf(val_str, "%u", &int_val)) {
194 mStandbyTimeInNsecs = milliseconds(int_val);
195 ALOGI("Using %u mSec as standby time.", int_val);
196 } else {
197 mStandbyTimeInNsecs = kDefaultStandbyTimeInNsecs;
198 ALOGI("Using default %u mSec as standby time.",
199 (uint32_t)(mStandbyTimeInNsecs / 1000000));
200 }
201 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700202
Eric Laurenta4c5a552012-03-29 10:12:40 -0700203 mMode = AUDIO_MODE_NORMAL;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700204}
205
206AudioFlinger::~AudioFlinger()
207{
208 while (!mRecordThreads.isEmpty()) {
Glenn Kastenc3ae93f2012-07-30 10:59:30 -0700209 // closeInput_nonvirtual() will remove specified entry from mRecordThreads
Glenn Kastend96c5722012-04-25 13:44:49 -0700210 closeInput_nonvirtual(mRecordThreads.keyAt(0));
Mathias Agopian65ab4712010-07-14 17:59:35 -0700211 }
212 while (!mPlaybackThreads.isEmpty()) {
Glenn Kastenc3ae93f2012-07-30 10:59:30 -0700213 // closeOutput_nonvirtual() will remove specified entry from mPlaybackThreads
Glenn Kastend96c5722012-04-25 13:44:49 -0700214 closeOutput_nonvirtual(mPlaybackThreads.keyAt(0));
Mathias Agopian65ab4712010-07-14 17:59:35 -0700215 }
Dima Zavin799a70e2011-04-18 16:57:27 -0700216
Glenn Kasten2b213bc2012-02-02 14:05:20 -0800217 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
218 // no mHardwareLock needed, as there are no other references to this
Eric Laurenta4c5a552012-03-29 10:12:40 -0700219 audio_hw_device_close(mAudioHwDevs.valueAt(i)->hwDevice());
220 delete mAudioHwDevs.valueAt(i);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700221 }
222}
223
Eric Laurenta4c5a552012-03-29 10:12:40 -0700224static const char * const audio_interfaces[] = {
225 AUDIO_HARDWARE_MODULE_ID_PRIMARY,
226 AUDIO_HARDWARE_MODULE_ID_A2DP,
227 AUDIO_HARDWARE_MODULE_ID_USB,
228};
229#define ARRAY_SIZE(x) (sizeof((x))/sizeof(((x)[0])))
230
John Grossmanee578c02012-07-23 17:05:46 -0700231AudioFlinger::AudioHwDevice* AudioFlinger::findSuitableHwDev_l(
232 audio_module_handle_t module,
233 audio_devices_t devices)
Dima Zavin799a70e2011-04-18 16:57:27 -0700234{
Eric Laurenta4c5a552012-03-29 10:12:40 -0700235 // if module is 0, the request comes from an old policy manager and we should load
236 // well known modules
237 if (module == 0) {
238 ALOGW("findSuitableHwDev_l() loading well know audio hw modules");
239 for (size_t i = 0; i < ARRAY_SIZE(audio_interfaces); i++) {
240 loadHwModule_l(audio_interfaces[i]);
241 }
Eric Laurentf1c04f92012-08-28 14:26:53 -0700242 // then try to find a module supporting the requested device.
243 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
244 AudioHwDevice *audioHwDevice = mAudioHwDevs.valueAt(i);
245 audio_hw_device_t *dev = audioHwDevice->hwDevice();
246 if ((dev->get_supported_devices != NULL) &&
247 (dev->get_supported_devices(dev) & devices) == devices)
248 return audioHwDevice;
Ricardo Cerqueira2b3c7972013-01-10 23:53:09 +0000249#ifdef ICS_AUDIO_BLOB
250 else if (dev->get_supported_devices == NULL && i != 0 &&
251 devices == 0x80)
252 // Reasonably safe assumption: A non-primary HAL without
253 // get_supported_devices is a locally-built A2DP binary
254 return audioHwDevice;
255#endif
Eric Laurentf1c04f92012-08-28 14:26:53 -0700256 }
Eric Laurenta4c5a552012-03-29 10:12:40 -0700257 } else {
258 // check a match for the requested module handle
John Grossmanee578c02012-07-23 17:05:46 -0700259 AudioHwDevice *audioHwDevice = mAudioHwDevs.valueFor(module);
260 if (audioHwDevice != NULL) {
261 return audioHwDevice;
Eric Laurenta4c5a552012-03-29 10:12:40 -0700262 }
263 }
Eric Laurenta4c5a552012-03-29 10:12:40 -0700264
Dima Zavin799a70e2011-04-18 16:57:27 -0700265 return NULL;
266}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700267
Glenn Kastenbe5f05e2012-07-18 15:24:02 -0700268void AudioFlinger::dumpClients(int fd, const Vector<String16>& args)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700269{
270 const size_t SIZE = 256;
271 char buffer[SIZE];
272 String8 result;
273
274 result.append("Clients:\n");
275 for (size_t i = 0; i < mClients.size(); ++i) {
Glenn Kasten77c11192012-01-25 14:27:41 -0800276 sp<Client> client = mClients.valueAt(i).promote();
277 if (client != 0) {
278 snprintf(buffer, SIZE, " pid: %d\n", client->pid());
279 result.append(buffer);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700280 }
281 }
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700282
Eric Laurentd1b28d42013-09-18 18:47:13 -0700283 result.append("Notification Clients:\n");
284 for (size_t i = 0; i < mNotificationClients.size(); ++i) {
285 snprintf(buffer, SIZE, " pid: %d\n", mNotificationClients.keyAt(i));
286 result.append(buffer);
287 }
288
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700289 result.append("Global session refs:\n");
Glenn Kasten012ca6b2012-03-06 11:22:01 -0800290 result.append(" session pid count\n");
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700291 for (size_t i = 0; i < mAudioSessionRefs.size(); i++) {
292 AudioSessionRef *r = mAudioSessionRefs[i];
Glenn Kasten012ca6b2012-03-06 11:22:01 -0800293 snprintf(buffer, SIZE, " %7d %3d %3d\n", r->mSessionid, r->mPid, r->mCnt);
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700294 result.append(buffer);
295 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700296 write(fd, result.string(), result.size());
Mathias Agopian65ab4712010-07-14 17:59:35 -0700297}
298
299
Glenn Kastenbe5f05e2012-07-18 15:24:02 -0700300void AudioFlinger::dumpInternals(int fd, const Vector<String16>& args)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700301{
302 const size_t SIZE = 256;
303 char buffer[SIZE];
304 String8 result;
Glenn Kastena4454b42012-01-04 11:02:33 -0800305 hardware_call_state hardwareStatus = mHardwareStatus;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700306
John Grossman4ff14ba2012-02-08 16:37:41 -0800307 snprintf(buffer, SIZE, "Hardware status: %d\n"
308 "Standby Time mSec: %u\n",
309 hardwareStatus,
310 (uint32_t)(mStandbyTimeInNsecs / 1000000));
Mathias Agopian65ab4712010-07-14 17:59:35 -0700311 result.append(buffer);
312 write(fd, result.string(), result.size());
Mathias Agopian65ab4712010-07-14 17:59:35 -0700313}
314
Glenn Kastenbe5f05e2012-07-18 15:24:02 -0700315void AudioFlinger::dumpPermissionDenial(int fd, const Vector<String16>& args)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700316{
317 const size_t SIZE = 256;
318 char buffer[SIZE];
319 String8 result;
320 snprintf(buffer, SIZE, "Permission Denial: "
321 "can't dump AudioFlinger from pid=%d, uid=%d\n",
322 IPCThreadState::self()->getCallingPid(),
323 IPCThreadState::self()->getCallingUid());
324 result.append(buffer);
325 write(fd, result.string(), result.size());
Mathias Agopian65ab4712010-07-14 17:59:35 -0700326}
327
Eric Laurent81784c32012-11-19 14:55:58 -0800328bool AudioFlinger::dumpTryLock(Mutex& mutex)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700329{
330 bool locked = false;
331 for (int i = 0; i < kDumpLockRetries; ++i) {
332 if (mutex.tryLock() == NO_ERROR) {
333 locked = true;
334 break;
335 }
Glenn Kasten7dede872011-12-13 11:04:14 -0800336 usleep(kDumpLockSleepUs);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700337 }
338 return locked;
339}
340
341status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
342{
Glenn Kasten44deb052012-02-05 18:09:08 -0800343 if (!dumpAllowed()) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700344 dumpPermissionDenial(fd, args);
345 } else {
346 // get state of hardware lock
Eric Laurent81784c32012-11-19 14:55:58 -0800347 bool hardwareLocked = dumpTryLock(mHardwareLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700348 if (!hardwareLocked) {
349 String8 result(kHardwareLockedString);
350 write(fd, result.string(), result.size());
351 } else {
352 mHardwareLock.unlock();
353 }
354
Eric Laurent81784c32012-11-19 14:55:58 -0800355 bool locked = dumpTryLock(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700356
357 // failed to lock - AudioFlinger is probably deadlocked
358 if (!locked) {
359 String8 result(kDeadlockedString);
360 write(fd, result.string(), result.size());
361 }
362
363 dumpClients(fd, args);
364 dumpInternals(fd, args);
365
366 // dump playback threads
367 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
368 mPlaybackThreads.valueAt(i)->dump(fd, args);
369 }
370
371 // dump record threads
372 for (size_t i = 0; i < mRecordThreads.size(); i++) {
373 mRecordThreads.valueAt(i)->dump(fd, args);
374 }
375
Dima Zavin799a70e2011-04-18 16:57:27 -0700376 // dump all hardware devs
377 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
Eric Laurenta4c5a552012-03-29 10:12:40 -0700378 audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();
Dima Zavin799a70e2011-04-18 16:57:27 -0700379 dev->dump(dev, fd);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700380 }
Glenn Kastend06785b2012-09-30 12:29:28 -0700381
Glenn Kasten46909e72013-02-26 09:20:22 -0800382#ifdef TEE_SINK
Glenn Kastend06785b2012-09-30 12:29:28 -0700383 // dump the serially shared record tee sink
384 if (mRecordTeeSource != 0) {
385 dumpTee(fd, mRecordTeeSource);
386 }
Glenn Kasten46909e72013-02-26 09:20:22 -0800387#endif
Glenn Kastend06785b2012-09-30 12:29:28 -0700388
Glenn Kastend65d73c2012-06-22 17:21:07 -0700389 if (locked) {
390 mLock.unlock();
391 }
Glenn Kasten9e58b552013-01-18 15:09:48 -0800392
393 // append a copy of media.log here by forwarding fd to it, but don't attempt
394 // to lookup the service if it's not running, as it will block for a second
395 if (mLogMemoryDealer != 0) {
396 sp<IBinder> binder = defaultServiceManager()->getService(String16("media.log"));
397 if (binder != 0) {
398 fdprintf(fd, "\nmedia.log:\n");
399 Vector<String16> args;
400 binder->dump(fd, args);
401 }
402 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700403 }
404 return NO_ERROR;
405}
406
Glenn Kasten98ec94c2012-01-25 14:28:29 -0800407sp<AudioFlinger::Client> AudioFlinger::registerPid_l(pid_t pid)
408{
409 // If pid is already in the mClients wp<> map, then use that entry
410 // (for which promote() is always != 0), otherwise create a new entry and Client.
411 sp<Client> client = mClients.valueFor(pid).promote();
412 if (client == 0) {
413 client = new Client(this, pid);
414 mClients.add(pid, client);
415 }
416
417 return client;
418}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700419
Glenn Kasten9e58b552013-01-18 15:09:48 -0800420sp<NBLog::Writer> AudioFlinger::newWriter_l(size_t size, const char *name)
421{
422 if (mLogMemoryDealer == 0) {
423 return new NBLog::Writer();
424 }
425 sp<IMemory> shared = mLogMemoryDealer->allocate(NBLog::Timeline::sharedSize(size));
426 sp<NBLog::Writer> writer = new NBLog::Writer(size, shared);
427 sp<IBinder> binder = defaultServiceManager()->getService(String16("media.log"));
428 if (binder != 0) {
429 interface_cast<IMediaLogService>(binder)->registerWriter(shared, size, name);
430 }
431 return writer;
432}
433
434void AudioFlinger::unregisterWriter(const sp<NBLog::Writer>& writer)
435{
Glenn Kasten685ef092013-02-04 08:15:34 -0800436 if (writer == 0) {
437 return;
438 }
Glenn Kasten9e58b552013-01-18 15:09:48 -0800439 sp<IMemory> iMemory(writer->getIMemory());
440 if (iMemory == 0) {
441 return;
442 }
443 sp<IBinder> binder = defaultServiceManager()->getService(String16("media.log"));
444 if (binder != 0) {
445 interface_cast<IMediaLogService>(binder)->unregisterWriter(iMemory);
446 // Now the media.log remote reference to IMemory is gone.
447 // When our last local reference to IMemory also drops to zero,
448 // the IMemory destructor will deallocate the region from mMemoryDealer.
449 }
450}
451
Mathias Agopian65ab4712010-07-14 17:59:35 -0700452// IAudioFlinger interface
453
454
455sp<IAudioTrack> AudioFlinger::createTrack(
Glenn Kastenfff6d712012-01-12 16:38:12 -0800456 audio_stream_type_t streamType,
Mathias Agopian65ab4712010-07-14 17:59:35 -0700457 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -0800458 audio_format_t format,
Glenn Kasten254af182012-07-03 14:59:05 -0700459 audio_channel_mask_t channelMask,
Glenn Kastene33054e2012-11-14 12:54:39 -0800460 size_t frameCount,
Glenn Kastene0b07172012-11-06 15:03:34 -0800461 IAudioFlinger::track_flags_t *flags,
Mathias Agopian65ab4712010-07-14 17:59:35 -0700462 const sp<IMemory>& sharedBuffer,
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800463 audio_io_handle_t output,
Glenn Kasten3acbd052012-02-28 10:39:56 -0800464 pid_t tid,
Mathias Agopian65ab4712010-07-14 17:59:35 -0700465 int *sessionId,
Glenn Kastend054c322013-07-12 12:59:20 -0700466 String8& name,
Mathias Agopian65ab4712010-07-14 17:59:35 -0700467 status_t *status)
468{
469 sp<PlaybackThread::Track> track;
470 sp<TrackHandle> trackHandle;
471 sp<Client> client;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700472 status_t lStatus;
473 int lSessionId;
474
Glenn Kasten263709e2012-01-06 08:40:01 -0800475 // client AudioTrack::set already implements AUDIO_STREAM_DEFAULT => AUDIO_STREAM_MUSIC,
476 // but if someone uses binder directly they could bypass that and cause us to crash
477 if (uint32_t(streamType) >= AUDIO_STREAM_CNT) {
Steve Block29357bc2012-01-06 19:20:56 +0000478 ALOGE("createTrack() invalid stream type %d", streamType);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700479 lStatus = BAD_VALUE;
480 goto Exit;
481 }
482
Glenn Kasten60a83922012-06-21 12:56:37 -0700483 // client is responsible for conversion of 8-bit PCM to 16-bit PCM,
484 // and we don't yet support 8.24 or 32-bit PCM
485 if (audio_is_linear_pcm(format) && format != AUDIO_FORMAT_PCM_16_BIT) {
486 ALOGE("createTrack() invalid format %d", format);
487 lStatus = BAD_VALUE;
488 goto Exit;
489 }
490
Mathias Agopian65ab4712010-07-14 17:59:35 -0700491 {
492 Mutex::Autolock _l(mLock);
493 PlaybackThread *thread = checkPlaybackThread_l(output);
Eric Laurent39e94f82010-07-28 01:32:47 -0700494 PlaybackThread *effectThread = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700495 if (thread == NULL) {
Glenn Kastenc9b2e202013-02-26 11:32:32 -0800496 ALOGE("no playback thread found for output handle %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700497 lStatus = BAD_VALUE;
498 goto Exit;
499 }
500
Glenn Kasten8d6cc842012-02-03 11:06:53 -0800501 pid_t pid = IPCThreadState::self()->getCallingPid();
Glenn Kasten98ec94c2012-01-25 14:28:29 -0800502 client = registerPid_l(pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700503
Steve Block3856b092011-10-20 11:56:00 +0100504 ALOGV("createTrack() sessionId: %d", (sessionId == NULL) ? -2 : *sessionId);
Dima Zavinfce7a472011-04-19 22:30:36 -0700505 if (sessionId != NULL && *sessionId != AUDIO_SESSION_OUTPUT_MIX) {
Eric Laurentf436fdc2012-05-24 11:07:14 -0700506 // check if an effect chain with the same session ID is present on another
507 // output thread and move it here.
Eric Laurentde070132010-07-13 04:45:46 -0700508 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurent39e94f82010-07-28 01:32:47 -0700509 sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
510 if (mPlaybackThreads.keyAt(i) != output) {
Eric Laurent39e94f82010-07-28 01:32:47 -0700511 uint32_t sessions = t->hasAudioSession(*sessionId);
Eric Laurent39e94f82010-07-28 01:32:47 -0700512 if (sessions & PlaybackThread::EFFECT_SESSION) {
513 effectThread = t.get();
Eric Laurentf436fdc2012-05-24 11:07:14 -0700514 break;
Eric Laurent39e94f82010-07-28 01:32:47 -0700515 }
Eric Laurentde070132010-07-13 04:45:46 -0700516 }
517 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700518 lSessionId = *sessionId;
519 } else {
Eric Laurentde070132010-07-13 04:45:46 -0700520 // if no audio session id is provided, create one here
Eric Laurent7c7f10b2011-06-17 21:29:58 -0700521 lSessionId = nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700522 if (sessionId != NULL) {
523 *sessionId = lSessionId;
524 }
525 }
Steve Block3856b092011-10-20 11:56:00 +0100526 ALOGV("createTrack() lSessionId: %d", lSessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700527
528 track = thread->createTrack_l(client, streamType, sampleRate, format,
Glenn Kasten3acbd052012-02-28 10:39:56 -0800529 channelMask, frameCount, sharedBuffer, lSessionId, flags, tid, &lStatus);
Eric Laurent39e94f82010-07-28 01:32:47 -0700530
531 // move effect chain to this output thread if an effect on same session was waiting
532 // for a track to be created
533 if (lStatus == NO_ERROR && effectThread != NULL) {
534 Mutex::Autolock _dl(thread->mLock);
535 Mutex::Autolock _sl(effectThread->mLock);
536 moveEffectChain_l(lSessionId, effectThread, thread, true);
537 }
Eric Laurenta011e352012-03-29 15:51:43 -0700538
539 // Look for sync events awaiting for a session to be used.
540 for (int i = 0; i < (int)mPendingSyncEvents.size(); i++) {
541 if (mPendingSyncEvents[i]->triggerSession() == lSessionId) {
542 if (thread->isValidSyncEvent(mPendingSyncEvents[i])) {
Eric Laurent29864602012-05-08 18:57:51 -0700543 if (lStatus == NO_ERROR) {
Glenn Kastend23eedc2012-08-02 13:35:47 -0700544 (void) track->setSyncEvent(mPendingSyncEvents[i]);
Eric Laurent29864602012-05-08 18:57:51 -0700545 } else {
546 mPendingSyncEvents[i]->cancel();
547 }
Eric Laurenta011e352012-03-29 15:51:43 -0700548 mPendingSyncEvents.removeAt(i);
549 i--;
550 }
551 }
552 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700553 }
554 if (lStatus == NO_ERROR) {
Glenn Kastend054c322013-07-12 12:59:20 -0700555 // s for server's pid, n for normal mixer name, f for fast index
556 name = String8::format("s:%d;n:%d;f:%d", getpid_cached, track->name() - AudioMixer::TRACK0,
557 track->fastIndex());
Mathias Agopian65ab4712010-07-14 17:59:35 -0700558 trackHandle = new TrackHandle(track);
559 } else {
560 // remove local strong reference to Client before deleting the Track so that the Client
561 // destructor is called by the TrackBase destructor with mLock held
562 client.clear();
563 track.clear();
564 }
565
566Exit:
Glenn Kastene53b9ea2012-03-12 16:29:55 -0700567 if (status != NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700568 *status = lStatus;
569 }
570 return trackHandle;
571}
572
Alok Kediya601e9b52013-09-27 11:55:10 +0530573sp<IDirectTrack> AudioFlinger::createDirectTrack(
574 pid_t pid,
575 uint32_t sampleRate,
576 audio_channel_mask_t channelMask,
577 audio_io_handle_t output,
578 int *sessionId,
579 IDirectTrackClient *client,
580 audio_stream_type_t streamType,
581 status_t *status)
582{
583 *status = NO_ERROR;
584 status_t lStatus = NO_ERROR;
585 sp<IDirectTrack> track = NULL;
586 DirectAudioTrack* directTrack = NULL;
587 Mutex::Autolock _l(mLock);
588
589 ALOGV("createDirectTrack() sessionId: %d sampleRate %d channelMask %d",
590 *sessionId, sampleRate, channelMask);
591 AudioSessionDescriptor *desc = mDirectAudioTracks.valueFor(output);
592 if(desc == NULL) {
593 ALOGE("Error: Invalid output (%d) to create direct audio track", output);
594 lStatus = BAD_VALUE;
595 goto Exit;
596 }
597 desc->mStreamType = streamType;
598 if (desc->flag & AUDIO_OUTPUT_FLAG_LPA) {
599 if (sessionId != NULL && *sessionId != AUDIO_SESSION_OUTPUT_MIX) {
600 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
601 sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
602 // Check if the session ID is already associated with a track
603 uint32_t sessions = t->hasAudioSession(*sessionId);
604
605 // check if an effect with same session ID is waiting for a ssession to be created
606 ALOGV("check if an effect with same session ID is waiting for a ssession to be created");
607 if ((mLPAEffectChain == NULL) && (sessions & PlaybackThread::EFFECT_SESSION)) {
608 // Clear reference to previous effect chain if any
609 t->mLock.lock();
610 ALOGV("getting the LPA effect chain and setting LPA flag to true.");
611 mLPAEffectChain = t->getEffectChain_l(*sessionId);
612 t->mLock.unlock();
613 }
614 }
615 mLPASessionId = *sessionId;
616 if (mLPAEffectChain != NULL) {
617 mLPAEffectChain->setLPAFlag(true);
618 // For LPA, the volume will be applied in DSP. No need for volume
619 // control in the Effect chain, so setting it to unity.
620 uint32_t volume = 0x1000000; // Equals to 1.0 in 8.24 format
621 mLPAEffectChain->setVolume_l(&volume,&volume);
622 } else {
623 ALOGW("There was no effectChain created for the sessionId(%d)", mLPASessionId);
624 }
625 mLPASampleRate = sampleRate;
626 mLPANumChannels = popcount(channelMask);
627 } else {
628 if(sessionId != NULL) {
629 ALOGE("Error: Invalid sessionID (%d) for direct audio track", *sessionId);
630 }
631 }
632 }
633 mLock.unlock();
634 directTrack = new DirectAudioTrack(this, output, desc, client, desc->flag);
635 desc->trackRefPtr = dynamic_cast<void *>(directTrack);
636 mLock.lock();
637 if (directTrack != 0) {
638 track = dynamic_cast<IDirectTrack *>(directTrack);
639 AudioEventObserver* obv = dynamic_cast<AudioEventObserver *>(directTrack);
640 ALOGE("setting observer mOutputDesc track %p, obv %p", track.get(), obv);
641 desc->stream->set_observer(desc->stream, reinterpret_cast<void *>(obv));
642 } else {
643 lStatus = BAD_VALUE;
644 }
645Exit:
646 if(lStatus) {
647 if (track != NULL) {
648 track.clear();
649 }
650 *status = lStatus;
651 }
652 return track;
653}
654
655void AudioFlinger::deleteEffectSession()
656{
657 ALOGV("deleteSession");
658 // -2 is invalid session ID
659 mLPASessionId = -2;
660 if (mLPAEffectChain != NULL) {
661 mLPAEffectChain->lock();
662 mLPAEffectChain->setLPAFlag(false);
663 size_t i, numEffects = mLPAEffectChain->getNumEffects();
664 for(i = 0; i < numEffects; i++) {
665 sp<EffectModule> effect = mLPAEffectChain->getEffectFromIndex_l(i);
666 effect->setInBuffer(mLPAEffectChain->inBuffer());
667 if (i == numEffects-1) {
668 effect->setOutBuffer(mLPAEffectChain->outBuffer());
669 } else {
670 effect->setOutBuffer(mLPAEffectChain->inBuffer());
671 }
672 effect->configure();
673 }
674 mLPAEffectChain->unlock();
675 mLPAEffectChain.clear();
676 mLPAEffectChain = NULL;
677 }
678}
679
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800680uint32_t AudioFlinger::sampleRate(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700681{
682 Mutex::Autolock _l(mLock);
Alok Kediya601e9b52013-09-27 11:55:10 +0530683 if (!mDirectAudioTracks.isEmpty()) {
684 AudioSessionDescriptor *desc = mDirectAudioTracks.valueFor(output);
685 if(desc != NULL) {
686 return desc->stream->common.get_sample_rate(&desc->stream->common);
687 }
688 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700689 PlaybackThread *thread = checkPlaybackThread_l(output);
690 if (thread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000691 ALOGW("sampleRate() unknown thread %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700692 return 0;
693 }
694 return thread->sampleRate();
695}
696
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800697int AudioFlinger::channelCount(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700698{
699 Mutex::Autolock _l(mLock);
Alok Kediya601e9b52013-09-27 11:55:10 +0530700 AudioSessionDescriptor *desc = mDirectAudioTracks.valueFor(output);
701 if(desc != NULL) {
702 return desc->stream->common.get_channels(&desc->stream->common);
703 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700704 PlaybackThread *thread = checkPlaybackThread_l(output);
705 if (thread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000706 ALOGW("channelCount() unknown thread %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700707 return 0;
708 }
709 return thread->channelCount();
710}
711
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800712audio_format_t AudioFlinger::format(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700713{
714 Mutex::Autolock _l(mLock);
715 PlaybackThread *thread = checkPlaybackThread_l(output);
716 if (thread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000717 ALOGW("format() unknown thread %d", output);
Glenn Kasten58f30212012-01-12 12:27:51 -0800718 return AUDIO_FORMAT_INVALID;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700719 }
720 return thread->format();
721}
722
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800723size_t AudioFlinger::frameCount(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700724{
725 Mutex::Autolock _l(mLock);
Alok Kediya601e9b52013-09-27 11:55:10 +0530726 AudioSessionDescriptor *desc = mDirectAudioTracks.valueFor(output);
727 if(desc != NULL) {
728 return desc->stream->common.get_buffer_size(&desc->stream->common);
729 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700730 PlaybackThread *thread = checkPlaybackThread_l(output);
731 if (thread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000732 ALOGW("frameCount() unknown thread %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700733 return 0;
734 }
Glenn Kasten58912562012-04-03 10:45:00 -0700735 // FIXME currently returns the normal mixer's frame count to avoid confusing legacy callers;
736 // should examine all callers and fix them to handle smaller counts
Mathias Agopian65ab4712010-07-14 17:59:35 -0700737 return thread->frameCount();
738}
739
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800740uint32_t AudioFlinger::latency(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700741{
742 Mutex::Autolock _l(mLock);
Alok Kediya601e9b52013-09-27 11:55:10 +0530743 if (!mDirectAudioTracks.isEmpty()) {
744 AudioSessionDescriptor *desc = mDirectAudioTracks.valueFor(output);
745 if (desc != NULL) {
746 return desc->stream->get_latency(desc->stream);
747 }
748 }
749
Mathias Agopian65ab4712010-07-14 17:59:35 -0700750 PlaybackThread *thread = checkPlaybackThread_l(output);
751 if (thread == NULL) {
Glenn Kastenc9b2e202013-02-26 11:32:32 -0800752 ALOGW("latency(): no playback thread found for output handle %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700753 return 0;
754 }
755 return thread->latency();
756}
757
758status_t AudioFlinger::setMasterVolume(float value)
759{
Eric Laurenta1884f92011-08-23 08:25:03 -0700760 status_t ret = initCheck();
761 if (ret != NO_ERROR) {
762 return ret;
763 }
764
Mathias Agopian65ab4712010-07-14 17:59:35 -0700765 // check calling permissions
766 if (!settingsAllowed()) {
767 return PERMISSION_DENIED;
768 }
769
Eric Laurenta4c5a552012-03-29 10:12:40 -0700770 Mutex::Autolock _l(mLock);
John Grossmanee578c02012-07-23 17:05:46 -0700771 mMasterVolume = value;
Eric Laurenta4c5a552012-03-29 10:12:40 -0700772
John Grossmanee578c02012-07-23 17:05:46 -0700773 // Set master volume in the HALs which support it.
774 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
775 AutoMutex lock(mHardwareLock);
776 AudioHwDevice *dev = mAudioHwDevs.valueAt(i);
John Grossman4ff14ba2012-02-08 16:37:41 -0800777
John Grossmanee578c02012-07-23 17:05:46 -0700778 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
779 if (dev->canSetMasterVolume()) {
780 dev->hwDevice()->set_master_volume(dev->hwDevice(), value);
Eric Laurent93575202011-01-18 18:39:02 -0800781 }
John Grossmanee578c02012-07-23 17:05:46 -0700782 mHardwareStatus = AUDIO_HW_IDLE;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700783 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700784
John Grossmanee578c02012-07-23 17:05:46 -0700785 // Now set the master volume in each playback thread. Playback threads
786 // assigned to HALs which do not have master volume support will apply
787 // master volume during the mix operation. Threads with HALs which do
788 // support master volume will simply ignore the setting.
Glenn Kasten8d6a2442012-02-08 14:04:28 -0800789 for (size_t i = 0; i < mPlaybackThreads.size(); i++)
John Grossmanee578c02012-07-23 17:05:46 -0700790 mPlaybackThreads.valueAt(i)->setMasterVolume(value);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700791
792 return NO_ERROR;
793}
794
Glenn Kastenf78aee72012-01-04 11:00:47 -0800795status_t AudioFlinger::setMode(audio_mode_t mode)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700796{
Eric Laurenta1884f92011-08-23 08:25:03 -0700797 status_t ret = initCheck();
798 if (ret != NO_ERROR) {
799 return ret;
800 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700801
802 // check calling permissions
803 if (!settingsAllowed()) {
804 return PERMISSION_DENIED;
805 }
Glenn Kasten930f4ca2012-01-06 16:47:31 -0800806 if (uint32_t(mode) >= AUDIO_MODE_CNT) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000807 ALOGW("Illegal value: setMode(%d)", mode);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700808 return BAD_VALUE;
809 }
810
811 { // scope for the lock
812 AutoMutex lock(mHardwareLock);
John Grossmanee578c02012-07-23 17:05:46 -0700813 audio_hw_device_t *dev = mPrimaryHardwareDev->hwDevice();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700814 mHardwareStatus = AUDIO_HW_SET_MODE;
John Grossmanee578c02012-07-23 17:05:46 -0700815 ret = dev->set_mode(dev, mode);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700816 mHardwareStatus = AUDIO_HW_IDLE;
817 }
818
819 if (NO_ERROR == ret) {
820 Mutex::Autolock _l(mLock);
821 mMode = mode;
Glenn Kasten8d6a2442012-02-08 14:04:28 -0800822 for (size_t i = 0; i < mPlaybackThreads.size(); i++)
Glenn Kastene53b9ea2012-03-12 16:29:55 -0700823 mPlaybackThreads.valueAt(i)->setMode(mode);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700824 }
825
826 return ret;
827}
828
829status_t AudioFlinger::setMicMute(bool state)
830{
Eric Laurenta1884f92011-08-23 08:25:03 -0700831 status_t ret = initCheck();
832 if (ret != NO_ERROR) {
833 return ret;
834 }
835
Mathias Agopian65ab4712010-07-14 17:59:35 -0700836 // check calling permissions
837 if (!settingsAllowed()) {
838 return PERMISSION_DENIED;
839 }
840
841 AutoMutex lock(mHardwareLock);
John Grossmanee578c02012-07-23 17:05:46 -0700842 audio_hw_device_t *dev = mPrimaryHardwareDev->hwDevice();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700843 mHardwareStatus = AUDIO_HW_SET_MIC_MUTE;
John Grossmanee578c02012-07-23 17:05:46 -0700844 ret = dev->set_mic_mute(dev, state);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700845 mHardwareStatus = AUDIO_HW_IDLE;
846 return ret;
847}
848
849bool AudioFlinger::getMicMute() const
850{
Eric Laurenta1884f92011-08-23 08:25:03 -0700851 status_t ret = initCheck();
852 if (ret != NO_ERROR) {
853 return false;
854 }
855
Dima Zavinfce7a472011-04-19 22:30:36 -0700856 bool state = AUDIO_MODE_INVALID;
Glenn Kasten2b213bc2012-02-02 14:05:20 -0800857 AutoMutex lock(mHardwareLock);
John Grossmanee578c02012-07-23 17:05:46 -0700858 audio_hw_device_t *dev = mPrimaryHardwareDev->hwDevice();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700859 mHardwareStatus = AUDIO_HW_GET_MIC_MUTE;
John Grossmanee578c02012-07-23 17:05:46 -0700860 dev->get_mic_mute(dev, &state);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700861 mHardwareStatus = AUDIO_HW_IDLE;
862 return state;
863}
864
865status_t AudioFlinger::setMasterMute(bool muted)
866{
John Grossmand8f178d2012-07-20 14:51:35 -0700867 status_t ret = initCheck();
868 if (ret != NO_ERROR) {
869 return ret;
870 }
871
Mathias Agopian65ab4712010-07-14 17:59:35 -0700872 // check calling permissions
873 if (!settingsAllowed()) {
874 return PERMISSION_DENIED;
875 }
876
John Grossmanee578c02012-07-23 17:05:46 -0700877 Mutex::Autolock _l(mLock);
878 mMasterMute = muted;
John Grossmand8f178d2012-07-20 14:51:35 -0700879
Emerson Pinter6d327d52013-07-28 19:34:16 -0300880#ifndef ICS_AUDIO_BLOB
John Grossmanee578c02012-07-23 17:05:46 -0700881 // Set master mute in the HALs which support it.
882 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
883 AutoMutex lock(mHardwareLock);
884 AudioHwDevice *dev = mAudioHwDevs.valueAt(i);
John Grossmand8f178d2012-07-20 14:51:35 -0700885
John Grossmanee578c02012-07-23 17:05:46 -0700886 mHardwareStatus = AUDIO_HW_SET_MASTER_MUTE;
887 if (dev->canSetMasterMute()) {
888 dev->hwDevice()->set_master_mute(dev->hwDevice(), muted);
John Grossmand8f178d2012-07-20 14:51:35 -0700889 }
John Grossmanee578c02012-07-23 17:05:46 -0700890 mHardwareStatus = AUDIO_HW_IDLE;
John Grossmand8f178d2012-07-20 14:51:35 -0700891 }
892
John Grossmanee578c02012-07-23 17:05:46 -0700893 // Now set the master mute in each playback thread. Playback threads
894 // assigned to HALs which do not have master mute support will apply master
895 // mute during the mix operation. Threads with HALs which do support master
896 // mute will simply ignore the setting.
Glenn Kasten8d6a2442012-02-08 14:04:28 -0800897 for (size_t i = 0; i < mPlaybackThreads.size(); i++)
John Grossmanee578c02012-07-23 17:05:46 -0700898 mPlaybackThreads.valueAt(i)->setMasterMute(muted);
Ricardo Cerqueira0d44b5b2013-11-03 02:46:27 +0000899#endif
Mathias Agopian65ab4712010-07-14 17:59:35 -0700900
901 return NO_ERROR;
902}
903
904float AudioFlinger::masterVolume() const
905{
Glenn Kasten98067102011-12-13 11:47:54 -0800906 Mutex::Autolock _l(mLock);
907 return masterVolume_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700908}
909
910bool AudioFlinger::masterMute() const
911{
Glenn Kasten98067102011-12-13 11:47:54 -0800912 Mutex::Autolock _l(mLock);
913 return masterMute_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700914}
915
John Grossman4ff14ba2012-02-08 16:37:41 -0800916float AudioFlinger::masterVolume_l() const
917{
John Grossman4ff14ba2012-02-08 16:37:41 -0800918 return mMasterVolume;
919}
920
John Grossmand8f178d2012-07-20 14:51:35 -0700921bool AudioFlinger::masterMute_l() const
922{
John Grossmanee578c02012-07-23 17:05:46 -0700923 return mMasterMute;
John Grossmand8f178d2012-07-20 14:51:35 -0700924}
925
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800926status_t AudioFlinger::setStreamVolume(audio_stream_type_t stream, float value,
927 audio_io_handle_t output)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700928{
929 // check calling permissions
930 if (!settingsAllowed()) {
931 return PERMISSION_DENIED;
932 }
933
Glenn Kasten263709e2012-01-06 08:40:01 -0800934 if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
Steve Block29357bc2012-01-06 19:20:56 +0000935 ALOGE("setStreamVolume() invalid stream %d", stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700936 return BAD_VALUE;
937 }
938
939 AutoMutex lock(mLock);
Alok Kediya601e9b52013-09-27 11:55:10 +0530940 ALOGV("setStreamVolume stream %d, output %d, value %f",stream, output, value);
941 AudioSessionDescriptor *desc = NULL;
942 if (!mDirectAudioTracks.isEmpty()) {
943 desc = mDirectAudioTracks.valueFor(output);
944 if (desc != NULL) {
945 ALOGV("setStreamVolume for mAudioTracks size %d desc %p",mDirectAudioTracks.size(),desc);
946 if (desc->mStreamType == stream) {
947 mStreamTypes[stream].volume = value;
948 desc->mVolumeScale = value;
949 desc->stream->set_volume(desc->stream,
950 desc->mVolumeLeft * mStreamTypes[stream].volume,
951 desc->mVolumeRight* mStreamTypes[stream].volume);
952 return NO_ERROR;
953 }
954 }
955 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700956 PlaybackThread *thread = NULL;
957 if (output) {
958 thread = checkPlaybackThread_l(output);
959 if (thread == NULL) {
Alok Kediya601e9b52013-09-27 11:55:10 +0530960 if (desc != NULL) {
961 return NO_ERROR;
962 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700963 return BAD_VALUE;
964 }
965 }
966
967 mStreamTypes[stream].volume = value;
968
969 if (thread == NULL) {
Glenn Kasten8d6a2442012-02-08 14:04:28 -0800970 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Glenn Kastene53b9ea2012-03-12 16:29:55 -0700971 mPlaybackThreads.valueAt(i)->setStreamVolume(stream, value);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700972 }
973 } else {
974 thread->setStreamVolume(stream, value);
975 }
976
977 return NO_ERROR;
978}
979
Glenn Kastenfff6d712012-01-12 16:38:12 -0800980status_t AudioFlinger::setStreamMute(audio_stream_type_t stream, bool muted)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700981{
982 // check calling permissions
983 if (!settingsAllowed()) {
984 return PERMISSION_DENIED;
985 }
986
Glenn Kasten263709e2012-01-06 08:40:01 -0800987 if (uint32_t(stream) >= AUDIO_STREAM_CNT ||
Dima Zavinfce7a472011-04-19 22:30:36 -0700988 uint32_t(stream) == AUDIO_STREAM_ENFORCED_AUDIBLE) {
Steve Block29357bc2012-01-06 19:20:56 +0000989 ALOGE("setStreamMute() invalid stream %d", stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700990 return BAD_VALUE;
991 }
992
Eric Laurent93575202011-01-18 18:39:02 -0800993 AutoMutex lock(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700994 mStreamTypes[stream].mute = muted;
995 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
Glenn Kastene53b9ea2012-03-12 16:29:55 -0700996 mPlaybackThreads.valueAt(i)->setStreamMute(stream, muted);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700997
998 return NO_ERROR;
999}
1000
Glenn Kasten72ef00d2012-01-17 11:09:42 -08001001float AudioFlinger::streamVolume(audio_stream_type_t stream, audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07001002{
Glenn Kasten263709e2012-01-06 08:40:01 -08001003 if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001004 return 0.0f;
1005 }
1006
1007 AutoMutex lock(mLock);
1008 float volume;
1009 if (output) {
1010 PlaybackThread *thread = checkPlaybackThread_l(output);
1011 if (thread == NULL) {
1012 return 0.0f;
1013 }
1014 volume = thread->streamVolume(stream);
1015 } else {
Glenn Kasten6637baa2012-01-09 09:40:36 -08001016 volume = streamVolume_l(stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001017 }
1018
1019 return volume;
1020}
1021
Glenn Kastenfff6d712012-01-12 16:38:12 -08001022bool AudioFlinger::streamMute(audio_stream_type_t stream) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07001023{
Glenn Kasten263709e2012-01-06 08:40:01 -08001024 if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001025 return true;
1026 }
1027
Glenn Kasten6637baa2012-01-09 09:40:36 -08001028 AutoMutex lock(mLock);
1029 return streamMute_l(stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001030}
1031
Glenn Kasten72ef00d2012-01-17 11:09:42 -08001032status_t AudioFlinger::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001033{
Glenn Kasten827e5f12012-11-02 10:00:06 -07001034 ALOGV("setParameters(): io %d, keyvalue %s, calling pid %d",
1035 ioHandle, keyValuePairs.string(), IPCThreadState::self()->getCallingPid());
Eric Laurent81784c32012-11-19 14:55:58 -08001036
Mathias Agopian65ab4712010-07-14 17:59:35 -07001037 // check calling permissions
1038 if (!settingsAllowed()) {
1039 return PERMISSION_DENIED;
1040 }
1041
Mathias Agopian65ab4712010-07-14 17:59:35 -07001042 // ioHandle == 0 means the parameters are global to the audio hardware interface
1043 if (ioHandle == 0) {
Eric Laurenta4c5a552012-03-29 10:12:40 -07001044 Mutex::Autolock _l(mLock);
Alok Kediya601e9b52013-09-27 11:55:10 +05301045#ifdef SRS_PROCESSING
1046 POSTPRO_PATCH_ICS_PARAMS_SET(keyValuePairs);
1047 if (!mDirectAudioTracks.isEmpty())
1048 audioConfigChanged_l(AudioSystem::EFFECT_CONFIG_CHANGED, 0, NULL);
1049#endif
Dima Zavin799a70e2011-04-18 16:57:27 -07001050 status_t final_result = NO_ERROR;
Glenn Kasten8abf44d2012-02-02 14:16:03 -08001051 {
Eric Laurenta4c5a552012-03-29 10:12:40 -07001052 AutoMutex lock(mHardwareLock);
1053 mHardwareStatus = AUDIO_HW_SET_PARAMETER;
1054 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
1055 audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();
1056 status_t result = dev->set_parameters(dev, keyValuePairs.string());
1057 final_result = result ?: final_result;
1058 }
1059 mHardwareStatus = AUDIO_HW_IDLE;
Glenn Kasten8abf44d2012-02-02 14:16:03 -08001060 }
Eric Laurent59bd0da2011-08-01 09:52:20 -07001061 // disable AEC and NS if the device is a BT SCO headset supporting those pre processings
1062 AudioParameter param = AudioParameter(keyValuePairs);
1063 String8 value;
1064 if (param.get(String8(AUDIO_PARAMETER_KEY_BT_NREC), value) == NO_ERROR) {
Eric Laurentbee53372011-08-29 12:42:48 -07001065 bool btNrecIsOff = (value == AUDIO_PARAMETER_VALUE_OFF);
1066 if (mBtNrecIsOff != btNrecIsOff) {
Eric Laurent59bd0da2011-08-01 09:52:20 -07001067 for (size_t i = 0; i < mRecordThreads.size(); i++) {
1068 sp<RecordThread> thread = mRecordThreads.valueAt(i);
Eric Laurentf1c04f92012-08-28 14:26:53 -07001069 audio_devices_t device = thread->inDevice();
Glenn Kasten510a3d62012-07-16 14:24:34 -07001070 bool suspend = audio_is_bluetooth_sco_device(device) && btNrecIsOff;
1071 // collect all of the thread's session IDs
1072 KeyedVector<int, bool> ids = thread->sessionIds();
1073 // suspend effects associated with those session IDs
1074 for (size_t j = 0; j < ids.size(); ++j) {
1075 int sessionId = ids.keyAt(j);
Eric Laurent59bd0da2011-08-01 09:52:20 -07001076 thread->setEffectSuspended(FX_IID_AEC,
1077 suspend,
Glenn Kasten510a3d62012-07-16 14:24:34 -07001078 sessionId);
Eric Laurent59bd0da2011-08-01 09:52:20 -07001079 thread->setEffectSuspended(FX_IID_NS,
1080 suspend,
Glenn Kasten510a3d62012-07-16 14:24:34 -07001081 sessionId);
Eric Laurent59bd0da2011-08-01 09:52:20 -07001082 }
1083 }
Eric Laurentbee53372011-08-29 12:42:48 -07001084 mBtNrecIsOff = btNrecIsOff;
Eric Laurent59bd0da2011-08-01 09:52:20 -07001085 }
1086 }
Glenn Kasten28ed2f92012-06-07 10:17:54 -07001087 String8 screenState;
1088 if (param.get(String8(AudioParameter::keyScreenState), screenState) == NO_ERROR) {
1089 bool isOff = screenState == "off";
Eric Laurent81784c32012-11-19 14:55:58 -08001090 if (isOff != (AudioFlinger::mScreenState & 1)) {
1091 AudioFlinger::mScreenState = ((AudioFlinger::mScreenState & ~1) + 2) | isOff;
Glenn Kasten28ed2f92012-06-07 10:17:54 -07001092 }
1093 }
Dima Zavin799a70e2011-04-18 16:57:27 -07001094 return final_result;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001095 }
1096
Alok Kediya601e9b52013-09-27 11:55:10 +05301097 AudioSessionDescriptor *desc = NULL;
1098 if (!mDirectAudioTracks.isEmpty()) {
1099 desc = mDirectAudioTracks.valueFor(ioHandle);
1100 if (desc != NULL) {
1101 ALOGV("setParameters for mAudioTracks size %d desc %p",mDirectAudioTracks.size(),desc);
1102 desc->stream->common.set_parameters(&desc->stream->common, keyValuePairs.string());
1103 AudioParameter param = AudioParameter(keyValuePairs);
1104 String8 key = String8(AudioParameter::keyRouting);
1105 int device;
1106 if (param.getInt(key, device) == NO_ERROR) {
1107 mDirectDevice = device;
1108#ifdef SRS_PROCESSING
1109 ALOGV("setParameters:: routing change to device %d", device);
1110 POSTPRO_PATCH_ICS_OUTPROC_MIX_ROUTE(desc->trackRefPtr, param, device);
1111#endif
1112 if(mLPAEffectChain != NULL){
1113 mLPAEffectChain->setDevice_l(device);
1114 audioConfigChanged_l(AudioSystem::EFFECT_CONFIG_CHANGED, 0, NULL);
1115 }
1116 }
1117 }
1118 }
1119
Mathias Agopian65ab4712010-07-14 17:59:35 -07001120 // hold a strong ref on thread in case closeOutput() or closeInput() is called
1121 // and the thread is exited once the lock is released
1122 sp<ThreadBase> thread;
1123 {
1124 Mutex::Autolock _l(mLock);
1125 thread = checkPlaybackThread_l(ioHandle);
Glenn Kastend5903ec2012-03-18 10:33:27 -07001126 if (thread == 0) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001127 thread = checkRecordThread_l(ioHandle);
Glenn Kasten7fc9a6f2012-01-10 10:46:34 -08001128 } else if (thread == primaryPlaybackThread_l()) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07001129 // indicate output device change to all input threads for pre processing
1130 AudioParameter param = AudioParameter(keyValuePairs);
1131 int value;
Eric Laurent89d94e72012-03-16 20:37:59 -07001132 if ((param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) &&
1133 (value != 0)) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07001134 for (size_t i = 0; i < mRecordThreads.size(); i++) {
1135 mRecordThreads.valueAt(i)->setParameters(keyValuePairs);
1136 }
1137 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001138 }
1139 }
Glenn Kasten7378ca52012-01-20 13:44:40 -08001140 if (thread != 0) {
1141 return thread->setParameters(keyValuePairs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001142 }
1143 return BAD_VALUE;
1144}
1145
Glenn Kasten72ef00d2012-01-17 11:09:42 -08001146String8 AudioFlinger::getParameters(audio_io_handle_t ioHandle, const String8& keys) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07001147{
Glenn Kasten827e5f12012-11-02 10:00:06 -07001148 ALOGVV("getParameters() io %d, keys %s, calling pid %d",
1149 ioHandle, keys.string(), IPCThreadState::self()->getCallingPid());
Mathias Agopian65ab4712010-07-14 17:59:35 -07001150
Eric Laurenta4c5a552012-03-29 10:12:40 -07001151 Mutex::Autolock _l(mLock);
1152
Mathias Agopian65ab4712010-07-14 17:59:35 -07001153 if (ioHandle == 0) {
Dima Zavinfce7a472011-04-19 22:30:36 -07001154 String8 out_s8;
1155
Alok Kediya601e9b52013-09-27 11:55:10 +05301156#ifdef SRS_PROCESSING
1157 POSTPRO_PATCH_ICS_PARAMS_GET(keys, out_s8);
1158#endif
Dima Zavin799a70e2011-04-18 16:57:27 -07001159 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
Glenn Kasten8abf44d2012-02-02 14:16:03 -08001160 char *s;
1161 {
1162 AutoMutex lock(mHardwareLock);
1163 mHardwareStatus = AUDIO_HW_GET_PARAMETER;
Eric Laurenta4c5a552012-03-29 10:12:40 -07001164 audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();
Glenn Kasten8abf44d2012-02-02 14:16:03 -08001165 s = dev->get_parameters(dev, keys.string());
1166 mHardwareStatus = AUDIO_HW_IDLE;
1167 }
John Grossmanef7740b2012-02-09 11:28:36 -08001168 out_s8 += String8(s ? s : "");
Dima Zavin799a70e2011-04-18 16:57:27 -07001169 free(s);
1170 }
Dima Zavinfce7a472011-04-19 22:30:36 -07001171 return out_s8;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001172 }
1173
Mathias Agopian65ab4712010-07-14 17:59:35 -07001174 PlaybackThread *playbackThread = checkPlaybackThread_l(ioHandle);
1175 if (playbackThread != NULL) {
1176 return playbackThread->getParameters(keys);
1177 }
1178 RecordThread *recordThread = checkRecordThread_l(ioHandle);
1179 if (recordThread != NULL) {
1180 return recordThread->getParameters(keys);
1181 }
1182 return String8("");
1183}
1184
Glenn Kastendd8104c2012-07-02 12:42:44 -07001185size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, audio_format_t format,
1186 audio_channel_mask_t channelMask) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07001187{
Eric Laurenta1884f92011-08-23 08:25:03 -07001188 status_t ret = initCheck();
1189 if (ret != NO_ERROR) {
1190 return 0;
1191 }
1192
Glenn Kasten2b213bc2012-02-02 14:05:20 -08001193 AutoMutex lock(mHardwareLock);
1194 mHardwareStatus = AUDIO_HW_GET_INPUT_BUFFER_SIZE;
Richard Fitzgeraldad3af332013-03-25 16:54:37 +00001195 struct audio_config config;
1196 memset(&config, 0, sizeof(config));
1197 config.sample_rate = sampleRate;
1198 config.channel_mask = channelMask;
1199 config.format = format;
1200
John Grossmanee578c02012-07-23 17:05:46 -07001201 audio_hw_device_t *dev = mPrimaryHardwareDev->hwDevice();
Ricardo Cerqueira0d44b5b2013-11-03 02:46:27 +00001202#ifndef ICS_AUDIO_BLOB
John Grossmanee578c02012-07-23 17:05:46 -07001203 size_t size = dev->get_input_buffer_size(dev, &config);
Ricardo Cerqueira0d44b5b2013-11-03 02:46:27 +00001204#else
1205 size_t size = dev->get_input_buffer_size(dev, sampleRate, format, popcount(channelMask));
1206#endif
Glenn Kasten2b213bc2012-02-02 14:05:20 -08001207 mHardwareStatus = AUDIO_HW_IDLE;
1208 return size;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001209}
1210
Glenn Kasten72ef00d2012-01-17 11:09:42 -08001211unsigned int AudioFlinger::getInputFramesLost(audio_io_handle_t ioHandle) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07001212{
Mathias Agopian65ab4712010-07-14 17:59:35 -07001213 Mutex::Autolock _l(mLock);
1214
1215 RecordThread *recordThread = checkRecordThread_l(ioHandle);
1216 if (recordThread != NULL) {
1217 return recordThread->getInputFramesLost();
1218 }
1219 return 0;
1220}
1221
1222status_t AudioFlinger::setVoiceVolume(float value)
1223{
Eric Laurenta1884f92011-08-23 08:25:03 -07001224 status_t ret = initCheck();
1225 if (ret != NO_ERROR) {
1226 return ret;
1227 }
1228
Mathias Agopian65ab4712010-07-14 17:59:35 -07001229 // check calling permissions
1230 if (!settingsAllowed()) {
1231 return PERMISSION_DENIED;
1232 }
1233
1234 AutoMutex lock(mHardwareLock);
John Grossmanee578c02012-07-23 17:05:46 -07001235 audio_hw_device_t *dev = mPrimaryHardwareDev->hwDevice();
Glenn Kasten8abf44d2012-02-02 14:16:03 -08001236 mHardwareStatus = AUDIO_HW_SET_VOICE_VOLUME;
John Grossmanee578c02012-07-23 17:05:46 -07001237 ret = dev->set_voice_volume(dev, value);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001238 mHardwareStatus = AUDIO_HW_IDLE;
1239
1240 return ret;
1241}
1242
Glenn Kasten26c77552012-11-16 12:01:44 -08001243status_t AudioFlinger::getRenderPosition(size_t *halFrames, size_t *dspFrames,
Glenn Kasten72ef00d2012-01-17 11:09:42 -08001244 audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07001245{
1246 status_t status;
1247
1248 Mutex::Autolock _l(mLock);
1249
1250 PlaybackThread *playbackThread = checkPlaybackThread_l(output);
1251 if (playbackThread != NULL) {
1252 return playbackThread->getRenderPosition(halFrames, dspFrames);
1253 }
1254
1255 return BAD_VALUE;
1256}
1257
1258void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
1259{
1260
1261 Mutex::Autolock _l(mLock);
1262
Glenn Kastenbb001922012-02-03 11:10:26 -08001263 pid_t pid = IPCThreadState::self()->getCallingPid();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001264 if (mNotificationClients.indexOfKey(pid) < 0) {
1265 sp<NotificationClient> notificationClient = new NotificationClient(this,
1266 client,
1267 pid);
Steve Block3856b092011-10-20 11:56:00 +01001268 ALOGV("registerClient() client %p, pid %d", notificationClient.get(), pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001269
1270 mNotificationClients.add(pid, notificationClient);
1271
1272 sp<IBinder> binder = client->asBinder();
1273 binder->linkToDeath(notificationClient);
1274
1275 // the config change is always sent from playback or record threads to avoid deadlock
1276 // with AudioSystem::gLock
1277 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurent896adcd2012-09-13 11:18:23 -07001278 mPlaybackThreads.valueAt(i)->sendIoConfigEvent(AudioSystem::OUTPUT_OPENED);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001279 }
1280
1281 for (size_t i = 0; i < mRecordThreads.size(); i++) {
Eric Laurent896adcd2012-09-13 11:18:23 -07001282 mRecordThreads.valueAt(i)->sendIoConfigEvent(AudioSystem::INPUT_OPENED);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001283 }
1284 }
1285}
1286
Alok Kediya601e9b52013-09-27 11:55:10 +05301287status_t AudioFlinger::deregisterClient(const sp<IAudioFlingerClient>& client)
1288{
1289 ALOGV("deregisterClient() %p, tid %d, calling tid %d", client.get(), gettid(), IPCThreadState::self()->getCallingPid());
1290 Mutex::Autolock _l(mLock);
1291
1292 pid_t pid = IPCThreadState::self()->getCallingPid();
1293 int index = mNotificationClients.indexOfKey(pid);
1294 if (index >= 0) {
1295 mNotificationClients.removeItemsAt(index);
1296 return true;
1297 }
1298
1299 return false;
1300}
1301
Mathias Agopian65ab4712010-07-14 17:59:35 -07001302void AudioFlinger::removeNotificationClient(pid_t pid)
1303{
1304 Mutex::Autolock _l(mLock);
1305
Glenn Kastena3b09252012-01-20 09:19:01 -08001306 mNotificationClients.removeItem(pid);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001307
Steve Block3856b092011-10-20 11:56:00 +01001308 ALOGV("%d died, releasing its sessions", pid);
Glenn Kasten8d6a2442012-02-08 14:04:28 -08001309 size_t num = mAudioSessionRefs.size();
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001310 bool removed = false;
Glenn Kasten8d6a2442012-02-08 14:04:28 -08001311 for (size_t i = 0; i< num; ) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001312 AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
Glenn Kasten012ca6b2012-03-06 11:22:01 -08001313 ALOGV(" pid %d @ %d", ref->mPid, i);
1314 if (ref->mPid == pid) {
1315 ALOGV(" removing entry for pid %d session %d", pid, ref->mSessionid);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001316 mAudioSessionRefs.removeAt(i);
1317 delete ref;
1318 removed = true;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001319 num--;
Glenn Kasten8d6a2442012-02-08 14:04:28 -08001320 } else {
1321 i++;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001322 }
1323 }
1324 if (removed) {
1325 purgeStaleEffects_l();
1326 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001327}
1328
1329// audioConfigChanged_l() must be called with AudioFlinger::mLock held
Glenn Kastenb81cc8c2012-03-01 09:14:51 -08001330void AudioFlinger::audioConfigChanged_l(int event, audio_io_handle_t ioHandle, const void *param2)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001331{
Alok Kediya601e9b52013-09-27 11:55:10 +05301332 ALOGV("AudioFlinger::audioConfigChanged_l: event %d", event);
1333 if (event == AudioSystem::EFFECT_CONFIG_CHANGED) {
1334 mIsEffectConfigChanged = true;
1335 }
1336 if (!mNotificationClients.isEmpty()){
1337 size_t size = mNotificationClients.size();
1338 for (size_t i = 0; i < size; i++) {
1339 mNotificationClients.valueAt(i)->audioFlingerClient()->ioConfigChanged(event, ioHandle,
1340 param2);
1341 }
1342 }
1343 if ((!mDirectAudioTracks.isEmpty())&& (event == AudioSystem::EFFECT_CONFIG_CHANGED)){
1344 size_t dsize = mDirectAudioTracks.size();
1345 for(size_t i = 0; i < dsize; i++) {
1346 AudioSessionDescriptor *desc = mDirectAudioTracks.valueAt(i);
1347 if(desc && ((DirectAudioTrack*)desc->trackRefPtr)) {
1348 ALOGV("signalling directAudioTrack ");
1349 ((DirectAudioTrack*)desc->trackRefPtr)->signalEffect();
1350 } else{
1351 ALOGV("not found track to signal directAudioTrack ");
1352 }
1353 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001354 }
1355}
1356
1357// removeClient_l() must be called with AudioFlinger::mLock held
1358void AudioFlinger::removeClient_l(pid_t pid)
1359{
Glenn Kasten827e5f12012-11-02 10:00:06 -07001360 ALOGV("removeClient_l() pid %d, calling pid %d", pid,
Glenn Kasten85ab62c2012-11-01 11:11:38 -07001361 IPCThreadState::self()->getCallingPid());
Mathias Agopian65ab4712010-07-14 17:59:35 -07001362 mClients.removeItem(pid);
1363}
1364
Eric Laurent717e1282012-06-29 16:36:52 -07001365// getEffectThread_l() must be called with AudioFlinger::mLock held
1366sp<AudioFlinger::PlaybackThread> AudioFlinger::getEffectThread_l(int sessionId, int EffectId)
1367{
1368 sp<PlaybackThread> thread;
1369
1370 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
1371 if (mPlaybackThreads.valueAt(i)->getEffect(sessionId, EffectId) != 0) {
1372 ALOG_ASSERT(thread == 0);
1373 thread = mPlaybackThreads.valueAt(i);
1374 }
1375 }
1376
1377 return thread;
1378}
Mathias Agopian65ab4712010-07-14 17:59:35 -07001379
Mathias Agopian65ab4712010-07-14 17:59:35 -07001380
Mathias Agopian65ab4712010-07-14 17:59:35 -07001381
1382// ----------------------------------------------------------------------------
1383
1384AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
1385 : RefBase(),
1386 mAudioFlinger(audioFlinger),
Glenn Kasten99e53b82012-01-19 08:59:58 -08001387 // FIXME should be a "k" constant not hard-coded, in .h or ro. property, see 4 lines below
Mathias Agopian65ab4712010-07-14 17:59:35 -07001388 mMemoryDealer(new MemoryDealer(1024*1024, "AudioFlinger::Client")),
John Grossman4ff14ba2012-02-08 16:37:41 -08001389 mPid(pid),
1390 mTimedTrackCount(0)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001391{
1392 // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
1393}
1394
1395// Client destructor must be called with AudioFlinger::mLock held
1396AudioFlinger::Client::~Client()
1397{
1398 mAudioFlinger->removeClient_l(mPid);
1399}
1400
Glenn Kasten435dbe62012-01-30 10:15:48 -08001401sp<MemoryDealer> AudioFlinger::Client::heap() const
Mathias Agopian65ab4712010-07-14 17:59:35 -07001402{
1403 return mMemoryDealer;
1404}
1405
John Grossman4ff14ba2012-02-08 16:37:41 -08001406// Reserve one of the limited slots for a timed audio track associated
1407// with this client
1408bool AudioFlinger::Client::reserveTimedTrack()
1409{
1410 const int kMaxTimedTracksPerClient = 4;
1411
1412 Mutex::Autolock _l(mTimedTrackLock);
1413
1414 if (mTimedTrackCount >= kMaxTimedTracksPerClient) {
1415 ALOGW("can not create timed track - pid %d has exceeded the limit",
1416 mPid);
1417 return false;
1418 }
1419
1420 mTimedTrackCount++;
1421 return true;
1422}
1423
1424// Release a slot for a timed audio track
1425void AudioFlinger::Client::releaseTimedTrack()
1426{
1427 Mutex::Autolock _l(mTimedTrackLock);
1428 mTimedTrackCount--;
1429}
1430
Mathias Agopian65ab4712010-07-14 17:59:35 -07001431// ----------------------------------------------------------------------------
1432
1433AudioFlinger::NotificationClient::NotificationClient(const sp<AudioFlinger>& audioFlinger,
1434 const sp<IAudioFlingerClient>& client,
1435 pid_t pid)
Glenn Kasten84afa3b2012-01-25 15:28:08 -08001436 : mAudioFlinger(audioFlinger), mPid(pid), mAudioFlingerClient(client)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001437{
1438}
1439
1440AudioFlinger::NotificationClient::~NotificationClient()
1441{
Mathias Agopian65ab4712010-07-14 17:59:35 -07001442}
1443
1444void AudioFlinger::NotificationClient::binderDied(const wp<IBinder>& who)
1445{
1446 sp<NotificationClient> keep(this);
Glenn Kastena1117922012-01-26 10:53:32 -08001447 mAudioFlinger->removeNotificationClient(mPid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001448}
1449
Mathias Agopian65ab4712010-07-14 17:59:35 -07001450
1451// ----------------------------------------------------------------------------
1452
Jeff Brown893a5642013-08-16 20:19:26 -07001453static bool deviceRequiresCaptureAudioOutputPermission(audio_devices_t inDevice) {
1454 return audio_is_remote_submix_device(inDevice);
1455}
1456
Mathias Agopian65ab4712010-07-14 17:59:35 -07001457sp<IAudioRecord> AudioFlinger::openRecord(
Glenn Kasten72ef00d2012-01-17 11:09:42 -08001458 audio_io_handle_t input,
Mathias Agopian65ab4712010-07-14 17:59:35 -07001459 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08001460 audio_format_t format,
Glenn Kasten254af182012-07-03 14:59:05 -07001461 audio_channel_mask_t channelMask,
Glenn Kastene33054e2012-11-14 12:54:39 -08001462 size_t frameCount,
Glenn Kasteneeca3262013-07-31 16:12:48 -07001463 IAudioFlinger::track_flags_t *flags,
Glenn Kasten1879fff2012-07-11 15:36:59 -07001464 pid_t tid,
Mathias Agopian65ab4712010-07-14 17:59:35 -07001465 int *sessionId,
1466 status_t *status)
1467{
1468 sp<RecordThread::RecordTrack> recordTrack;
1469 sp<RecordHandle> recordHandle;
1470 sp<Client> client;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001471 status_t lStatus;
1472 RecordThread *thread;
1473 size_t inFrameCount;
1474 int lSessionId;
Alok Kediya601e9b52013-09-27 11:55:10 +05301475 size_t inputBufferSize = 0;
1476 uint32_t channelCount = popcount(channelMask);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001477
1478 // check calling permissions
1479 if (!recordingAllowed()) {
Glenn Kastene93cf2c2013-09-24 11:52:37 -07001480 ALOGE("openRecord() permission denied: recording not allowed");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001481 lStatus = PERMISSION_DENIED;
1482 goto Exit;
1483 }
1484
Alok Kediya601e9b52013-09-27 11:55:10 +05301485 // Check that audio input stream accepts requested audio parameters
1486 inputBufferSize = getInputBufferSize(sampleRate, format, channelCount);
1487 if (inputBufferSize == 0) {
Glenn Kasten291bb6d2013-07-16 17:23:39 -07001488 lStatus = BAD_VALUE;
Alok Kediya601e9b52013-09-27 11:55:10 +05301489 ALOGE("Bad audio input parameters: sampling rate %u, format %d, channels %d", sampleRate, format, channelCount);
Glenn Kasten291bb6d2013-07-16 17:23:39 -07001490 goto Exit;
1491 }
1492
Mathias Agopian65ab4712010-07-14 17:59:35 -07001493 // add client to list
1494 { // scope for mLock
1495 Mutex::Autolock _l(mLock);
1496 thread = checkRecordThread_l(input);
1497 if (thread == NULL) {
Glenn Kastene93cf2c2013-09-24 11:52:37 -07001498 ALOGE("openRecord() checkRecordThread_l failed");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001499 lStatus = BAD_VALUE;
1500 goto Exit;
1501 }
1502
Jeff Brown893a5642013-08-16 20:19:26 -07001503 if (deviceRequiresCaptureAudioOutputPermission(thread->inDevice())
1504 && !captureAudioOutputAllowed()) {
Glenn Kastene93cf2c2013-09-24 11:52:37 -07001505 ALOGE("openRecord() permission denied: capture not allowed");
Jeff Brown893a5642013-08-16 20:19:26 -07001506 lStatus = PERMISSION_DENIED;
1507 goto Exit;
1508 }
1509
Glenn Kasten8d6cc842012-02-03 11:06:53 -08001510 pid_t pid = IPCThreadState::self()->getCallingPid();
Glenn Kasten98ec94c2012-01-25 14:28:29 -08001511 client = registerPid_l(pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001512
1513 // If no audio session id is provided, create one here
Dima Zavinfce7a472011-04-19 22:30:36 -07001514 if (sessionId != NULL && *sessionId != AUDIO_SESSION_OUTPUT_MIX) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001515 lSessionId = *sessionId;
1516 } else {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07001517 lSessionId = nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001518 if (sessionId != NULL) {
1519 *sessionId = lSessionId;
1520 }
1521 }
Alok Kediya601e9b52013-09-27 11:55:10 +05301522
1523 // frameCount must be a multiple of input buffer size
1524 // Change for Codec type
1525 uint8_t channelCount = popcount(channelMask);
1526 if (*flags & IAudioFlinger::TRACK_VOICE_COMMUNICATION) {
1527 inFrameCount = inputBufferSize/channelCount/sizeof(short);
1528 } else {
1529 if ((format == AUDIO_FORMAT_PCM_16_BIT) ||
1530 (format == AUDIO_FORMAT_PCM_8_BIT)) {
1531 inFrameCount = inputBufferSize/channelCount/sizeof(short);
1532 } else if (format == AUDIO_FORMAT_AMR_NB) {
1533 inFrameCount = inputBufferSize/channelCount/AMR_FRAMESIZE;
1534 } else if (format == AUDIO_FORMAT_EVRC) {
1535 inFrameCount = inputBufferSize/channelCount/EVRC_FRAMESIZE;
1536 } else if (format == AUDIO_FORMAT_QCELP) {
1537 inFrameCount = inputBufferSize/channelCount/QCELP_FRAMESIZE;
1538 } else if (format == AUDIO_FORMAT_AAC) {
1539 inFrameCount = inputBufferSize/AAC_FRAMESIZE;
1540 } else if (format == AUDIO_FORMAT_AMR_WB) {
1541 inFrameCount = inputBufferSize/channelCount/AMR_WB_FRAMESIZE;
1542 }
1543 }
1544 frameCount = ((frameCount - 1)/inFrameCount + 1) * inFrameCount;
1545
Glenn Kasten85ab62c2012-11-01 11:11:38 -07001546 // create new record track.
1547 // The record track uses one track in mHardwareMixerThread by convention.
Glenn Kasten1879fff2012-07-11 15:36:59 -07001548 recordTrack = thread->createRecordTrack_l(client, sampleRate, format, channelMask,
Glenn Kastenddb0ccf2013-07-31 16:14:50 -07001549 frameCount, lSessionId, flags, tid, &lStatus);
Glenn Kastene93cf2c2013-09-24 11:52:37 -07001550 LOG_ALWAYS_FATAL_IF((recordTrack != 0) != (lStatus == NO_ERROR));
Mathias Agopian65ab4712010-07-14 17:59:35 -07001551 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07001552 if (lStatus != NO_ERROR) {
Glenn Kasten85ab62c2012-11-01 11:11:38 -07001553 // remove local strong reference to Client before deleting the RecordTrack so that the
1554 // Client destructor is called by the TrackBase destructor with mLock held
Mathias Agopian65ab4712010-07-14 17:59:35 -07001555 client.clear();
1556 recordTrack.clear();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001557 goto Exit;
1558 }
1559
1560 // return to handle to client
1561 recordHandle = new RecordHandle(recordTrack);
1562 lStatus = NO_ERROR;
1563
1564Exit:
1565 if (status) {
1566 *status = lStatus;
1567 }
1568 return recordHandle;
1569}
1570
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001571
1572
Mathias Agopian65ab4712010-07-14 17:59:35 -07001573// ----------------------------------------------------------------------------
1574
Eric Laurenta4c5a552012-03-29 10:12:40 -07001575audio_module_handle_t AudioFlinger::loadHwModule(const char *name)
1576{
1577 if (!settingsAllowed()) {
1578 return 0;
1579 }
1580 Mutex::Autolock _l(mLock);
1581 return loadHwModule_l(name);
1582}
1583
1584// loadHwModule_l() must be called with AudioFlinger::mLock held
1585audio_module_handle_t AudioFlinger::loadHwModule_l(const char *name)
1586{
1587 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
1588 if (strncmp(mAudioHwDevs.valueAt(i)->moduleName(), name, strlen(name)) == 0) {
1589 ALOGW("loadHwModule() module %s already loaded", name);
1590 return mAudioHwDevs.keyAt(i);
1591 }
1592 }
1593
Eric Laurenta4c5a552012-03-29 10:12:40 -07001594 audio_hw_device_t *dev;
1595
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07001596 int rc = load_audio_interface(name, &dev);
Eric Laurenta4c5a552012-03-29 10:12:40 -07001597 if (rc) {
1598 ALOGI("loadHwModule() error %d loading module %s ", rc, name);
1599 return 0;
1600 }
1601
1602 mHardwareStatus = AUDIO_HW_INIT;
1603 rc = dev->init_check(dev);
1604 mHardwareStatus = AUDIO_HW_IDLE;
1605 if (rc) {
1606 ALOGI("loadHwModule() init check error %d for module %s ", rc, name);
1607 return 0;
1608 }
1609
John Grossmanee578c02012-07-23 17:05:46 -07001610 // Check and cache this HAL's level of support for master mute and master
1611 // volume. If this is the first HAL opened, and it supports the get
1612 // methods, use the initial values provided by the HAL as the current
1613 // master mute and volume settings.
1614
1615 AudioHwDevice::Flags flags = static_cast<AudioHwDevice::Flags>(0);
1616 { // scope for auto-lock pattern
Eric Laurenta4c5a552012-03-29 10:12:40 -07001617 AutoMutex lock(mHardwareLock);
John Grossmanee578c02012-07-23 17:05:46 -07001618
Ricardo Cerqueira0d44b5b2013-11-03 02:46:27 +00001619#if !defined(ICS_AUDIO_BLOB) && !defined(MR0_AUDIO_BLOB)
John Grossmanee578c02012-07-23 17:05:46 -07001620 if (0 == mAudioHwDevs.size()) {
1621 mHardwareStatus = AUDIO_HW_GET_MASTER_VOLUME;
1622 if (NULL != dev->get_master_volume) {
1623 float mv;
1624 if (OK == dev->get_master_volume(dev, &mv)) {
1625 mMasterVolume = mv;
1626 }
1627 }
1628
1629 mHardwareStatus = AUDIO_HW_GET_MASTER_MUTE;
1630 if (NULL != dev->get_master_mute) {
1631 bool mm;
1632 if (OK == dev->get_master_mute(dev, &mm)) {
1633 mMasterMute = mm;
1634 }
1635 }
1636 }
Ricardo Cerqueira0d44b5b2013-11-03 02:46:27 +00001637#endif
John Grossmanee578c02012-07-23 17:05:46 -07001638
Eric Laurenta4c5a552012-03-29 10:12:40 -07001639 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
John Grossmanee578c02012-07-23 17:05:46 -07001640 if ((NULL != dev->set_master_volume) &&
1641 (OK == dev->set_master_volume(dev, mMasterVolume))) {
1642 flags = static_cast<AudioHwDevice::Flags>(flags |
1643 AudioHwDevice::AHWD_CAN_SET_MASTER_VOLUME);
1644 }
1645
Ricardo Cerqueira0d44b5b2013-11-03 02:46:27 +00001646#if !defined(ICS_AUDIO_BLOB) && !defined(MR0_AUDIO_BLOB)
John Grossmanee578c02012-07-23 17:05:46 -07001647 mHardwareStatus = AUDIO_HW_SET_MASTER_MUTE;
1648 if ((NULL != dev->set_master_mute) &&
1649 (OK == dev->set_master_mute(dev, mMasterMute))) {
1650 flags = static_cast<AudioHwDevice::Flags>(flags |
1651 AudioHwDevice::AHWD_CAN_SET_MASTER_MUTE);
1652 }
Ricardo Cerqueira0d44b5b2013-11-03 02:46:27 +00001653#endif
John Grossmanee578c02012-07-23 17:05:46 -07001654
Eric Laurenta4c5a552012-03-29 10:12:40 -07001655 mHardwareStatus = AUDIO_HW_IDLE;
1656 }
1657
1658 audio_module_handle_t handle = nextUniqueId();
John Grossmanee578c02012-07-23 17:05:46 -07001659 mAudioHwDevs.add(handle, new AudioHwDevice(name, dev, flags));
Eric Laurenta4c5a552012-03-29 10:12:40 -07001660
1661 ALOGI("loadHwModule() Loaded %s audio interface from %s (%s) handle %d",
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07001662 name, dev->common.module->name, dev->common.module->id, handle);
Eric Laurenta4c5a552012-03-29 10:12:40 -07001663
1664 return handle;
1665
1666}
1667
Glenn Kastencc0f1cf2012-09-24 11:27:18 -07001668// ----------------------------------------------------------------------------
1669
Glenn Kasten3b16c762012-11-14 08:44:39 -08001670uint32_t AudioFlinger::getPrimaryOutputSamplingRate()
Glenn Kastencc0f1cf2012-09-24 11:27:18 -07001671{
1672 Mutex::Autolock _l(mLock);
1673 PlaybackThread *thread = primaryPlaybackThread_l();
1674 return thread != NULL ? thread->sampleRate() : 0;
1675}
1676
Glenn Kastene33054e2012-11-14 12:54:39 -08001677size_t AudioFlinger::getPrimaryOutputFrameCount()
Glenn Kastencc0f1cf2012-09-24 11:27:18 -07001678{
1679 Mutex::Autolock _l(mLock);
1680 PlaybackThread *thread = primaryPlaybackThread_l();
1681 return thread != NULL ? thread->frameCountHAL() : 0;
1682}
1683
1684// ----------------------------------------------------------------------------
1685
Glenn Kasten4182c4e2013-07-15 14:45:07 -07001686status_t AudioFlinger::setLowRamDevice(bool isLowRamDevice)
1687{
1688 uid_t uid = IPCThreadState::self()->getCallingUid();
1689 if (uid != AID_SYSTEM) {
1690 return PERMISSION_DENIED;
1691 }
1692 Mutex::Autolock _l(mLock);
1693 if (mIsDeviceTypeKnown) {
1694 return INVALID_OPERATION;
1695 }
1696 mIsLowRamDevice = isLowRamDevice;
1697 mIsDeviceTypeKnown = true;
1698 return NO_ERROR;
1699}
1700
1701// ----------------------------------------------------------------------------
1702
Eric Laurenta4c5a552012-03-29 10:12:40 -07001703audio_io_handle_t AudioFlinger::openOutput(audio_module_handle_t module,
1704 audio_devices_t *pDevices,
1705 uint32_t *pSamplingRate,
1706 audio_format_t *pFormat,
1707 audio_channel_mask_t *pChannelMask,
1708 uint32_t *pLatencyMs,
Richard Fitzgeraldad3af332013-03-25 16:54:37 +00001709 audio_output_flags_t flags,
1710 const audio_offload_info_t *offloadInfo)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001711{
Mathias Agopian65ab4712010-07-14 17:59:35 -07001712 PlaybackThread *thread = NULL;
Richard Fitzgeraldad3af332013-03-25 16:54:37 +00001713 struct audio_config config;
1714 config.sample_rate = (pSamplingRate != NULL) ? *pSamplingRate : 0;
1715 config.channel_mask = (pChannelMask != NULL) ? *pChannelMask : 0;
1716 config.format = (pFormat != NULL) ? *pFormat : AUDIO_FORMAT_DEFAULT;
1717 if (offloadInfo) {
1718 config.offload_info = *offloadInfo;
1719 }
1720
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07001721 audio_stream_out_t *outStream = NULL;
John Grossmanee578c02012-07-23 17:05:46 -07001722 AudioHwDevice *outHwDev;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001723
Eric Laurentbfb1b832013-01-07 09:53:42 -08001724 ALOGV("openOutput(), module %d Device %x, SamplingRate %d, Format %#08x, Channels %x, flags %x",
Eric Laurenta4c5a552012-03-29 10:12:40 -07001725 module,
Glenn Kastenbb4350d2012-07-03 15:56:38 -07001726 (pDevices != NULL) ? *pDevices : 0,
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07001727 config.sample_rate,
1728 config.format,
1729 config.channel_mask,
Eric Laurenta4c5a552012-03-29 10:12:40 -07001730 flags);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001731 ALOGV("openOutput(), offloadInfo %p version 0x%04x",
1732 offloadInfo, offloadInfo == NULL ? -1 : offloadInfo->version );
Mathias Agopian65ab4712010-07-14 17:59:35 -07001733
1734 if (pDevices == NULL || *pDevices == 0) {
1735 return 0;
1736 }
Dima Zavin799a70e2011-04-18 16:57:27 -07001737
Mathias Agopian65ab4712010-07-14 17:59:35 -07001738 Mutex::Autolock _l(mLock);
1739
Eric Laurenta4c5a552012-03-29 10:12:40 -07001740 outHwDev = findSuitableHwDev_l(module, *pDevices);
Dima Zavin799a70e2011-04-18 16:57:27 -07001741 if (outHwDev == NULL)
1742 return 0;
1743
John Grossmanee578c02012-07-23 17:05:46 -07001744 audio_hw_device_t *hwDevHal = outHwDev->hwDevice();
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07001745 audio_io_handle_t id = nextUniqueId();
1746
Glenn Kasten8abf44d2012-02-02 14:16:03 -08001747 mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07001748
Ricardo Cerqueira0d44b5b2013-11-03 02:46:27 +00001749 status_t status;
1750#ifndef ICS_AUDIO_BLOB
1751 status = hwDevHal->open_output_stream(hwDevHal,
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07001752 id,
1753 *pDevices,
1754 (audio_output_flags_t)flags,
1755 &config,
1756 &outStream);
Ricardo Cerqueira0d44b5b2013-11-03 02:46:27 +00001757#else
1758 status = hwDevHal->open_output_stream(hwDevHal,
1759 *pDevices,
1760 (int *)&config.format,
1761 &config.channel_mask,
1762 &config.sample_rate,
1763 &outStream);
1764 uint32_t newflags = flags | AUDIO_OUTPUT_FLAG_PRIMARY;
1765 flags = (audio_output_flags_t)newflags;
1766#endif
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07001767
Glenn Kasten8abf44d2012-02-02 14:16:03 -08001768 mHardwareStatus = AUDIO_HW_IDLE;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001769 ALOGV("openOutput() openOutputStream returned output %p, SamplingRate %d, Format %#08x, "
Glenn Kasten85ab62c2012-11-01 11:11:38 -07001770 "Channels %x, status %d",
Dima Zavin799a70e2011-04-18 16:57:27 -07001771 outStream,
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07001772 config.sample_rate,
1773 config.format,
1774 config.channel_mask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07001775 status);
1776
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07001777 if (status == NO_ERROR && outStream != NULL) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001778 AudioStreamOut *output = new AudioStreamOut(outHwDev, outStream, flags);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001779 if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
1780 thread = new OffloadThread(this, output, id, *pDevices);
1781 ALOGV("openOutput() created offload output: ID %d thread %p", id, thread);
Alok Kediya601e9b52013-09-27 11:55:10 +05301782 }
1783 if (flags & AUDIO_OUTPUT_FLAG_LPA || flags & AUDIO_OUTPUT_FLAG_TUNNEL ) {
1784 AudioSessionDescriptor *desc = new AudioSessionDescriptor(hwDevHal, outStream, flags);
1785 desc->mActive = true;
1786 //TODO: no stream type
1787 //desc->mStreamType = streamType;
1788 desc->mVolumeLeft = 1.0;
1789 desc->mVolumeRight = 1.0;
1790 desc->device = *pDevices;
1791 desc->trackRefPtr = NULL;
1792 mDirectAudioTracks.add(id, desc);
1793 mDirectDevice = desc->device;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001794 } else if ((flags & AUDIO_OUTPUT_FLAG_DIRECT) ||
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07001795 (config.format != AUDIO_FORMAT_PCM_16_BIT) ||
1796 (config.channel_mask != AUDIO_CHANNEL_OUT_STEREO)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001797 thread = new DirectOutputThread(this, output, id, *pDevices);
Steve Block3856b092011-10-20 11:56:00 +01001798 ALOGV("openOutput() created direct output: ID %d thread %p", id, thread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001799 } else {
1800 thread = new MixerThread(this, output, id, *pDevices);
Steve Block3856b092011-10-20 11:56:00 +01001801 ALOGV("openOutput() created mixer output: ID %d thread %p", id, thread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001802 }
Alok Kediya601e9b52013-09-27 11:55:10 +05301803 if (thread != NULL) {
1804 mPlaybackThreads.add(id, thread);
1805 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001806
Glenn Kasten7c027242012-12-26 14:43:16 -08001807 if (pSamplingRate != NULL) {
1808 *pSamplingRate = config.sample_rate;
1809 }
1810 if (pFormat != NULL) {
1811 *pFormat = config.format;
1812 }
1813 if (pChannelMask != NULL) {
1814 *pChannelMask = config.channel_mask;
1815 }
Alok Kediya601e9b52013-09-27 11:55:10 +05301816 if (thread != NULL) {
1817 if (pLatencyMs != NULL) *pLatencyMs = thread->latency();
1818 // notify client processes of the new output creation
1819 thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
1820 }
1821 else {
1822 *pLatencyMs = 0;
1823 if ((flags & AUDIO_OUTPUT_FLAG_LPA) || (flags & AUDIO_OUTPUT_FLAG_TUNNEL)) {
1824 AudioSessionDescriptor *desc = mDirectAudioTracks.valueFor(id);
1825 *pLatencyMs = desc->stream->get_latency(desc->stream);
1826 }
Glenn Kasten7c027242012-12-26 14:43:16 -08001827 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001828
Eric Laurenta4c5a552012-03-29 10:12:40 -07001829
1830 // the first primary output opened designates the primary hw device
Eric Laurent0ca3cf92012-04-18 09:24:29 -07001831 if ((mPrimaryHardwareDev == NULL) && (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
Eric Laurenta4c5a552012-03-29 10:12:40 -07001832 ALOGI("Using module %d has the primary audio interface", module);
1833 mPrimaryHardwareDev = outHwDev;
Alok Kediya601e9b52013-09-27 11:55:10 +05301834#ifdef SRS_PROCESSING
1835 SRS_Processing::RawDataSet(NULL, "qdsp hook", &mPrimaryHardwareDev,
1836 sizeof(&mPrimaryHardwareDev));
1837#endif
Eric Laurenta4c5a552012-03-29 10:12:40 -07001838 AutoMutex lock(mHardwareLock);
1839 mHardwareStatus = AUDIO_HW_SET_MODE;
John Grossmanee578c02012-07-23 17:05:46 -07001840 hwDevHal->set_mode(hwDevHal, mMode);
Eric Laurenta4c5a552012-03-29 10:12:40 -07001841 mHardwareStatus = AUDIO_HW_IDLE;
Eric Laurenta4c5a552012-03-29 10:12:40 -07001842 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001843 return id;
1844 }
1845
1846 return 0;
1847}
1848
Glenn Kasten72ef00d2012-01-17 11:09:42 -08001849audio_io_handle_t AudioFlinger::openDuplicateOutput(audio_io_handle_t output1,
1850 audio_io_handle_t output2)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001851{
1852 Mutex::Autolock _l(mLock);
1853 MixerThread *thread1 = checkMixerThread_l(output1);
1854 MixerThread *thread2 = checkMixerThread_l(output2);
1855
1856 if (thread1 == NULL || thread2 == NULL) {
Glenn Kasten85ab62c2012-11-01 11:11:38 -07001857 ALOGW("openDuplicateOutput() wrong output mixer type for output %d or %d", output1,
1858 output2);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001859 return 0;
1860 }
1861
Glenn Kasten72ef00d2012-01-17 11:09:42 -08001862 audio_io_handle_t id = nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001863 DuplicatingThread *thread = new DuplicatingThread(this, thread1, id);
1864 thread->addOutputTrack(thread2);
1865 mPlaybackThreads.add(id, thread);
1866 // notify client processes of the new output creation
1867 thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
1868 return id;
1869}
1870
Glenn Kasten72ef00d2012-01-17 11:09:42 -08001871status_t AudioFlinger::closeOutput(audio_io_handle_t output)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001872{
Glenn Kastend96c5722012-04-25 13:44:49 -07001873 return closeOutput_nonvirtual(output);
1874}
1875
1876status_t AudioFlinger::closeOutput_nonvirtual(audio_io_handle_t output)
1877{
Mathias Agopian65ab4712010-07-14 17:59:35 -07001878 // keep strong reference on the playback thread so that
1879 // it is not destroyed while exit() is executed
Alok Kediya601e9b52013-09-27 11:55:10 +05301880 AudioSessionDescriptor *desc = mDirectAudioTracks.valueFor(output);
1881 if (desc) {
1882 ALOGV("Closing DirectTrack output %d", output);
1883 desc->mActive = false;
1884 desc->stream->common.standby(&desc->stream->common);
1885 desc->hwDev->close_output_stream(desc->hwDev, desc->stream);
1886 desc->trackRefPtr = NULL;
1887 desc->stream = NULL;
1888 mDirectAudioTracks.removeItem(output);
1889 audioConfigChanged_l(AudioSystem::OUTPUT_CLOSED, output, NULL);
1890 delete desc;
1891 return NO_ERROR;
1892 }
1893
Glenn Kastene53b9ea2012-03-12 16:29:55 -07001894 sp<PlaybackThread> thread;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001895 {
1896 Mutex::Autolock _l(mLock);
1897 thread = checkPlaybackThread_l(output);
1898 if (thread == NULL) {
1899 return BAD_VALUE;
1900 }
1901
Steve Block3856b092011-10-20 11:56:00 +01001902 ALOGV("closeOutput() %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001903
Eric Laurent7c7f10b2011-06-17 21:29:58 -07001904 if (thread->type() == ThreadBase::MIXER) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001905 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07001906 if (mPlaybackThreads.valueAt(i)->type() == ThreadBase::DUPLICATING) {
Glenn Kasten85ab62c2012-11-01 11:11:38 -07001907 DuplicatingThread *dupThread =
1908 (DuplicatingThread *)mPlaybackThreads.valueAt(i).get();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001909 dupThread->removeOutputTrack((MixerThread *)thread.get());
Eric Laurentbfb1b832013-01-07 09:53:42 -08001910
1911 }
1912 }
1913 }
1914
1915
1916 mPlaybackThreads.removeItem(output);
1917 // save all effects to the default thread
1918 if (mPlaybackThreads.size()) {
1919 PlaybackThread *dstThread = checkPlaybackThread_l(mPlaybackThreads.keyAt(0));
1920 if (dstThread != NULL) {
1921 // audioflinger lock is held here so the acquisition order of thread locks does not
1922 // matter
1923 Mutex::Autolock _dl(dstThread->mLock);
1924 Mutex::Autolock _sl(thread->mLock);
1925 Vector< sp<EffectChain> > effectChains = thread->getEffectChains_l();
1926 for (size_t i = 0; i < effectChains.size(); i ++) {
1927 moveEffectChain_l(effectChains[i]->sessionId(), thread.get(), dstThread, true);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001928 }
1929 }
1930 }
Glenn Kastena1117922012-01-26 10:53:32 -08001931 audioConfigChanged_l(AudioSystem::OUTPUT_CLOSED, output, NULL);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001932 }
1933 thread->exit();
Glenn Kastenb28686f2012-01-06 08:39:38 -08001934 // The thread entity (active unit of execution) is no longer running here,
1935 // but the ThreadBase container still exists.
Mathias Agopian65ab4712010-07-14 17:59:35 -07001936
Eric Laurent7c7f10b2011-06-17 21:29:58 -07001937 if (thread->type() != ThreadBase::DUPLICATING) {
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001938 AudioStreamOut *out = thread->clearOutput();
Glenn Kasten5798d4e2012-03-08 12:18:35 -08001939 ALOG_ASSERT(out != NULL, "out shouldn't be NULL");
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001940 // from now on thread->mOutput is NULL
John Grossmanee578c02012-07-23 17:05:46 -07001941 out->hwDev()->close_output_stream(out->hwDev(), out->stream);
Dima Zavin799a70e2011-04-18 16:57:27 -07001942 delete out;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001943 }
1944 return NO_ERROR;
1945}
1946
Glenn Kasten72ef00d2012-01-17 11:09:42 -08001947status_t AudioFlinger::suspendOutput(audio_io_handle_t output)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001948{
1949 Mutex::Autolock _l(mLock);
1950 PlaybackThread *thread = checkPlaybackThread_l(output);
1951
1952 if (thread == NULL) {
1953 return BAD_VALUE;
1954 }
1955
Steve Block3856b092011-10-20 11:56:00 +01001956 ALOGV("suspendOutput() %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001957 thread->suspend();
1958
1959 return NO_ERROR;
1960}
1961
Glenn Kasten72ef00d2012-01-17 11:09:42 -08001962status_t AudioFlinger::restoreOutput(audio_io_handle_t output)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001963{
1964 Mutex::Autolock _l(mLock);
1965 PlaybackThread *thread = checkPlaybackThread_l(output);
1966
1967 if (thread == NULL) {
1968 return BAD_VALUE;
1969 }
1970
Steve Block3856b092011-10-20 11:56:00 +01001971 ALOGV("restoreOutput() %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001972
1973 thread->restore();
1974
1975 return NO_ERROR;
1976}
1977
Eric Laurenta4c5a552012-03-29 10:12:40 -07001978audio_io_handle_t AudioFlinger::openInput(audio_module_handle_t module,
1979 audio_devices_t *pDevices,
1980 uint32_t *pSamplingRate,
1981 audio_format_t *pFormat,
Glenn Kasten254af182012-07-03 14:59:05 -07001982 audio_channel_mask_t *pChannelMask)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001983{
1984 status_t status;
1985 RecordThread *thread = NULL;
Richard Fitzgeraldad3af332013-03-25 16:54:37 +00001986 struct audio_config config;
1987 config.sample_rate = (pSamplingRate != NULL) ? *pSamplingRate : 0;
1988 config.channel_mask = (pChannelMask != NULL) ? *pChannelMask : 0;
1989 config.format = (pFormat != NULL) ? *pFormat : AUDIO_FORMAT_DEFAULT;
1990
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07001991 uint32_t reqSamplingRate = config.sample_rate;
1992 audio_format_t reqFormat = config.format;
1993 audio_channel_mask_t reqChannels = config.channel_mask;
1994 audio_stream_in_t *inStream = NULL;
John Grossmanee578c02012-07-23 17:05:46 -07001995 AudioHwDevice *inHwDev;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001996
1997 if (pDevices == NULL || *pDevices == 0) {
1998 return 0;
1999 }
Dima Zavin799a70e2011-04-18 16:57:27 -07002000
Mathias Agopian65ab4712010-07-14 17:59:35 -07002001 Mutex::Autolock _l(mLock);
2002
Eric Laurenta4c5a552012-03-29 10:12:40 -07002003 inHwDev = findSuitableHwDev_l(module, *pDevices);
Dima Zavin799a70e2011-04-18 16:57:27 -07002004 if (inHwDev == NULL)
2005 return 0;
2006
John Grossmanee578c02012-07-23 17:05:46 -07002007 audio_hw_device_t *inHwHal = inHwDev->hwDevice();
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07002008 audio_io_handle_t id = nextUniqueId();
2009
Ricardo Cerqueira0d44b5b2013-11-03 02:46:27 +00002010#ifndef ICS_AUDIO_BLOB
John Grossmanee578c02012-07-23 17:05:46 -07002011 status = inHwHal->open_input_stream(inHwHal, id, *pDevices, &config,
Dima Zavin799a70e2011-04-18 16:57:27 -07002012 &inStream);
Ricardo Cerqueira0d44b5b2013-11-03 02:46:27 +00002013#else
2014 status = inHwHal->open_input_stream(inHwHal, *pDevices,
2015 (int *)&config.format,
2016 &config.channel_mask,
2017 &config.sample_rate, (audio_in_acoustics_t)0,
2018 &inStream);
2019#endif
Glenn Kasten85ab62c2012-11-01 11:11:38 -07002020 ALOGV("openInput() openInputStream returned input %p, SamplingRate %d, Format %d, Channels %x, "
2021 "status %d",
Dima Zavin799a70e2011-04-18 16:57:27 -07002022 inStream,
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07002023 config.sample_rate,
2024 config.format,
2025 config.channel_mask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07002026 status);
2027
Glenn Kasten85ab62c2012-11-01 11:11:38 -07002028 // If the input could not be opened with the requested parameters and we can handle the
2029 // conversion internally, try to open again with the proposed parameters. The AudioFlinger can
2030 // resample the input and do mono to stereo or stereo to mono conversions on 16 bit PCM inputs.
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07002031 if (status == BAD_VALUE &&
2032 reqFormat == config.format && config.format == AUDIO_FORMAT_PCM_16_BIT &&
2033 (config.sample_rate <= 2 * reqSamplingRate) &&
Alok Kediya601e9b52013-09-27 11:55:10 +05302034 (getInputChannelCount(config.channel_mask) <= FCC_2) && (getInputChannelCount(reqChannels) <= FCC_2)) {
Glenn Kasten254af182012-07-03 14:59:05 -07002035 ALOGV("openInput() reopening with proposed sampling rate and channel mask");
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07002036 inStream = NULL;
Ricardo Cerqueira0d44b5b2013-11-03 02:46:27 +00002037#ifndef ICS_AUDIO_BLOB
John Grossmanee578c02012-07-23 17:05:46 -07002038 status = inHwHal->open_input_stream(inHwHal, id, *pDevices, &config, &inStream);
Ricardo Cerqueira0d44b5b2013-11-03 02:46:27 +00002039#else
2040 status = inHwHal->open_input_stream(inHwHal, *pDevices,
2041 (int *)&config.format,
2042 &config.channel_mask,
2043 &config.sample_rate, (audio_in_acoustics_t)0,
2044 &inStream);
2045#endif
Mathias Agopian65ab4712010-07-14 17:59:35 -07002046 }
2047
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07002048 if (status == NO_ERROR && inStream != NULL) {
Glenn Kastend06785b2012-09-30 12:29:28 -07002049
Glenn Kasten46909e72013-02-26 09:20:22 -08002050#ifdef TEE_SINK
Glenn Kastend06785b2012-09-30 12:29:28 -07002051 // Try to re-use most recently used Pipe to archive a copy of input for dumpsys,
2052 // or (re-)create if current Pipe is idle and does not match the new format
2053 sp<NBAIO_Sink> teeSink;
Glenn Kastend06785b2012-09-30 12:29:28 -07002054 enum {
2055 TEE_SINK_NO, // don't copy input
2056 TEE_SINK_NEW, // copy input using a new pipe
2057 TEE_SINK_OLD, // copy input using an existing pipe
2058 } kind;
2059 NBAIO_Format format = Format_from_SR_C(inStream->common.get_sample_rate(&inStream->common),
2060 popcount(inStream->common.get_channels(&inStream->common)));
Glenn Kastenda6ef132013-01-10 12:31:01 -08002061 if (!mTeeSinkInputEnabled) {
2062 kind = TEE_SINK_NO;
2063 } else if (format == Format_Invalid) {
Glenn Kastend06785b2012-09-30 12:29:28 -07002064 kind = TEE_SINK_NO;
2065 } else if (mRecordTeeSink == 0) {
2066 kind = TEE_SINK_NEW;
2067 } else if (mRecordTeeSink->getStrongCount() != 1) {
2068 kind = TEE_SINK_NO;
2069 } else if (format == mRecordTeeSink->format()) {
2070 kind = TEE_SINK_OLD;
2071 } else {
2072 kind = TEE_SINK_NEW;
2073 }
2074 switch (kind) {
2075 case TEE_SINK_NEW: {
Glenn Kastenda6ef132013-01-10 12:31:01 -08002076 Pipe *pipe = new Pipe(mTeeSinkInputFrames, format);
Glenn Kastend06785b2012-09-30 12:29:28 -07002077 size_t numCounterOffers = 0;
2078 const NBAIO_Format offers[1] = {format};
2079 ssize_t index = pipe->negotiate(offers, 1, NULL, numCounterOffers);
2080 ALOG_ASSERT(index == 0);
2081 PipeReader *pipeReader = new PipeReader(*pipe);
2082 numCounterOffers = 0;
2083 index = pipeReader->negotiate(offers, 1, NULL, numCounterOffers);
2084 ALOG_ASSERT(index == 0);
2085 mRecordTeeSink = pipe;
2086 mRecordTeeSource = pipeReader;
2087 teeSink = pipe;
2088 }
2089 break;
2090 case TEE_SINK_OLD:
2091 teeSink = mRecordTeeSink;
2092 break;
2093 case TEE_SINK_NO:
2094 default:
2095 break;
2096 }
Glenn Kasten46909e72013-02-26 09:20:22 -08002097#endif
Glenn Kastenda6ef132013-01-10 12:31:01 -08002098
Dima Zavin799a70e2011-04-18 16:57:27 -07002099 AudioStreamIn *input = new AudioStreamIn(inHwDev, inStream);
2100
Eric Laurent7c7f10b2011-06-17 21:29:58 -07002101 // Start record thread
Glenn Kasten34af0262013-07-30 11:52:39 -07002102 // RecordThread requires both input and output device indication to forward to audio
Eric Laurent7c7f10b2011-06-17 21:29:58 -07002103 // pre processing modules
Eric Laurent7c7f10b2011-06-17 21:29:58 -07002104 thread = new RecordThread(this,
2105 input,
2106 reqSamplingRate,
2107 reqChannels,
2108 id,
Eric Laurentd3922f72013-02-01 17:57:04 -08002109 primaryOutputDevice_l(),
Glenn Kasten46909e72013-02-26 09:20:22 -08002110 *pDevices
2111#ifdef TEE_SINK
2112 , teeSink
2113#endif
2114 );
Mathias Agopian65ab4712010-07-14 17:59:35 -07002115 mRecordThreads.add(id, thread);
Steve Block3856b092011-10-20 11:56:00 +01002116 ALOGV("openInput() created record thread: ID %d thread %p", id, thread);
Glenn Kasten7c027242012-12-26 14:43:16 -08002117 if (pSamplingRate != NULL) {
2118 *pSamplingRate = reqSamplingRate;
2119 }
2120 if (pFormat != NULL) {
2121 *pFormat = config.format;
2122 }
2123 if (pChannelMask != NULL) {
2124 *pChannelMask = reqChannels;
2125 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002126
Mathias Agopian65ab4712010-07-14 17:59:35 -07002127 // notify client processes of the new input creation
2128 thread->audioConfigChanged_l(AudioSystem::INPUT_OPENED);
2129 return id;
2130 }
2131
2132 return 0;
2133}
2134
Glenn Kasten72ef00d2012-01-17 11:09:42 -08002135status_t AudioFlinger::closeInput(audio_io_handle_t input)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002136{
Glenn Kastend96c5722012-04-25 13:44:49 -07002137 return closeInput_nonvirtual(input);
2138}
2139
2140status_t AudioFlinger::closeInput_nonvirtual(audio_io_handle_t input)
2141{
Mathias Agopian65ab4712010-07-14 17:59:35 -07002142 // keep strong reference on the record thread so that
2143 // it is not destroyed while exit() is executed
Glenn Kastene53b9ea2012-03-12 16:29:55 -07002144 sp<RecordThread> thread;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002145 {
2146 Mutex::Autolock _l(mLock);
2147 thread = checkRecordThread_l(input);
Glenn Kastend5903ec2012-03-18 10:33:27 -07002148 if (thread == 0) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002149 return BAD_VALUE;
2150 }
2151
Steve Block3856b092011-10-20 11:56:00 +01002152 ALOGV("closeInput() %d", input);
Glenn Kastena1117922012-01-26 10:53:32 -08002153 audioConfigChanged_l(AudioSystem::INPUT_CLOSED, input, NULL);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002154 mRecordThreads.removeItem(input);
2155 }
2156 thread->exit();
Glenn Kastenb28686f2012-01-06 08:39:38 -08002157 // The thread entity (active unit of execution) is no longer running here,
2158 // but the ThreadBase container still exists.
Mathias Agopian65ab4712010-07-14 17:59:35 -07002159
Eric Laurentb8ba0a92011-08-07 16:32:26 -07002160 AudioStreamIn *in = thread->clearInput();
Glenn Kasten5798d4e2012-03-08 12:18:35 -08002161 ALOG_ASSERT(in != NULL, "in shouldn't be NULL");
Eric Laurentb8ba0a92011-08-07 16:32:26 -07002162 // from now on thread->mInput is NULL
John Grossmanee578c02012-07-23 17:05:46 -07002163 in->hwDev()->close_input_stream(in->hwDev(), in->stream);
Dima Zavin799a70e2011-04-18 16:57:27 -07002164 delete in;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002165
2166 return NO_ERROR;
2167}
2168
Glenn Kasten72ef00d2012-01-17 11:09:42 -08002169status_t AudioFlinger::setStreamOutput(audio_stream_type_t stream, audio_io_handle_t output)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002170{
2171 Mutex::Autolock _l(mLock);
Steve Block3856b092011-10-20 11:56:00 +01002172 ALOGV("setStreamOutput() stream %d to output %d", stream, output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002173
2174 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
2175 PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
Eric Laurent22167852012-06-20 12:26:32 -07002176 thread->invalidateTracks(stream);
Eric Laurentde070132010-07-13 04:45:46 -07002177 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002178
2179 return NO_ERROR;
2180}
2181
2182
2183int AudioFlinger::newAudioSessionId()
2184{
Eric Laurent7c7f10b2011-06-17 21:29:58 -07002185 return nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002186}
2187
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002188void AudioFlinger::acquireAudioSessionId(int audioSession)
2189{
2190 Mutex::Autolock _l(mLock);
Glenn Kastenbb001922012-02-03 11:10:26 -08002191 pid_t caller = IPCThreadState::self()->getCallingPid();
Steve Block3856b092011-10-20 11:56:00 +01002192 ALOGV("acquiring %d from %d", audioSession, caller);
Eric Laurentd1b28d42013-09-18 18:47:13 -07002193
2194 // Ignore requests received from processes not known as notification client. The request
2195 // is likely proxied by mediaserver (e.g CameraService) and releaseAudioSessionId() can be
2196 // called from a different pid leaving a stale session reference. Also we don't know how
2197 // to clear this reference if the client process dies.
2198 if (mNotificationClients.indexOfKey(caller) < 0) {
2199 ALOGV("acquireAudioSessionId() unknown client %d for session %d", caller, audioSession);
2200 return;
2201 }
2202
Glenn Kasten8d6a2442012-02-08 14:04:28 -08002203 size_t num = mAudioSessionRefs.size();
2204 for (size_t i = 0; i< num; i++) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002205 AudioSessionRef *ref = mAudioSessionRefs.editItemAt(i);
Glenn Kasten012ca6b2012-03-06 11:22:01 -08002206 if (ref->mSessionid == audioSession && ref->mPid == caller) {
2207 ref->mCnt++;
2208 ALOGV(" incremented refcount to %d", ref->mCnt);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002209 return;
2210 }
2211 }
Glenn Kasten84afa3b2012-01-25 15:28:08 -08002212 mAudioSessionRefs.push(new AudioSessionRef(audioSession, caller));
2213 ALOGV(" added new entry for %d", audioSession);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002214}
2215
2216void AudioFlinger::releaseAudioSessionId(int audioSession)
2217{
2218 Mutex::Autolock _l(mLock);
Glenn Kastenbb001922012-02-03 11:10:26 -08002219 pid_t caller = IPCThreadState::self()->getCallingPid();
Steve Block3856b092011-10-20 11:56:00 +01002220 ALOGV("releasing %d from %d", audioSession, caller);
Glenn Kasten8d6a2442012-02-08 14:04:28 -08002221 size_t num = mAudioSessionRefs.size();
2222 for (size_t i = 0; i< num; i++) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002223 AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
Glenn Kasten012ca6b2012-03-06 11:22:01 -08002224 if (ref->mSessionid == audioSession && ref->mPid == caller) {
2225 ref->mCnt--;
2226 ALOGV(" decremented refcount to %d", ref->mCnt);
2227 if (ref->mCnt == 0) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002228 mAudioSessionRefs.removeAt(i);
2229 delete ref;
2230 purgeStaleEffects_l();
2231 }
2232 return;
2233 }
2234 }
Eric Laurentd1b28d42013-09-18 18:47:13 -07002235 // If the caller is mediaserver it is likely that the session being released was acquired
2236 // on behalf of a process not in notification clients and we ignore the warning.
2237 ALOGW_IF(caller != getpid_cached, "session id %d not found for pid %d", audioSession, caller);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002238}
2239
2240void AudioFlinger::purgeStaleEffects_l() {
2241
Steve Block3856b092011-10-20 11:56:00 +01002242 ALOGV("purging stale effects");
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002243
2244 Vector< sp<EffectChain> > chains;
2245
2246 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
2247 sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
2248 for (size_t j = 0; j < t->mEffectChains.size(); j++) {
2249 sp<EffectChain> ec = t->mEffectChains[j];
Marco Nelissen0270b182011-08-12 14:14:39 -07002250 if (ec->sessionId() > AUDIO_SESSION_OUTPUT_MIX) {
2251 chains.push(ec);
2252 }
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002253 }
2254 }
2255 for (size_t i = 0; i < mRecordThreads.size(); i++) {
2256 sp<RecordThread> t = mRecordThreads.valueAt(i);
2257 for (size_t j = 0; j < t->mEffectChains.size(); j++) {
2258 sp<EffectChain> ec = t->mEffectChains[j];
2259 chains.push(ec);
2260 }
2261 }
2262
2263 for (size_t i = 0; i < chains.size(); i++) {
2264 sp<EffectChain> ec = chains[i];
2265 int sessionid = ec->sessionId();
2266 sp<ThreadBase> t = ec->mThread.promote();
2267 if (t == 0) {
2268 continue;
2269 }
2270 size_t numsessionrefs = mAudioSessionRefs.size();
2271 bool found = false;
2272 for (size_t k = 0; k < numsessionrefs; k++) {
2273 AudioSessionRef *ref = mAudioSessionRefs.itemAt(k);
Glenn Kasten012ca6b2012-03-06 11:22:01 -08002274 if (ref->mSessionid == sessionid) {
Steve Block3856b092011-10-20 11:56:00 +01002275 ALOGV(" session %d still exists for %d with %d refs",
Glenn Kastene53b9ea2012-03-12 16:29:55 -07002276 sessionid, ref->mPid, ref->mCnt);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002277 found = true;
2278 break;
2279 }
2280 }
2281 if (!found) {
Eric Laurenta5f44eb2012-06-25 11:38:29 -07002282 Mutex::Autolock _l (t->mLock);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002283 // remove all effects from the chain
2284 while (ec->mEffects.size()) {
2285 sp<EffectModule> effect = ec->mEffects[0];
2286 effect->unPin();
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002287 t->removeEffect_l(effect);
Eric Laurenta5f44eb2012-06-25 11:38:29 -07002288 if (effect->purgeHandles()) {
2289 t->checkSuspendOnEffectEnabled_l(effect, false, effect->sessionId());
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002290 }
2291 AudioSystem::unregisterEffect(effect->id());
2292 }
2293 }
2294 }
2295 return;
2296}
2297
Mathias Agopian65ab4712010-07-14 17:59:35 -07002298// checkPlaybackThread_l() must be called with AudioFlinger::mLock held
Glenn Kasten72ef00d2012-01-17 11:09:42 -08002299AudioFlinger::PlaybackThread *AudioFlinger::checkPlaybackThread_l(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07002300{
Glenn Kastena1117922012-01-26 10:53:32 -08002301 return mPlaybackThreads.valueFor(output).get();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002302}
2303
2304// checkMixerThread_l() must be called with AudioFlinger::mLock held
Glenn Kasten72ef00d2012-01-17 11:09:42 -08002305AudioFlinger::MixerThread *AudioFlinger::checkMixerThread_l(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07002306{
2307 PlaybackThread *thread = checkPlaybackThread_l(output);
Glenn Kastena1117922012-01-26 10:53:32 -08002308 return thread != NULL && thread->type() != ThreadBase::DIRECT ? (MixerThread *) thread : NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002309}
2310
2311// checkRecordThread_l() must be called with AudioFlinger::mLock held
Glenn Kasten72ef00d2012-01-17 11:09:42 -08002312AudioFlinger::RecordThread *AudioFlinger::checkRecordThread_l(audio_io_handle_t input) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07002313{
Glenn Kastena1117922012-01-26 10:53:32 -08002314 return mRecordThreads.valueFor(input).get();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002315}
2316
Eric Laurent7c7f10b2011-06-17 21:29:58 -07002317uint32_t AudioFlinger::nextUniqueId()
Mathias Agopian65ab4712010-07-14 17:59:35 -07002318{
Eric Laurent7c7f10b2011-06-17 21:29:58 -07002319 return android_atomic_inc(&mNextUniqueId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002320}
2321
Glenn Kasten02fe1bf2012-02-24 15:42:17 -08002322AudioFlinger::PlaybackThread *AudioFlinger::primaryPlaybackThread_l() const
Eric Laurent7c7f10b2011-06-17 21:29:58 -07002323{
2324 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
2325 PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
Eric Laurentb8ba0a92011-08-07 16:32:26 -07002326 AudioStreamOut *output = thread->getOutput();
John Grossmanee578c02012-07-23 17:05:46 -07002327 if (output != NULL && output->audioHwDev == mPrimaryHardwareDev) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07002328 return thread;
2329 }
2330 }
2331 return NULL;
2332}
2333
Glenn Kastenbb4350d2012-07-03 15:56:38 -07002334audio_devices_t AudioFlinger::primaryOutputDevice_l() const
Eric Laurent7c7f10b2011-06-17 21:29:58 -07002335{
2336 PlaybackThread *thread = primaryPlaybackThread_l();
2337
2338 if (thread == NULL) {
2339 return 0;
2340 }
2341
Eric Laurentf1c04f92012-08-28 14:26:53 -07002342 return thread->outDevice();
Eric Laurent7c7f10b2011-06-17 21:29:58 -07002343}
2344
Eric Laurenta011e352012-03-29 15:51:43 -07002345sp<AudioFlinger::SyncEvent> AudioFlinger::createSyncEvent(AudioSystem::sync_event_t type,
2346 int triggerSession,
2347 int listenerSession,
2348 sync_event_callback_t callBack,
2349 void *cookie)
2350{
2351 Mutex::Autolock _l(mLock);
2352
2353 sp<SyncEvent> event = new SyncEvent(type, triggerSession, listenerSession, callBack, cookie);
2354 status_t playStatus = NAME_NOT_FOUND;
2355 status_t recStatus = NAME_NOT_FOUND;
2356 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
2357 playStatus = mPlaybackThreads.valueAt(i)->setSyncEvent(event);
2358 if (playStatus == NO_ERROR) {
2359 return event;
2360 }
2361 }
2362 for (size_t i = 0; i < mRecordThreads.size(); i++) {
2363 recStatus = mRecordThreads.valueAt(i)->setSyncEvent(event);
2364 if (recStatus == NO_ERROR) {
2365 return event;
2366 }
2367 }
2368 if (playStatus == NAME_NOT_FOUND || recStatus == NAME_NOT_FOUND) {
2369 mPendingSyncEvents.add(event);
2370 } else {
2371 ALOGV("createSyncEvent() invalid event %d", event->type());
2372 event.clear();
2373 }
2374 return event;
2375}
Eric Laurent7c7f10b2011-06-17 21:29:58 -07002376
Mathias Agopian65ab4712010-07-14 17:59:35 -07002377// ----------------------------------------------------------------------------
2378// Effect management
2379// ----------------------------------------------------------------------------
2380
2381
Glenn Kastenf587ba52012-01-26 16:25:10 -08002382status_t AudioFlinger::queryNumberEffects(uint32_t *numEffects) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07002383{
2384 Mutex::Autolock _l(mLock);
2385 return EffectQueryNumberEffects(numEffects);
2386}
2387
Glenn Kastenf587ba52012-01-26 16:25:10 -08002388status_t AudioFlinger::queryEffect(uint32_t index, effect_descriptor_t *descriptor) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07002389{
2390 Mutex::Autolock _l(mLock);
2391 return EffectQueryEffect(index, descriptor);
2392}
2393
Glenn Kasten5e92a782012-01-30 07:40:52 -08002394status_t AudioFlinger::getEffectDescriptor(const effect_uuid_t *pUuid,
Glenn Kastenf587ba52012-01-26 16:25:10 -08002395 effect_descriptor_t *descriptor) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07002396{
2397 Mutex::Autolock _l(mLock);
2398 return EffectGetDescriptor(pUuid, descriptor);
2399}
2400
2401
Glenn Kasten8d6cc842012-02-03 11:06:53 -08002402sp<IEffect> AudioFlinger::createEffect(
Mathias Agopian65ab4712010-07-14 17:59:35 -07002403 effect_descriptor_t *pDesc,
2404 const sp<IEffectClient>& effectClient,
2405 int32_t priority,
Glenn Kasten72ef00d2012-01-17 11:09:42 -08002406 audio_io_handle_t io,
Mathias Agopian65ab4712010-07-14 17:59:35 -07002407 int sessionId,
2408 status_t *status,
2409 int *id,
2410 int *enabled)
2411{
2412 status_t lStatus = NO_ERROR;
2413 sp<EffectHandle> handle;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002414 effect_descriptor_t desc;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002415
Glenn Kasten8d6cc842012-02-03 11:06:53 -08002416 pid_t pid = IPCThreadState::self()->getCallingPid();
Glenn Kasten98ec94c2012-01-25 14:28:29 -08002417 ALOGV("createEffect pid %d, effectClient %p, priority %d, sessionId %d, io %d",
Eric Laurent7c7f10b2011-06-17 21:29:58 -07002418 pid, effectClient.get(), priority, sessionId, io);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002419
2420 if (pDesc == NULL) {
2421 lStatus = BAD_VALUE;
2422 goto Exit;
2423 }
2424
Eric Laurent84e9a102010-09-23 16:10:16 -07002425 // check audio settings permission for global effects
Dima Zavinfce7a472011-04-19 22:30:36 -07002426 if (sessionId == AUDIO_SESSION_OUTPUT_MIX && !settingsAllowed()) {
Eric Laurent84e9a102010-09-23 16:10:16 -07002427 lStatus = PERMISSION_DENIED;
2428 goto Exit;
2429 }
2430
Dima Zavinfce7a472011-04-19 22:30:36 -07002431 // Session AUDIO_SESSION_OUTPUT_STAGE is reserved for output stage effects
Eric Laurent84e9a102010-09-23 16:10:16 -07002432 // that can only be created by audio policy manager (running in same process)
Glenn Kasten44deb052012-02-05 18:09:08 -08002433 if (sessionId == AUDIO_SESSION_OUTPUT_STAGE && getpid_cached != pid) {
Eric Laurent84e9a102010-09-23 16:10:16 -07002434 lStatus = PERMISSION_DENIED;
2435 goto Exit;
2436 }
2437
Mathias Agopian65ab4712010-07-14 17:59:35 -07002438 {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002439 if (!EffectIsNullUuid(&pDesc->uuid)) {
2440 // if uuid is specified, request effect descriptor
2441 lStatus = EffectGetDescriptor(&pDesc->uuid, &desc);
2442 if (lStatus < 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00002443 ALOGW("createEffect() error %d from EffectGetDescriptor", lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002444 goto Exit;
2445 }
2446 } else {
2447 // if uuid is not specified, look for an available implementation
2448 // of the required type in effect factory
2449 if (EffectIsNullUuid(&pDesc->type)) {
Steve Block5ff1dd52012-01-05 23:22:43 +00002450 ALOGW("createEffect() no effect type");
Mathias Agopian65ab4712010-07-14 17:59:35 -07002451 lStatus = BAD_VALUE;
2452 goto Exit;
2453 }
2454 uint32_t numEffects = 0;
2455 effect_descriptor_t d;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002456 d.flags = 0; // prevent compiler warning
Mathias Agopian65ab4712010-07-14 17:59:35 -07002457 bool found = false;
2458
2459 lStatus = EffectQueryNumberEffects(&numEffects);
2460 if (lStatus < 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00002461 ALOGW("createEffect() error %d from EffectQueryNumberEffects", lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002462 goto Exit;
2463 }
2464 for (uint32_t i = 0; i < numEffects; i++) {
2465 lStatus = EffectQueryEffect(i, &desc);
2466 if (lStatus < 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00002467 ALOGW("createEffect() error %d from EffectQueryEffect", lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002468 continue;
2469 }
2470 if (memcmp(&desc.type, &pDesc->type, sizeof(effect_uuid_t)) == 0) {
2471 // If matching type found save effect descriptor. If the session is
2472 // 0 and the effect is not auxiliary, continue enumeration in case
2473 // an auxiliary version of this effect type is available
2474 found = true;
Glenn Kastena189a682012-02-20 12:16:30 -08002475 d = desc;
Dima Zavinfce7a472011-04-19 22:30:36 -07002476 if (sessionId != AUDIO_SESSION_OUTPUT_MIX ||
Mathias Agopian65ab4712010-07-14 17:59:35 -07002477 (desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
2478 break;
2479 }
2480 }
2481 }
2482 if (!found) {
2483 lStatus = BAD_VALUE;
Steve Block5ff1dd52012-01-05 23:22:43 +00002484 ALOGW("createEffect() effect not found");
Mathias Agopian65ab4712010-07-14 17:59:35 -07002485 goto Exit;
2486 }
2487 // For same effect type, chose auxiliary version over insert version if
2488 // connect to output mix (Compliance to OpenSL ES)
Dima Zavinfce7a472011-04-19 22:30:36 -07002489 if (sessionId == AUDIO_SESSION_OUTPUT_MIX &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07002490 (d.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_AUXILIARY) {
Glenn Kastena189a682012-02-20 12:16:30 -08002491 desc = d;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002492 }
2493 }
2494
2495 // Do not allow auxiliary effects on a session different from 0 (output mix)
Dima Zavinfce7a472011-04-19 22:30:36 -07002496 if (sessionId != AUDIO_SESSION_OUTPUT_MIX &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07002497 (desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
2498 lStatus = INVALID_OPERATION;
2499 goto Exit;
2500 }
2501
Eric Laurent59255e42011-07-27 19:49:51 -07002502 // check recording permission for visualizer
2503 if ((memcmp(&desc.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) &&
2504 !recordingAllowed()) {
2505 lStatus = PERMISSION_DENIED;
2506 goto Exit;
2507 }
2508
Mathias Agopian65ab4712010-07-14 17:59:35 -07002509 // return effect descriptor
Glenn Kastena189a682012-02-20 12:16:30 -08002510 *pDesc = desc;
Eric Laurenteb3c3372013-09-25 12:25:29 -07002511 if (io == 0 && sessionId == AUDIO_SESSION_OUTPUT_MIX) {
2512 // if the output returned by getOutputForEffect() is removed before we lock the
2513 // mutex below, the call to checkPlaybackThread_l(io) below will detect it
2514 // and we will exit safely
2515 io = AudioSystem::getOutputForEffect(&desc);
2516 ALOGV("createEffect got output %d", io);
2517 }
2518
2519 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002520
2521 // If output is not specified try to find a matching audio session ID in one of the
2522 // output threads.
Eric Laurent84e9a102010-09-23 16:10:16 -07002523 // If output is 0 here, sessionId is neither SESSION_OUTPUT_STAGE nor SESSION_OUTPUT_MIX
2524 // because of code checking output when entering the function.
Eric Laurent7c7f10b2011-06-17 21:29:58 -07002525 // Note: io is never 0 when creating an effect on an input
2526 if (io == 0) {
Eric Laurent5baf2af2013-09-12 17:37:00 -07002527 if (sessionId == AUDIO_SESSION_OUTPUT_STAGE) {
2528 // output must be specified by AudioPolicyManager when using session
2529 // AUDIO_SESSION_OUTPUT_STAGE
2530 lStatus = BAD_VALUE;
2531 goto Exit;
2532 }
Eric Laurenteb3c3372013-09-25 12:25:29 -07002533 // look for the thread where the specified audio session is present
2534 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
2535 if (mPlaybackThreads.valueAt(i)->hasAudioSession(sessionId) != 0) {
2536 io = mPlaybackThreads.keyAt(i);
2537 break;
2538 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002539 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07002540 if (io == 0) {
Eric Laurenteb3c3372013-09-25 12:25:29 -07002541 for (size_t i = 0; i < mRecordThreads.size(); i++) {
2542 if (mRecordThreads.valueAt(i)->hasAudioSession(sessionId) != 0) {
2543 io = mRecordThreads.keyAt(i);
Glenn Kastene53b9ea2012-03-12 16:29:55 -07002544 break;
2545 }
2546 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07002547 }
Eric Laurent84e9a102010-09-23 16:10:16 -07002548 // If no output thread contains the requested session ID, default to
2549 // first output. The effect chain will be moved to the correct output
2550 // thread when a track with the same session ID is created
Eric Laurent7c7f10b2011-06-17 21:29:58 -07002551 if (io == 0 && mPlaybackThreads.size()) {
2552 io = mPlaybackThreads.keyAt(0);
2553 }
Steve Block3856b092011-10-20 11:56:00 +01002554 ALOGV("createEffect() got io %d for effect %s", io, desc.name);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07002555 }
2556 ThreadBase *thread = checkRecordThread_l(io);
2557 if (thread == NULL) {
2558 thread = checkPlaybackThread_l(io);
2559 if (thread == NULL) {
Steve Block29357bc2012-01-06 19:20:56 +00002560 ALOGE("createEffect() unknown output thread");
Eric Laurent7c7f10b2011-06-17 21:29:58 -07002561 lStatus = BAD_VALUE;
2562 goto Exit;
Eric Laurent84e9a102010-09-23 16:10:16 -07002563 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002564 }
Eric Laurent84e9a102010-09-23 16:10:16 -07002565
Glenn Kasten98ec94c2012-01-25 14:28:29 -08002566 sp<Client> client = registerPid_l(pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002567
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002568 // create effect on selected output thread
Eric Laurentde070132010-07-13 04:45:46 -07002569 handle = thread->createEffect_l(client, effectClient, priority, sessionId,
2570 &desc, enabled, &lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002571 if (handle != 0 && id != NULL) {
2572 *id = handle->id();
2573 }
2574 }
2575
2576Exit:
Glenn Kastene53b9ea2012-03-12 16:29:55 -07002577 if (status != NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002578 *status = lStatus;
2579 }
2580 return handle;
2581}
2582
Glenn Kasten72ef00d2012-01-17 11:09:42 -08002583status_t AudioFlinger::moveEffects(int sessionId, audio_io_handle_t srcOutput,
2584 audio_io_handle_t dstOutput)
Eric Laurentde070132010-07-13 04:45:46 -07002585{
Steve Block3856b092011-10-20 11:56:00 +01002586 ALOGV("moveEffects() session %d, srcOutput %d, dstOutput %d",
Eric Laurent59255e42011-07-27 19:49:51 -07002587 sessionId, srcOutput, dstOutput);
Eric Laurentde070132010-07-13 04:45:46 -07002588 Mutex::Autolock _l(mLock);
2589 if (srcOutput == dstOutput) {
Steve Block5ff1dd52012-01-05 23:22:43 +00002590 ALOGW("moveEffects() same dst and src outputs %d", dstOutput);
Eric Laurentde070132010-07-13 04:45:46 -07002591 return NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002592 }
Eric Laurentde070132010-07-13 04:45:46 -07002593 PlaybackThread *srcThread = checkPlaybackThread_l(srcOutput);
2594 if (srcThread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00002595 ALOGW("moveEffects() bad srcOutput %d", srcOutput);
Eric Laurentde070132010-07-13 04:45:46 -07002596 return BAD_VALUE;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002597 }
Eric Laurentde070132010-07-13 04:45:46 -07002598 PlaybackThread *dstThread = checkPlaybackThread_l(dstOutput);
2599 if (dstThread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00002600 ALOGW("moveEffects() bad dstOutput %d", dstOutput);
Eric Laurentde070132010-07-13 04:45:46 -07002601 return BAD_VALUE;
2602 }
2603
2604 Mutex::Autolock _dl(dstThread->mLock);
2605 Mutex::Autolock _sl(srcThread->mLock);
Eric Laurent5baf2af2013-09-12 17:37:00 -07002606 return moveEffectChain_l(sessionId, srcThread, dstThread, false);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002607}
2608
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002609// moveEffectChain_l must be called with both srcThread and dstThread mLocks held
Eric Laurent59255e42011-07-27 19:49:51 -07002610status_t AudioFlinger::moveEffectChain_l(int sessionId,
Eric Laurentde070132010-07-13 04:45:46 -07002611 AudioFlinger::PlaybackThread *srcThread,
Eric Laurent39e94f82010-07-28 01:32:47 -07002612 AudioFlinger::PlaybackThread *dstThread,
2613 bool reRegister)
Eric Laurentde070132010-07-13 04:45:46 -07002614{
Steve Block3856b092011-10-20 11:56:00 +01002615 ALOGV("moveEffectChain_l() session %d from thread %p to thread %p",
Eric Laurent59255e42011-07-27 19:49:51 -07002616 sessionId, srcThread, dstThread);
Eric Laurentde070132010-07-13 04:45:46 -07002617
Eric Laurent59255e42011-07-27 19:49:51 -07002618 sp<EffectChain> chain = srcThread->getEffectChain_l(sessionId);
Eric Laurentde070132010-07-13 04:45:46 -07002619 if (chain == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00002620 ALOGW("moveEffectChain_l() effect chain for session %d not on source thread %p",
Eric Laurent59255e42011-07-27 19:49:51 -07002621 sessionId, srcThread);
Eric Laurentde070132010-07-13 04:45:46 -07002622 return INVALID_OPERATION;
2623 }
2624
Eric Laurent39e94f82010-07-28 01:32:47 -07002625 // remove chain first. This is useful only if reconfiguring effect chain on same output thread,
Eric Laurentde070132010-07-13 04:45:46 -07002626 // so that a new chain is created with correct parameters when first effect is added. This is
Eric Laurentec35a142011-10-05 17:42:25 -07002627 // otherwise unnecessary as removeEffect_l() will remove the chain when last effect is
Eric Laurentde070132010-07-13 04:45:46 -07002628 // removed.
2629 srcThread->removeEffectChain_l(chain);
2630
2631 // transfer all effects one by one so that new effect chain is created on new thread with
2632 // correct buffer sizes and audio parameters and effect engines reconfigured accordingly
Eric Laurent39e94f82010-07-28 01:32:47 -07002633 sp<EffectChain> dstChain;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002634 uint32_t strategy = 0; // prevent compiler warning
Eric Laurentde070132010-07-13 04:45:46 -07002635 sp<EffectModule> effect = chain->getEffectFromId_l(0);
Eric Laurent5baf2af2013-09-12 17:37:00 -07002636 Vector< sp<EffectModule> > removed;
2637 status_t status = NO_ERROR;
Eric Laurentde070132010-07-13 04:45:46 -07002638 while (effect != 0) {
2639 srcThread->removeEffect_l(effect);
Eric Laurent5baf2af2013-09-12 17:37:00 -07002640 removed.add(effect);
2641 status = dstThread->addEffect_l(effect);
2642 if (status != NO_ERROR) {
2643 break;
2644 }
Eric Laurentec35a142011-10-05 17:42:25 -07002645 // removeEffect_l() has stopped the effect if it was active so it must be restarted
2646 if (effect->state() == EffectModule::ACTIVE ||
2647 effect->state() == EffectModule::STOPPING) {
2648 effect->start();
2649 }
Eric Laurent39e94f82010-07-28 01:32:47 -07002650 // if the move request is not received from audio policy manager, the effect must be
2651 // re-registered with the new strategy and output
2652 if (dstChain == 0) {
2653 dstChain = effect->chain().promote();
2654 if (dstChain == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00002655 ALOGW("moveEffectChain_l() cannot get chain from effect %p", effect.get());
Eric Laurent5baf2af2013-09-12 17:37:00 -07002656 status = NO_INIT;
2657 break;
Eric Laurent39e94f82010-07-28 01:32:47 -07002658 }
2659 strategy = dstChain->strategy();
2660 }
2661 if (reRegister) {
2662 AudioSystem::unregisterEffect(effect->id());
2663 AudioSystem::registerEffect(&effect->desc(),
Eric Laurent5baf2af2013-09-12 17:37:00 -07002664 dstThread->id(),
Eric Laurent39e94f82010-07-28 01:32:47 -07002665 strategy,
Eric Laurent59255e42011-07-27 19:49:51 -07002666 sessionId,
Eric Laurent39e94f82010-07-28 01:32:47 -07002667 effect->id());
2668 }
Eric Laurentde070132010-07-13 04:45:46 -07002669 effect = chain->getEffectFromId_l(0);
2670 }
2671
Eric Laurent5baf2af2013-09-12 17:37:00 -07002672 if (status != NO_ERROR) {
2673 for (size_t i = 0; i < removed.size(); i++) {
2674 srcThread->addEffect_l(removed[i]);
2675 if (dstChain != 0 && reRegister) {
2676 AudioSystem::unregisterEffect(removed[i]->id());
2677 AudioSystem::registerEffect(&removed[i]->desc(),
2678 srcThread->id(),
2679 strategy,
2680 sessionId,
2681 removed[i]->id());
2682 }
2683 }
2684 }
2685
2686 return status;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002687}
2688
Eric Laurent5baf2af2013-09-12 17:37:00 -07002689bool AudioFlinger::isNonOffloadableGlobalEffectEnabled_l()
Eric Laurent813e2a72013-08-31 12:59:48 -07002690{
2691 if (mGlobalEffectEnableTime != 0 &&
2692 ((systemTime() - mGlobalEffectEnableTime) < kMinGlobalEffectEnabletimeNs)) {
2693 return true;
2694 }
2695
2696 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
2697 sp<EffectChain> ec =
2698 mPlaybackThreads.valueAt(i)->getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
Eric Laurent5baf2af2013-09-12 17:37:00 -07002699 if (ec != 0 && ec->isNonOffloadableEnabled()) {
Eric Laurent813e2a72013-08-31 12:59:48 -07002700 return true;
2701 }
2702 }
2703 return false;
2704}
2705
Eric Laurent5baf2af2013-09-12 17:37:00 -07002706void AudioFlinger::onNonOffloadableGlobalEffectEnable()
Eric Laurent813e2a72013-08-31 12:59:48 -07002707{
2708 Mutex::Autolock _l(mLock);
2709
2710 mGlobalEffectEnableTime = systemTime();
2711
2712 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
2713 sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
2714 if (t->mType == ThreadBase::OFFLOAD) {
2715 t->invalidateTracks(AUDIO_STREAM_MUSIC);
2716 }
2717 }
2718
2719}
2720
Glenn Kastenda6ef132013-01-10 12:31:01 -08002721struct Entry {
2722#define MAX_NAME 32 // %Y%m%d%H%M%S_%d.wav
2723 char mName[MAX_NAME];
2724};
2725
2726int comparEntry(const void *p1, const void *p2)
2727{
2728 return strcmp(((const Entry *) p1)->mName, ((const Entry *) p2)->mName);
2729}
2730
Glenn Kasten46909e72013-02-26 09:20:22 -08002731#ifdef TEE_SINK
Eric Laurent81784c32012-11-19 14:55:58 -08002732void AudioFlinger::dumpTee(int fd, const sp<NBAIO_Source>& source, audio_io_handle_t id)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002733{
Eric Laurent81784c32012-11-19 14:55:58 -08002734 NBAIO_Source *teeSource = source.get();
2735 if (teeSource != NULL) {
Glenn Kastenda6ef132013-01-10 12:31:01 -08002736 // .wav rotation
2737 // There is a benign race condition if 2 threads call this simultaneously.
2738 // They would both traverse the directory, but the result would simply be
2739 // failures at unlink() which are ignored. It's also unlikely since
2740 // normally dumpsys is only done by bugreport or from the command line.
2741 char teePath[32+256];
2742 strcpy(teePath, "/data/misc/media");
2743 size_t teePathLen = strlen(teePath);
2744 DIR *dir = opendir(teePath);
2745 teePath[teePathLen++] = '/';
2746 if (dir != NULL) {
2747#define MAX_SORT 20 // number of entries to sort
2748#define MAX_KEEP 10 // number of entries to keep
2749 struct Entry entries[MAX_SORT];
2750 size_t entryCount = 0;
2751 while (entryCount < MAX_SORT) {
2752 struct dirent de;
2753 struct dirent *result = NULL;
2754 int rc = readdir_r(dir, &de, &result);
2755 if (rc != 0) {
2756 ALOGW("readdir_r failed %d", rc);
2757 break;
2758 }
2759 if (result == NULL) {
2760 break;
2761 }
2762 if (result != &de) {
2763 ALOGW("readdir_r returned unexpected result %p != %p", result, &de);
2764 break;
2765 }
2766 // ignore non .wav file entries
2767 size_t nameLen = strlen(de.d_name);
2768 if (nameLen <= 4 || nameLen >= MAX_NAME ||
2769 strcmp(&de.d_name[nameLen - 4], ".wav")) {
2770 continue;
2771 }
2772 strcpy(entries[entryCount++].mName, de.d_name);
2773 }
2774 (void) closedir(dir);
2775 if (entryCount > MAX_KEEP) {
2776 qsort(entries, entryCount, sizeof(Entry), comparEntry);
2777 for (size_t i = 0; i < entryCount - MAX_KEEP; ++i) {
2778 strcpy(&teePath[teePathLen], entries[i].mName);
2779 (void) unlink(teePath);
2780 }
2781 }
2782 } else {
2783 if (fd >= 0) {
2784 fdprintf(fd, "unable to rotate tees in %s: %s\n", teePath, strerror(errno));
2785 }
2786 }
Eric Laurent81784c32012-11-19 14:55:58 -08002787 char teeTime[16];
2788 struct timeval tv;
2789 gettimeofday(&tv, NULL);
2790 struct tm tm;
2791 localtime_r(&tv.tv_sec, &tm);
Glenn Kastenda6ef132013-01-10 12:31:01 -08002792 strftime(teeTime, sizeof(teeTime), "%Y%m%d%H%M%S", &tm);
2793 snprintf(&teePath[teePathLen], sizeof(teePath) - teePathLen, "%s_%d.wav", teeTime, id);
2794 // if 2 dumpsys are done within 1 second, and rotation didn't work, then discard 2nd
2795 int teeFd = open(teePath, O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW, S_IRUSR | S_IWUSR);
Eric Laurent81784c32012-11-19 14:55:58 -08002796 if (teeFd >= 0) {
2797 char wavHeader[44];
2798 memcpy(wavHeader,
2799 "RIFF\0\0\0\0WAVEfmt \20\0\0\0\1\0\2\0\104\254\0\0\0\0\0\0\4\0\20\0data\0\0\0\0",
2800 sizeof(wavHeader));
2801 NBAIO_Format format = teeSource->format();
2802 unsigned channelCount = Format_channelCount(format);
2803 ALOG_ASSERT(channelCount <= FCC_2);
2804 uint32_t sampleRate = Format_sampleRate(format);
2805 wavHeader[22] = channelCount; // number of channels
2806 wavHeader[24] = sampleRate; // sample rate
2807 wavHeader[25] = sampleRate >> 8;
2808 wavHeader[32] = channelCount * 2; // block alignment
2809 write(teeFd, wavHeader, sizeof(wavHeader));
2810 size_t total = 0;
2811 bool firstRead = true;
2812 for (;;) {
2813#define TEE_SINK_READ 1024
2814 short buffer[TEE_SINK_READ * FCC_2];
2815 size_t count = TEE_SINK_READ;
2816 ssize_t actual = teeSource->read(buffer, count,
2817 AudioBufferProvider::kInvalidPTS);
2818 bool wasFirstRead = firstRead;
2819 firstRead = false;
2820 if (actual <= 0) {
2821 if (actual == (ssize_t) OVERRUN && wasFirstRead) {
2822 continue;
Eric Laurent59255e42011-07-27 19:49:51 -07002823 }
Eric Laurent81784c32012-11-19 14:55:58 -08002824 break;
Eric Laurent59255e42011-07-27 19:49:51 -07002825 }
Eric Laurent81784c32012-11-19 14:55:58 -08002826 ALOG_ASSERT(actual <= (ssize_t)count);
2827 write(teeFd, buffer, actual * channelCount * sizeof(short));
2828 total += actual;
Eric Laurent59255e42011-07-27 19:49:51 -07002829 }
Eric Laurent81784c32012-11-19 14:55:58 -08002830 lseek(teeFd, (off_t) 4, SEEK_SET);
2831 uint32_t temp = 44 + total * channelCount * sizeof(short) - 8;
2832 write(teeFd, &temp, sizeof(temp));
2833 lseek(teeFd, (off_t) 40, SEEK_SET);
2834 temp = total * channelCount * sizeof(short);
2835 write(teeFd, &temp, sizeof(temp));
2836 close(teeFd);
Glenn Kastenda6ef132013-01-10 12:31:01 -08002837 if (fd >= 0) {
2838 fdprintf(fd, "tee copied to %s\n", teePath);
2839 }
Eric Laurent59255e42011-07-27 19:49:51 -07002840 } else {
Glenn Kastenda6ef132013-01-10 12:31:01 -08002841 if (fd >= 0) {
2842 fdprintf(fd, "unable to create tee %s: %s\n", teePath, strerror(errno));
2843 }
Eric Laurent59255e42011-07-27 19:49:51 -07002844 }
2845 }
2846}
Glenn Kasten46909e72013-02-26 09:20:22 -08002847#endif
Eric Laurent59255e42011-07-27 19:49:51 -07002848
Mathias Agopian65ab4712010-07-14 17:59:35 -07002849status_t AudioFlinger::onTransact(
2850 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
2851{
2852 return BnAudioFlinger::onTransact(code, data, reply, flags);
2853}
2854
Mathias Agopian65ab4712010-07-14 17:59:35 -07002855}; // namespace android