blob: 1f9a1da9845fffcafe175b5d762521609becf77f [file] [log] [blame]
Glenn Kasten99e53b82012-01-19 08:59:58 -08001/*
Mathias Agopian65ab4712010-07-14 17:59:35 -07002**
3** Copyright 2007, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18
19#define LOG_TAG "AudioFlinger"
20//#define LOG_NDEBUG 0
21
Glenn Kasten153b9fe2013-07-15 11:23:36 -070022#include "Configuration.h"
Glenn Kastenda6ef132013-01-10 12:31:01 -080023#include <dirent.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070024#include <math.h>
25#include <signal.h>
26#include <sys/time.h>
27#include <sys/resource.h>
28
Gloria Wang9ee159b2011-02-24 14:51:45 -080029#include <binder/IPCThreadState.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070030#include <binder/IServiceManager.h>
31#include <utils/Log.h>
Glenn Kastend8e6fd32012-05-07 11:07:57 -070032#include <utils/Trace.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070033#include <binder/Parcel.h>
Mikhail Naganova0c91332016-09-19 10:01:12 -070034#include <media/audiohal/DeviceHalInterface.h>
35#include <media/audiohal/DevicesFactoryHalInterface.h>
36#include <media/audiohal/EffectsFactoryHalInterface.h>
Mikhail Naganov00260b52016-10-13 12:54:24 -070037#include <media/AudioParameter.h>
Mikhail Naganov913d06c2016-11-01 12:49:22 -070038#include <media/TypeConverter.h>
Andy Hung35fec5f2016-04-13 14:21:48 -070039#include <memunreachable/memunreachable.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070040#include <utils/String16.h>
41#include <utils/threads.h>
Eric Laurent38ccae22011-03-28 18:37:07 -070042#include <utils/Atomic.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070043
Dima Zavinfce7a472011-04-19 22:30:36 -070044#include <cutils/bitops.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070045#include <cutils/properties.h>
46
Dima Zavin64760242011-05-11 14:15:23 -070047#include <system/audio.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070048
Mathias Agopian65ab4712010-07-14 17:59:35 -070049#include "AudioFlinger.h"
Glenn Kasten44deb052012-02-05 18:09:08 -080050#include "ServiceUtilities.h"
Mathias Agopian65ab4712010-07-14 17:59:35 -070051
Andy Hung6770c6f2015-04-07 13:43:36 -070052#include <media/AudioResamplerPublic.h>
53
Mikhail Naganov9fe94012016-10-14 14:57:40 -070054#include <system/audio_effects/effect_visualizer.h>
55#include <system/audio_effects/effect_ns.h>
56#include <system/audio_effects/effect_aec.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070057
Glenn Kasten3b21c502011-12-15 09:52:39 -080058#include <audio_utils/primitives.h>
59
Eric Laurentfeb0db62011-07-22 09:04:31 -070060#include <powermanager/PowerManager.h>
Glenn Kasten190a46f2012-03-06 11:27:10 -080061
Glenn Kasten9e58b552013-01-18 15:09:48 -080062#include <media/IMediaLogService.h>
Andy Hung07b745e2016-05-23 16:21:07 -070063#include <media/MemoryLeakTrackUtil.h>
Glenn Kastenda6ef132013-01-10 12:31:01 -080064#include <media/nbaio/Pipe.h>
65#include <media/nbaio/PipeReader.h>
Glenn Kasten1ab85ec2013-05-31 09:18:43 -070066#include <media/AudioParameter.h>
Wei Jia3f273d12015-11-24 09:06:49 -080067#include <mediautils/BatteryNotifier.h>
Glenn Kasten4182c4e2013-07-15 14:45:07 -070068#include <private/android_filesystem_config.h>
Glenn Kastenda6ef132013-01-10 12:31:01 -080069
rago3bd1c872016-09-26 12:58:14 -070070//#define BUFLOG_NDEBUG 0
71#include <BufLog.h>
72
Nicolas Rouletfe1e1442017-01-30 12:02:03 -080073#include "TypedLogger.h"
74
Mathias Agopian65ab4712010-07-14 17:59:35 -070075// ----------------------------------------------------------------------------
Mathias Agopian65ab4712010-07-14 17:59:35 -070076
John Grossman1c345192012-03-27 14:00:17 -070077// Note: the following macro is used for extremely verbose logging message. In
78// order to run with ALOG_ASSERT turned on, we need to have LOG_NDEBUG set to
79// 0; but one side effect of this is to turn all LOGV's as well. Some messages
80// are so verbose that we want to suppress them even when we have ALOG_ASSERT
81// turned on. Do not uncomment the #def below unless you really know what you
82// are doing and want to see all of the extremely verbose messages.
83//#define VERY_VERY_VERBOSE_LOGGING
84#ifdef VERY_VERY_VERBOSE_LOGGING
85#define ALOGVV ALOGV
86#else
87#define ALOGVV(a...) do { } while(0)
88#endif
Eric Laurentde070132010-07-13 04:45:46 -070089
Mathias Agopian65ab4712010-07-14 17:59:35 -070090namespace android {
91
Glenn Kastenec1d6b52011-12-12 09:04:45 -080092static const char kDeadlockedString[] = "AudioFlinger may be deadlocked\n";
93static const char kHardwareLockedString[] = "Hardware lock is taken\n";
Eric Laurent021cf962014-05-13 10:18:14 -070094static const char kClientLockedString[] = "Client lock is taken\n";
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -070095static const char kNoEffectsFactory[] = "Effects Factory is absent\n";
Mathias Agopian65ab4712010-07-14 17:59:35 -070096
Glenn Kasten58912562012-04-03 10:45:00 -070097
John Grossman4ff14ba2012-02-08 16:37:41 -080098nsecs_t AudioFlinger::mStandbyTimeInNsecs = kDefaultStandbyTimeInNsecs;
Eric Laurent7cafbb32011-11-22 18:50:29 -080099
Eric Laurent81784c32012-11-19 14:55:58 -0800100uint32_t AudioFlinger::mScreenState;
Glenn Kasten3ed29202012-08-07 15:24:44 -0700101
Eric Laurentfc235202016-12-20 18:48:17 -0800102
Glenn Kasten46909e72013-02-26 09:20:22 -0800103#ifdef TEE_SINK
Glenn Kastenda6ef132013-01-10 12:31:01 -0800104bool AudioFlinger::mTeeSinkInputEnabled = false;
105bool AudioFlinger::mTeeSinkOutputEnabled = false;
106bool AudioFlinger::mTeeSinkTrackEnabled = false;
107
108size_t AudioFlinger::mTeeSinkInputFrames = kTeeSinkInputFramesDefault;
109size_t AudioFlinger::mTeeSinkOutputFrames = kTeeSinkOutputFramesDefault;
110size_t AudioFlinger::mTeeSinkTrackFrames = kTeeSinkTrackFramesDefault;
Glenn Kasten46909e72013-02-26 09:20:22 -0800111#endif
Glenn Kastenda6ef132013-01-10 12:31:01 -0800112
Eric Laurent813e2a72013-08-31 12:59:48 -0700113// In order to avoid invalidating offloaded tracks each time a Visualizer is turned on and off
114// we define a minimum time during which a global effect is considered enabled.
115static const nsecs_t kMinGlobalEffectEnabletimeNs = seconds(7200);
116
Eric Laurentfc235202016-12-20 18:48:17 -0800117Mutex gLock;
118wp<AudioFlinger> gAudioFlinger;
119
Glenn Kasten3ac24a12017-04-10 14:58:47 -0700120// Keep a strong reference to media.log service around forever.
121// The service is within our parent process so it can never die in a way that we could observe.
122// These two variables are const after initialization.
123static sp<IBinder> sMediaLogServiceAsBinder;
124static sp<IMediaLogService> sMediaLogService;
125
126static pthread_once_t sMediaLogOnce = PTHREAD_ONCE_INIT;
127
128static void sMediaLogInit()
129{
130 sMediaLogServiceAsBinder = defaultServiceManager()->getService(String16("media.log"));
131 if (sMediaLogServiceAsBinder != 0) {
132 sMediaLogService = interface_cast<IMediaLogService>(sMediaLogServiceAsBinder);
133 }
134}
135
Mathias Agopian65ab4712010-07-14 17:59:35 -0700136// ----------------------------------------------------------------------------
137
Mikhail Naganov913d06c2016-11-01 12:49:22 -0700138std::string formatToString(audio_format_t format) {
139 std::string result;
140 FormatConverter::toString(format, result);
141 return result;
Marco Nelissenb2208842014-02-07 14:00:50 -0800142}
143
Mathias Agopian65ab4712010-07-14 17:59:35 -0700144// ----------------------------------------------------------------------------
145
146AudioFlinger::AudioFlinger()
147 : BnAudioFlinger(),
Nicolas Rouletdcdfaec2017-02-14 10:18:39 -0800148 mMediaLogNotifier(new AudioFlinger::MediaLogNotifier()),
John Grossman4ff14ba2012-02-08 16:37:41 -0800149 mPrimaryHardwareDev(NULL),
Glenn Kasten9ea65d02014-01-17 10:21:24 -0800150 mAudioHwDevs(NULL),
Glenn Kasten7d6c35b2012-07-02 12:45:10 -0700151 mHardwareStatus(AUDIO_HW_IDLE),
John Grossman4ff14ba2012-02-08 16:37:41 -0800152 mMasterVolume(1.0f),
John Grossman4ff14ba2012-02-08 16:37:41 -0800153 mMasterMute(false),
Glenn Kastend2e67e12016-04-11 08:26:37 -0700154 // mNextUniqueId(AUDIO_UNIQUE_ID_USE_MAX),
John Grossman4ff14ba2012-02-08 16:37:41 -0800155 mMode(AUDIO_MODE_INVALID),
Glenn Kasten4182c4e2013-07-15 14:45:07 -0700156 mBtNrecIsOff(false),
157 mIsLowRamDevice(true),
Eric Laurent813e2a72013-08-31 12:59:48 -0700158 mIsDeviceTypeKnown(false),
Glenn Kasten4ea00a22014-06-02 08:29:22 -0700159 mGlobalEffectEnableTime(0),
Eric Laurent72e3f392015-05-20 14:43:50 -0700160 mSystemReady(false)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700161{
Glenn Kastend2e67e12016-04-11 08:26:37 -0700162 // unsigned instead of audio_unique_id_use_t, because ++ operator is unavailable for enum
163 for (unsigned use = AUDIO_UNIQUE_ID_USE_UNSPECIFIED; use < AUDIO_UNIQUE_ID_USE_MAX; use++) {
164 // zero ID has a special meaning, so unavailable
165 mNextUniqueIds[use] = AUDIO_UNIQUE_ID_USE_MAX;
166 }
167
Glenn Kasten949a9262013-04-16 12:35:20 -0700168 getpid_cached = getpid();
Glenn Kastenae0cff12016-02-24 13:57:49 -0800169 const bool doLog = property_get_bool("ro.test_harness", false);
Glenn Kasten9e58b552013-01-18 15:09:48 -0800170 if (doLog) {
Glenn Kastenb187de12014-12-30 08:18:15 -0800171 mLogMemoryDealer = new MemoryDealer(kLogMemorySize, "LogWriters",
172 MemoryHeapBase::READ_ONLY);
Glenn Kasten3ac24a12017-04-10 14:58:47 -0700173 (void) pthread_once(&sMediaLogOnce, sMediaLogInit);
Glenn Kasten9e58b552013-01-18 15:09:48 -0800174 }
Eric Laurent1c333e22014-05-20 10:48:17 -0700175
Wei Jia3f273d12015-11-24 09:06:49 -0800176 // reset battery stats.
177 // if the audio service has crashed, battery stats could be left
178 // in bad state, reset the state upon service start.
179 BatteryNotifier::getInstance().noteResetAudio();
180
Mikhail Naganove4f1f632016-08-31 11:35:10 -0700181 mDevicesFactoryHal = DevicesFactoryHalInterface::create();
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700182 mEffectsFactoryHal = EffectsFactoryHalInterface::create();
183
Nicolas Rouletdcdfaec2017-02-14 10:18:39 -0800184 mMediaLogNotifier->run("MediaLogNotifier");
185
Glenn Kasten46909e72013-02-26 09:20:22 -0800186#ifdef TEE_SINK
Glenn Kasten9a003992016-02-23 15:24:34 -0800187 char value[PROPERTY_VALUE_MAX];
Glenn Kastenda6ef132013-01-10 12:31:01 -0800188 (void) property_get("ro.debuggable", value, "0");
189 int debuggable = atoi(value);
190 int teeEnabled = 0;
191 if (debuggable) {
192 (void) property_get("af.tee", value, "0");
193 teeEnabled = atoi(value);
194 }
Glenn Kastenf66b4222014-02-20 10:23:28 -0800195 // FIXME symbolic constants here
Glenn Kasten6e2ebe92013-08-13 09:14:51 -0700196 if (teeEnabled & 1) {
Glenn Kastenda6ef132013-01-10 12:31:01 -0800197 mTeeSinkInputEnabled = true;
Glenn Kasten6e2ebe92013-08-13 09:14:51 -0700198 }
199 if (teeEnabled & 2) {
Glenn Kastenda6ef132013-01-10 12:31:01 -0800200 mTeeSinkOutputEnabled = true;
Glenn Kasten6e2ebe92013-08-13 09:14:51 -0700201 }
202 if (teeEnabled & 4) {
Glenn Kastenda6ef132013-01-10 12:31:01 -0800203 mTeeSinkTrackEnabled = true;
Glenn Kasten6e2ebe92013-08-13 09:14:51 -0700204 }
Glenn Kasten46909e72013-02-26 09:20:22 -0800205#endif
Dima Zavin5a61d2f2011-04-19 19:04:32 -0700206}
207
208void AudioFlinger::onFirstRef()
209{
Eric Laurent93575202011-01-18 18:39:02 -0800210 Mutex::Autolock _l(mLock);
211
Dima Zavin799a70e2011-04-18 16:57:27 -0700212 /* TODO: move all this work into an Init() function */
John Grossman4ff14ba2012-02-08 16:37:41 -0800213 char val_str[PROPERTY_VALUE_MAX] = { 0 };
214 if (property_get("ro.audio.flinger_standbytime_ms", val_str, NULL) >= 0) {
215 uint32_t int_val;
216 if (1 == sscanf(val_str, "%u", &int_val)) {
217 mStandbyTimeInNsecs = milliseconds(int_val);
218 ALOGI("Using %u mSec as standby time.", int_val);
219 } else {
220 mStandbyTimeInNsecs = kDefaultStandbyTimeInNsecs;
221 ALOGI("Using default %u mSec as standby time.",
222 (uint32_t)(mStandbyTimeInNsecs / 1000000));
223 }
224 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700225
Eric Laurent1c333e22014-05-20 10:48:17 -0700226 mPatchPanel = new PatchPanel(this);
Andy Hungdeb03352016-08-29 14:40:14 -0700227
Eric Laurenta4c5a552012-03-29 10:12:40 -0700228 mMode = AUDIO_MODE_NORMAL;
Eric Laurentfc235202016-12-20 18:48:17 -0800229
230 gAudioFlinger = this;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700231}
232
233AudioFlinger::~AudioFlinger()
234{
235 while (!mRecordThreads.isEmpty()) {
Glenn Kastenc3ae93f2012-07-30 10:59:30 -0700236 // closeInput_nonvirtual() will remove specified entry from mRecordThreads
Glenn Kastend96c5722012-04-25 13:44:49 -0700237 closeInput_nonvirtual(mRecordThreads.keyAt(0));
Mathias Agopian65ab4712010-07-14 17:59:35 -0700238 }
239 while (!mPlaybackThreads.isEmpty()) {
Glenn Kastenc3ae93f2012-07-30 10:59:30 -0700240 // closeOutput_nonvirtual() will remove specified entry from mPlaybackThreads
Glenn Kastend96c5722012-04-25 13:44:49 -0700241 closeOutput_nonvirtual(mPlaybackThreads.keyAt(0));
Mathias Agopian65ab4712010-07-14 17:59:35 -0700242 }
Dima Zavin799a70e2011-04-18 16:57:27 -0700243
Glenn Kasten2b213bc2012-02-02 14:05:20 -0800244 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
245 // no mHardwareLock needed, as there are no other references to this
Eric Laurenta4c5a552012-03-29 10:12:40 -0700246 delete mAudioHwDevs.valueAt(i);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700247 }
Glenn Kasten481fb672013-09-30 14:39:28 -0700248
249 // Tell media.log service about any old writers that still need to be unregistered
Glenn Kasten3ac24a12017-04-10 14:58:47 -0700250 if (sMediaLogService != 0) {
251 for (size_t count = mUnregisteredWriters.size(); count > 0; count--) {
252 sp<IMemory> iMemory(mUnregisteredWriters.top()->getIMemory());
253 mUnregisteredWriters.pop();
254 sMediaLogService->unregisterWriter(iMemory);
Glenn Kasten481fb672013-09-30 14:39:28 -0700255 }
256 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700257}
258
Eric Laurentfc235202016-12-20 18:48:17 -0800259//static
Eric Laurent6acd1d42017-01-04 14:23:29 -0800260__attribute__ ((visibility ("default")))
Eric Laurentfc235202016-12-20 18:48:17 -0800261status_t MmapStreamInterface::openMmapStream(MmapStreamInterface::stream_direction_t direction,
262 const audio_attributes_t *attr,
263 audio_config_base_t *config,
264 const MmapStreamInterface::Client& client,
265 audio_port_handle_t *deviceId,
266 const sp<MmapStreamCallback>& callback,
267 sp<MmapStreamInterface>& interface)
268{
269 sp<AudioFlinger> af;
270 {
271 Mutex::Autolock _l(gLock);
272 af = gAudioFlinger.promote();
273 }
274 status_t ret = NO_INIT;
275 if (af != 0) {
276 ret = af->openMmapStream(
277 direction, attr, config, client, deviceId, callback, interface);
278 }
279 return ret;
280}
281
Eric Laurent6acd1d42017-01-04 14:23:29 -0800282status_t AudioFlinger::openMmapStream(MmapStreamInterface::stream_direction_t direction,
283 const audio_attributes_t *attr,
284 audio_config_base_t *config,
285 const MmapStreamInterface::Client& client,
286 audio_port_handle_t *deviceId,
287 const sp<MmapStreamCallback>& callback,
288 sp<MmapStreamInterface>& interface)
Eric Laurentfc235202016-12-20 18:48:17 -0800289{
290 status_t ret = initCheck();
291 if (ret != NO_ERROR) {
292 return ret;
293 }
294
Eric Laurent6acd1d42017-01-04 14:23:29 -0800295 audio_session_t sessionId = (audio_session_t) newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
296 audio_stream_type_t streamType = AUDIO_STREAM_DEFAULT;
297 audio_io_handle_t io;
298 audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;
299 if (direction == MmapStreamInterface::DIRECTION_OUTPUT) {
300 audio_config_t fullConfig = AUDIO_CONFIG_INITIALIZER;
301 fullConfig.sample_rate = config->sample_rate;
302 fullConfig.channel_mask = config->channel_mask;
303 fullConfig.format = config->format;
304 ret = AudioSystem::getOutputForAttr(attr, &io,
305 sessionId,
306 &streamType, client.clientUid,
307 &fullConfig,
Glenn Kastend3bb6452016-12-05 18:14:37 -0800308 (audio_output_flags_t)(AUDIO_OUTPUT_FLAG_MMAP_NOIRQ |
309 AUDIO_OUTPUT_FLAG_DIRECT),
Eric Laurent6acd1d42017-01-04 14:23:29 -0800310 *deviceId, &portId);
311 } else {
312 ret = AudioSystem::getInputForAttr(attr, &io,
313 sessionId,
314 client.clientPid,
315 client.clientUid,
316 config,
317 AUDIO_INPUT_FLAG_MMAP_NOIRQ, *deviceId, &portId);
318 }
319 if (ret != NO_ERROR) {
320 return ret;
321 }
322
323 // at this stage, a MmapThread was created when openOutput() or openInput() was called by
324 // audio policy manager and we can retrieve it
325 sp<MmapThread> thread = mMmapThreads.valueFor(io);
326 if (thread != 0) {
327 interface = new MmapThreadHandle(thread);
328 thread->configure(attr, streamType, sessionId, callback, portId);
329 } else {
330 ret = NO_INIT;
331 }
332
333 ALOGV("%s done status %d portId %d", __FUNCTION__, ret, portId);
334
Eric Laurentfc235202016-12-20 18:48:17 -0800335 return ret;
336}
337
Eric Laurenta4c5a552012-03-29 10:12:40 -0700338static const char * const audio_interfaces[] = {
339 AUDIO_HARDWARE_MODULE_ID_PRIMARY,
340 AUDIO_HARDWARE_MODULE_ID_A2DP,
341 AUDIO_HARDWARE_MODULE_ID_USB,
342};
343#define ARRAY_SIZE(x) (sizeof((x))/sizeof(((x)[0])))
344
Phil Burk062e67a2015-02-11 13:40:50 -0800345AudioHwDevice* AudioFlinger::findSuitableHwDev_l(
John Grossmanee578c02012-07-23 17:05:46 -0700346 audio_module_handle_t module,
347 audio_devices_t devices)
Dima Zavin799a70e2011-04-18 16:57:27 -0700348{
Eric Laurenta4c5a552012-03-29 10:12:40 -0700349 // if module is 0, the request comes from an old policy manager and we should load
350 // well known modules
351 if (module == 0) {
352 ALOGW("findSuitableHwDev_l() loading well know audio hw modules");
353 for (size_t i = 0; i < ARRAY_SIZE(audio_interfaces); i++) {
354 loadHwModule_l(audio_interfaces[i]);
355 }
Eric Laurentf1c04f92012-08-28 14:26:53 -0700356 // then try to find a module supporting the requested device.
357 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
358 AudioHwDevice *audioHwDevice = mAudioHwDevs.valueAt(i);
Mikhail Naganove4f1f632016-08-31 11:35:10 -0700359 sp<DeviceHalInterface> dev = audioHwDevice->hwDevice();
360 uint32_t supportedDevices;
361 if (dev->getSupportedDevices(&supportedDevices) == OK &&
362 (supportedDevices & devices) == devices) {
Eric Laurentf1c04f92012-08-28 14:26:53 -0700363 return audioHwDevice;
Mikhail Naganove4f1f632016-08-31 11:35:10 -0700364 }
Eric Laurentf1c04f92012-08-28 14:26:53 -0700365 }
Eric Laurenta4c5a552012-03-29 10:12:40 -0700366 } else {
367 // check a match for the requested module handle
John Grossmanee578c02012-07-23 17:05:46 -0700368 AudioHwDevice *audioHwDevice = mAudioHwDevs.valueFor(module);
369 if (audioHwDevice != NULL) {
370 return audioHwDevice;
Eric Laurenta4c5a552012-03-29 10:12:40 -0700371 }
372 }
Eric Laurenta4c5a552012-03-29 10:12:40 -0700373
Dima Zavin799a70e2011-04-18 16:57:27 -0700374 return NULL;
375}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700376
Glenn Kasten0f11b512014-01-31 16:18:54 -0800377void AudioFlinger::dumpClients(int fd, const Vector<String16>& args __unused)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700378{
379 const size_t SIZE = 256;
380 char buffer[SIZE];
381 String8 result;
382
383 result.append("Clients:\n");
384 for (size_t i = 0; i < mClients.size(); ++i) {
Glenn Kasten77c11192012-01-25 14:27:41 -0800385 sp<Client> client = mClients.valueAt(i).promote();
386 if (client != 0) {
387 snprintf(buffer, SIZE, " pid: %d\n", client->pid());
388 result.append(buffer);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700389 }
390 }
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700391
Eric Laurentd1b28d42013-09-18 18:47:13 -0700392 result.append("Notification Clients:\n");
393 for (size_t i = 0; i < mNotificationClients.size(); ++i) {
394 snprintf(buffer, SIZE, " pid: %d\n", mNotificationClients.keyAt(i));
395 result.append(buffer);
396 }
397
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700398 result.append("Global session refs:\n");
Marco Nelissenb2208842014-02-07 14:00:50 -0800399 result.append(" session pid count\n");
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700400 for (size_t i = 0; i < mAudioSessionRefs.size(); i++) {
401 AudioSessionRef *r = mAudioSessionRefs[i];
Marco Nelissenb2208842014-02-07 14:00:50 -0800402 snprintf(buffer, SIZE, " %7d %5d %5d\n", r->mSessionid, r->mPid, r->mCnt);
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700403 result.append(buffer);
404 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700405 write(fd, result.string(), result.size());
Mathias Agopian65ab4712010-07-14 17:59:35 -0700406}
407
408
Glenn Kasten0f11b512014-01-31 16:18:54 -0800409void AudioFlinger::dumpInternals(int fd, const Vector<String16>& args __unused)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700410{
411 const size_t SIZE = 256;
412 char buffer[SIZE];
413 String8 result;
Glenn Kastena4454b42012-01-04 11:02:33 -0800414 hardware_call_state hardwareStatus = mHardwareStatus;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700415
John Grossman4ff14ba2012-02-08 16:37:41 -0800416 snprintf(buffer, SIZE, "Hardware status: %d\n"
417 "Standby Time mSec: %u\n",
418 hardwareStatus,
419 (uint32_t)(mStandbyTimeInNsecs / 1000000));
Mathias Agopian65ab4712010-07-14 17:59:35 -0700420 result.append(buffer);
421 write(fd, result.string(), result.size());
Mathias Agopian65ab4712010-07-14 17:59:35 -0700422}
423
Glenn Kasten0f11b512014-01-31 16:18:54 -0800424void AudioFlinger::dumpPermissionDenial(int fd, const Vector<String16>& args __unused)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700425{
426 const size_t SIZE = 256;
427 char buffer[SIZE];
428 String8 result;
429 snprintf(buffer, SIZE, "Permission Denial: "
430 "can't dump AudioFlinger from pid=%d, uid=%d\n",
431 IPCThreadState::self()->getCallingPid(),
432 IPCThreadState::self()->getCallingUid());
433 result.append(buffer);
434 write(fd, result.string(), result.size());
Mathias Agopian65ab4712010-07-14 17:59:35 -0700435}
436
Eric Laurent81784c32012-11-19 14:55:58 -0800437bool AudioFlinger::dumpTryLock(Mutex& mutex)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700438{
439 bool locked = false;
440 for (int i = 0; i < kDumpLockRetries; ++i) {
441 if (mutex.tryLock() == NO_ERROR) {
442 locked = true;
443 break;
444 }
Glenn Kasten7dede872011-12-13 11:04:14 -0800445 usleep(kDumpLockSleepUs);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700446 }
447 return locked;
448}
449
450status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
451{
Glenn Kasten44deb052012-02-05 18:09:08 -0800452 if (!dumpAllowed()) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700453 dumpPermissionDenial(fd, args);
454 } else {
455 // get state of hardware lock
Eric Laurent81784c32012-11-19 14:55:58 -0800456 bool hardwareLocked = dumpTryLock(mHardwareLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700457 if (!hardwareLocked) {
458 String8 result(kHardwareLockedString);
459 write(fd, result.string(), result.size());
460 } else {
461 mHardwareLock.unlock();
462 }
463
Eric Laurent81784c32012-11-19 14:55:58 -0800464 bool locked = dumpTryLock(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700465
466 // failed to lock - AudioFlinger is probably deadlocked
467 if (!locked) {
468 String8 result(kDeadlockedString);
469 write(fd, result.string(), result.size());
470 }
471
Eric Laurent021cf962014-05-13 10:18:14 -0700472 bool clientLocked = dumpTryLock(mClientLock);
473 if (!clientLocked) {
474 String8 result(kClientLockedString);
475 write(fd, result.string(), result.size());
476 }
Marco Nelissend89eadd2014-10-07 13:28:44 -0700477
Mikhail Naganov1dc98672016-08-18 17:50:29 -0700478 if (mEffectsFactoryHal != 0) {
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700479 mEffectsFactoryHal->dumpEffects(fd);
480 } else {
481 String8 result(kNoEffectsFactory);
482 write(fd, result.string(), result.size());
483 }
Marco Nelissend89eadd2014-10-07 13:28:44 -0700484
Mathias Agopian65ab4712010-07-14 17:59:35 -0700485 dumpClients(fd, args);
Eric Laurent021cf962014-05-13 10:18:14 -0700486 if (clientLocked) {
487 mClientLock.unlock();
488 }
489
Mathias Agopian65ab4712010-07-14 17:59:35 -0700490 dumpInternals(fd, args);
491
492 // dump playback threads
493 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
494 mPlaybackThreads.valueAt(i)->dump(fd, args);
495 }
496
497 // dump record threads
498 for (size_t i = 0; i < mRecordThreads.size(); i++) {
499 mRecordThreads.valueAt(i)->dump(fd, args);
500 }
501
Eric Laurent6acd1d42017-01-04 14:23:29 -0800502 // dump mmap threads
503 for (size_t i = 0; i < mMmapThreads.size(); i++) {
504 mMmapThreads.valueAt(i)->dump(fd, args);
505 }
506
Eric Laurentaaa44472014-09-12 17:41:50 -0700507 // dump orphan effect chains
508 if (mOrphanEffectChains.size() != 0) {
509 write(fd, " Orphan Effect Chains\n", strlen(" Orphan Effect Chains\n"));
510 for (size_t i = 0; i < mOrphanEffectChains.size(); i++) {
511 mOrphanEffectChains.valueAt(i)->dump(fd, args);
512 }
513 }
Dima Zavin799a70e2011-04-18 16:57:27 -0700514 // dump all hardware devs
515 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
Mikhail Naganove4f1f632016-08-31 11:35:10 -0700516 sp<DeviceHalInterface> dev = mAudioHwDevs.valueAt(i)->hwDevice();
517 dev->dump(fd);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700518 }
Glenn Kastend06785b2012-09-30 12:29:28 -0700519
Glenn Kasten46909e72013-02-26 09:20:22 -0800520#ifdef TEE_SINK
Glenn Kastend06785b2012-09-30 12:29:28 -0700521 // dump the serially shared record tee sink
522 if (mRecordTeeSource != 0) {
523 dumpTee(fd, mRecordTeeSource);
524 }
Glenn Kasten46909e72013-02-26 09:20:22 -0800525#endif
Glenn Kastend06785b2012-09-30 12:29:28 -0700526
rago3bd1c872016-09-26 12:58:14 -0700527 BUFLOG_RESET;
528
Glenn Kastend65d73c2012-06-22 17:21:07 -0700529 if (locked) {
530 mLock.unlock();
531 }
Glenn Kasten9e58b552013-01-18 15:09:48 -0800532
533 // append a copy of media.log here by forwarding fd to it, but don't attempt
534 // to lookup the service if it's not running, as it will block for a second
Glenn Kasten3ac24a12017-04-10 14:58:47 -0700535 if (sMediaLogServiceAsBinder != 0) {
536 dprintf(fd, "\nmedia.log:\n");
537 Vector<String16> args;
538 sMediaLogServiceAsBinder->dump(fd, args);
Glenn Kasten9e58b552013-01-18 15:09:48 -0800539 }
Andy Hung35fec5f2016-04-13 14:21:48 -0700540
541 // check for optional arguments
Andy Hung07b745e2016-05-23 16:21:07 -0700542 bool dumpMem = false;
Andy Hung35fec5f2016-04-13 14:21:48 -0700543 bool unreachableMemory = false;
544 for (const auto &arg : args) {
Andy Hung07b745e2016-05-23 16:21:07 -0700545 if (arg == String16("-m")) {
546 dumpMem = true;
547 } else if (arg == String16("--unreachable")) {
Andy Hung35fec5f2016-04-13 14:21:48 -0700548 unreachableMemory = true;
549 }
550 }
551
Andy Hung07b745e2016-05-23 16:21:07 -0700552 if (dumpMem) {
553 dprintf(fd, "\nDumping memory:\n");
554 std::string s = dumpMemoryAddresses(100 /* limit */);
555 write(fd, s.c_str(), s.size());
556 }
Andy Hung35fec5f2016-04-13 14:21:48 -0700557 if (unreachableMemory) {
558 dprintf(fd, "\nDumping unreachable memory:\n");
559 // TODO - should limit be an argument parameter?
Andy Hung07b745e2016-05-23 16:21:07 -0700560 std::string s = GetUnreachableMemoryString(true /* contents */, 100 /* limit */);
Andy Hung35fec5f2016-04-13 14:21:48 -0700561 write(fd, s.c_str(), s.size());
562 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700563 }
564 return NO_ERROR;
565}
566
Eric Laurent021cf962014-05-13 10:18:14 -0700567sp<AudioFlinger::Client> AudioFlinger::registerPid(pid_t pid)
Glenn Kasten98ec94c2012-01-25 14:28:29 -0800568{
Eric Laurent021cf962014-05-13 10:18:14 -0700569 Mutex::Autolock _cl(mClientLock);
Glenn Kasten98ec94c2012-01-25 14:28:29 -0800570 // If pid is already in the mClients wp<> map, then use that entry
571 // (for which promote() is always != 0), otherwise create a new entry and Client.
572 sp<Client> client = mClients.valueFor(pid).promote();
573 if (client == 0) {
574 client = new Client(this, pid);
575 mClients.add(pid, client);
576 }
577
578 return client;
579}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700580
Glenn Kasten9e58b552013-01-18 15:09:48 -0800581sp<NBLog::Writer> AudioFlinger::newWriter_l(size_t size, const char *name)
582{
Glenn Kasten3ac24a12017-04-10 14:58:47 -0700583 // If there is no memory allocated for logs, return a dummy writer that does nothing.
584 // Similarly if we can't contact the media.log service, also return a dummy writer.
585 if (mLogMemoryDealer == 0 || sMediaLogService == 0) {
Glenn Kasten9e58b552013-01-18 15:09:48 -0800586 return new NBLog::Writer();
587 }
Glenn Kasten481fb672013-09-30 14:39:28 -0700588 sp<IMemory> shared = mLogMemoryDealer->allocate(NBLog::Timeline::sharedSize(size));
589 // If allocation fails, consult the vector of previously unregistered writers
590 // and garbage-collect one or more them until an allocation succeeds
591 if (shared == 0) {
592 Mutex::Autolock _l(mUnregisteredWritersLock);
593 for (size_t count = mUnregisteredWriters.size(); count > 0; count--) {
594 {
595 // Pick the oldest stale writer to garbage-collect
596 sp<IMemory> iMemory(mUnregisteredWriters[0]->getIMemory());
597 mUnregisteredWriters.removeAt(0);
Glenn Kasten3ac24a12017-04-10 14:58:47 -0700598 sMediaLogService->unregisterWriter(iMemory);
Glenn Kasten481fb672013-09-30 14:39:28 -0700599 // Now the media.log remote reference to IMemory is gone. When our last local
600 // reference to IMemory also drops to zero at end of this block,
601 // the IMemory destructor will deallocate the region from mLogMemoryDealer.
602 }
603 // Re-attempt the allocation
604 shared = mLogMemoryDealer->allocate(NBLog::Timeline::sharedSize(size));
605 if (shared != 0) {
606 goto success;
607 }
608 }
609 // Even after garbage-collecting all old writers, there is still not enough memory,
610 // so return a dummy writer
611 return new NBLog::Writer();
612 }
613success:
Glenn Kasten535e1612016-12-05 12:19:36 -0800614 NBLog::Shared *sharedRawPtr = (NBLog::Shared *) shared->pointer();
615 new((void *) sharedRawPtr) NBLog::Shared(); // placement new here, but the corresponding
616 // explicit destructor not needed since it is POD
Glenn Kasten3ac24a12017-04-10 14:58:47 -0700617 sMediaLogService->registerWriter(shared, size, name);
Glenn Kasten535e1612016-12-05 12:19:36 -0800618 return new NBLog::Writer(shared, size);
Glenn Kasten9e58b552013-01-18 15:09:48 -0800619}
620
621void AudioFlinger::unregisterWriter(const sp<NBLog::Writer>& writer)
622{
Glenn Kasten685ef092013-02-04 08:15:34 -0800623 if (writer == 0) {
624 return;
625 }
Glenn Kasten9e58b552013-01-18 15:09:48 -0800626 sp<IMemory> iMemory(writer->getIMemory());
627 if (iMemory == 0) {
628 return;
629 }
Glenn Kasten481fb672013-09-30 14:39:28 -0700630 // Rather than removing the writer immediately, append it to a queue of old writers to
631 // be garbage-collected later. This allows us to continue to view old logs for a while.
632 Mutex::Autolock _l(mUnregisteredWritersLock);
633 mUnregisteredWriters.push(writer);
Glenn Kasten9e58b552013-01-18 15:09:48 -0800634}
635
Mathias Agopian65ab4712010-07-14 17:59:35 -0700636// IAudioFlinger interface
637
638
639sp<IAudioTrack> AudioFlinger::createTrack(
Glenn Kastenfff6d712012-01-12 16:38:12 -0800640 audio_stream_type_t streamType,
Mathias Agopian65ab4712010-07-14 17:59:35 -0700641 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -0800642 audio_format_t format,
Glenn Kasten254af182012-07-03 14:59:05 -0700643 audio_channel_mask_t channelMask,
Glenn Kasten74935e42013-12-19 08:56:45 -0800644 size_t *frameCount,
Eric Laurent05067782016-06-01 18:27:28 -0700645 audio_output_flags_t *flags,
Mathias Agopian65ab4712010-07-14 17:59:35 -0700646 const sp<IMemory>& sharedBuffer,
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800647 audio_io_handle_t output,
Haynes Mathew George9ea77cd2016-04-06 17:07:48 -0700648 pid_t pid,
Glenn Kasten3acbd052012-02-28 10:39:56 -0800649 pid_t tid,
Glenn Kastend848eb42016-03-08 13:42:11 -0800650 audio_session_t *sessionId,
Marco Nelissen462fd2f2013-01-14 14:12:05 -0800651 int clientUid,
Eric Laurent20b9ef02016-12-05 11:03:16 -0800652 status_t *status,
653 audio_port_handle_t portId)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700654{
655 sp<PlaybackThread::Track> track;
656 sp<TrackHandle> trackHandle;
657 sp<Client> client;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700658 status_t lStatus;
Glenn Kastend848eb42016-03-08 13:42:11 -0800659 audio_session_t lSessionId;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700660
Haynes Mathew George9ea77cd2016-04-06 17:07:48 -0700661 const uid_t callingUid = IPCThreadState::self()->getCallingUid();
662 if (pid == -1 || !isTrustedCallingUid(callingUid)) {
663 const pid_t callingPid = IPCThreadState::self()->getCallingPid();
664 ALOGW_IF(pid != -1 && pid != callingPid,
665 "%s uid %d pid %d tried to pass itself off as pid %d",
666 __func__, callingUid, callingPid, pid);
667 pid = callingPid;
668 }
669
Glenn Kasten263709e2012-01-06 08:40:01 -0800670 // client AudioTrack::set already implements AUDIO_STREAM_DEFAULT => AUDIO_STREAM_MUSIC,
671 // but if someone uses binder directly they could bypass that and cause us to crash
672 if (uint32_t(streamType) >= AUDIO_STREAM_CNT) {
Steve Block29357bc2012-01-06 19:20:56 +0000673 ALOGE("createTrack() invalid stream type %d", streamType);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700674 lStatus = BAD_VALUE;
675 goto Exit;
676 }
677
Glenn Kasten53b5d092014-02-05 10:00:23 -0800678 // further sample rate checks are performed by createTrack_l() depending on the thread type
679 if (sampleRate == 0) {
680 ALOGE("createTrack() invalid sample rate %u", sampleRate);
681 lStatus = BAD_VALUE;
682 goto Exit;
683 }
684
685 // further channel mask checks are performed by createTrack_l() depending on the thread type
686 if (!audio_is_output_channel(channelMask)) {
687 ALOGE("createTrack() invalid channel mask %#x", channelMask);
688 lStatus = BAD_VALUE;
689 goto Exit;
690 }
691
Glenn Kastenc4b88a82014-04-30 16:54:30 -0700692 // further format checks are performed by createTrack_l() depending on the thread type
693 if (!audio_is_valid_format(format)) {
Glenn Kastencac3daa2014-02-07 09:47:14 -0800694 ALOGE("createTrack() invalid format %#x", format);
Glenn Kasten60a83922012-06-21 12:56:37 -0700695 lStatus = BAD_VALUE;
696 goto Exit;
697 }
698
Glenn Kasten663c2242013-09-24 11:52:37 -0700699 if (sharedBuffer != 0 && sharedBuffer->pointer() == NULL) {
700 ALOGE("createTrack() sharedBuffer is non-0 but has NULL pointer()");
701 lStatus = BAD_VALUE;
702 goto Exit;
703 }
704
Mathias Agopian65ab4712010-07-14 17:59:35 -0700705 {
706 Mutex::Autolock _l(mLock);
707 PlaybackThread *thread = checkPlaybackThread_l(output);
708 if (thread == NULL) {
Glenn Kastenc9b2e202013-02-26 11:32:32 -0800709 ALOGE("no playback thread found for output handle %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700710 lStatus = BAD_VALUE;
711 goto Exit;
712 }
713
Eric Laurent021cf962014-05-13 10:18:14 -0700714 client = registerPid(pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700715
Glenn Kastene848bd92014-03-13 15:00:32 -0700716 PlaybackThread *effectThread = NULL;
Glenn Kastenaea7ea02013-06-26 09:25:47 -0700717 if (sessionId != NULL && *sessionId != AUDIO_SESSION_ALLOCATE) {
Glenn Kasteneeecb982016-02-26 10:44:04 -0800718 if (audio_unique_id_get_use(*sessionId) != AUDIO_UNIQUE_ID_USE_SESSION) {
719 ALOGE("createTrack() invalid session ID %d", *sessionId);
720 lStatus = BAD_VALUE;
721 goto Exit;
722 }
Glenn Kasten570f6332014-03-13 15:01:06 -0700723 lSessionId = *sessionId;
Eric Laurentf436fdc2012-05-24 11:07:14 -0700724 // check if an effect chain with the same session ID is present on another
725 // output thread and move it here.
Eric Laurentde070132010-07-13 04:45:46 -0700726 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurent39e94f82010-07-28 01:32:47 -0700727 sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
728 if (mPlaybackThreads.keyAt(i) != output) {
Glenn Kasten570f6332014-03-13 15:01:06 -0700729 uint32_t sessions = t->hasAudioSession(lSessionId);
Eric Laurent4c415062016-06-17 16:14:16 -0700730 if (sessions & ThreadBase::EFFECT_SESSION) {
Eric Laurent39e94f82010-07-28 01:32:47 -0700731 effectThread = t.get();
Eric Laurentf436fdc2012-05-24 11:07:14 -0700732 break;
Eric Laurent39e94f82010-07-28 01:32:47 -0700733 }
Eric Laurentde070132010-07-13 04:45:46 -0700734 }
735 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700736 } else {
Eric Laurentde070132010-07-13 04:45:46 -0700737 // if no audio session id is provided, create one here
Glenn Kastend848eb42016-03-08 13:42:11 -0800738 lSessionId = (audio_session_t) nextUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700739 if (sessionId != NULL) {
740 *sessionId = lSessionId;
741 }
742 }
Steve Block3856b092011-10-20 11:56:00 +0100743 ALOGV("createTrack() lSessionId: %d", lSessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700744
745 track = thread->createTrack_l(client, streamType, sampleRate, format,
Eric Laurent20b9ef02016-12-05 11:03:16 -0800746 channelMask, frameCount, sharedBuffer, lSessionId, flags, tid,
747 clientUid, &lStatus, portId);
Haynes Mathew George03e9e832013-12-13 15:40:13 -0800748 LOG_ALWAYS_FATAL_IF((lStatus == NO_ERROR) && (track == 0));
Glenn Kasten2fc14732013-08-05 14:58:14 -0700749 // we don't abort yet if lStatus != NO_ERROR; there is still work to be done regardless
Eric Laurent39e94f82010-07-28 01:32:47 -0700750
751 // move effect chain to this output thread if an effect on same session was waiting
752 // for a track to be created
753 if (lStatus == NO_ERROR && effectThread != NULL) {
Glenn Kasten2fc14732013-08-05 14:58:14 -0700754 // no risk of deadlock because AudioFlinger::mLock is held
Eric Laurent39e94f82010-07-28 01:32:47 -0700755 Mutex::Autolock _dl(thread->mLock);
756 Mutex::Autolock _sl(effectThread->mLock);
757 moveEffectChain_l(lSessionId, effectThread, thread, true);
758 }
Eric Laurenta011e352012-03-29 15:51:43 -0700759
760 // Look for sync events awaiting for a session to be used.
Mark Salyzyn3ab368e2014-04-15 14:55:53 -0700761 for (size_t i = 0; i < mPendingSyncEvents.size(); i++) {
Eric Laurenta011e352012-03-29 15:51:43 -0700762 if (mPendingSyncEvents[i]->triggerSession() == lSessionId) {
763 if (thread->isValidSyncEvent(mPendingSyncEvents[i])) {
Eric Laurent29864602012-05-08 18:57:51 -0700764 if (lStatus == NO_ERROR) {
Glenn Kastend23eedc2012-08-02 13:35:47 -0700765 (void) track->setSyncEvent(mPendingSyncEvents[i]);
Eric Laurent29864602012-05-08 18:57:51 -0700766 } else {
767 mPendingSyncEvents[i]->cancel();
768 }
Eric Laurenta011e352012-03-29 15:51:43 -0700769 mPendingSyncEvents.removeAt(i);
770 i--;
771 }
772 }
773 }
Glenn Kastene198c362013-08-13 09:13:36 -0700774
Glenn Kastend848eb42016-03-08 13:42:11 -0800775 setAudioHwSyncForSession_l(thread, lSessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700776 }
Glenn Kastene198c362013-08-13 09:13:36 -0700777
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700778 if (lStatus != NO_ERROR) {
779 // remove local strong reference to Client before deleting the Track so that the
Eric Laurent021cf962014-05-13 10:18:14 -0700780 // Client destructor is called by the TrackBase destructor with mClientLock held
Eric Laurentfe1a94e2014-05-26 16:03:08 -0700781 // Don't hold mClientLock when releasing the reference on the track as the
782 // destructor will acquire it.
783 {
784 Mutex::Autolock _cl(mClientLock);
785 client.clear();
786 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700787 track.clear();
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700788 goto Exit;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700789 }
790
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700791 // return handle to client
792 trackHandle = new TrackHandle(track);
793
Mathias Agopian65ab4712010-07-14 17:59:35 -0700794Exit:
Glenn Kasten9156ef32013-08-06 15:39:08 -0700795 *status = lStatus;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700796 return trackHandle;
797}
798
Glenn Kasten2c073da2016-02-26 09:14:08 -0800799uint32_t AudioFlinger::sampleRate(audio_io_handle_t ioHandle) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700800{
801 Mutex::Autolock _l(mLock);
Glenn Kasten2c073da2016-02-26 09:14:08 -0800802 ThreadBase *thread = checkThread_l(ioHandle);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700803 if (thread == NULL) {
Glenn Kasten2c073da2016-02-26 09:14:08 -0800804 ALOGW("sampleRate() unknown thread %d", ioHandle);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700805 return 0;
806 }
807 return thread->sampleRate();
808}
809
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800810audio_format_t AudioFlinger::format(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700811{
812 Mutex::Autolock _l(mLock);
813 PlaybackThread *thread = checkPlaybackThread_l(output);
814 if (thread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000815 ALOGW("format() unknown thread %d", output);
Glenn Kasten58f30212012-01-12 12:27:51 -0800816 return AUDIO_FORMAT_INVALID;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700817 }
818 return thread->format();
819}
820
Glenn Kasten2c073da2016-02-26 09:14:08 -0800821size_t AudioFlinger::frameCount(audio_io_handle_t ioHandle) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700822{
823 Mutex::Autolock _l(mLock);
Glenn Kasten2c073da2016-02-26 09:14:08 -0800824 ThreadBase *thread = checkThread_l(ioHandle);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700825 if (thread == NULL) {
Glenn Kasten2c073da2016-02-26 09:14:08 -0800826 ALOGW("frameCount() unknown thread %d", ioHandle);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700827 return 0;
828 }
Glenn Kasten58912562012-04-03 10:45:00 -0700829 // FIXME currently returns the normal mixer's frame count to avoid confusing legacy callers;
830 // should examine all callers and fix them to handle smaller counts
Mathias Agopian65ab4712010-07-14 17:59:35 -0700831 return thread->frameCount();
832}
833
Glenn Kasten4a8308b2016-04-18 14:10:01 -0700834size_t AudioFlinger::frameCountHAL(audio_io_handle_t ioHandle) const
835{
836 Mutex::Autolock _l(mLock);
837 ThreadBase *thread = checkThread_l(ioHandle);
838 if (thread == NULL) {
839 ALOGW("frameCountHAL() unknown thread %d", ioHandle);
840 return 0;
841 }
842 return thread->frameCountHAL();
843}
844
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800845uint32_t AudioFlinger::latency(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700846{
847 Mutex::Autolock _l(mLock);
848 PlaybackThread *thread = checkPlaybackThread_l(output);
849 if (thread == NULL) {
Glenn Kastenc9b2e202013-02-26 11:32:32 -0800850 ALOGW("latency(): no playback thread found for output handle %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700851 return 0;
852 }
853 return thread->latency();
854}
855
856status_t AudioFlinger::setMasterVolume(float value)
857{
Eric Laurenta1884f92011-08-23 08:25:03 -0700858 status_t ret = initCheck();
859 if (ret != NO_ERROR) {
860 return ret;
861 }
862
Mathias Agopian65ab4712010-07-14 17:59:35 -0700863 // check calling permissions
864 if (!settingsAllowed()) {
865 return PERMISSION_DENIED;
866 }
867
Eric Laurenta4c5a552012-03-29 10:12:40 -0700868 Mutex::Autolock _l(mLock);
John Grossmanee578c02012-07-23 17:05:46 -0700869 mMasterVolume = value;
Eric Laurenta4c5a552012-03-29 10:12:40 -0700870
John Grossmanee578c02012-07-23 17:05:46 -0700871 // Set master volume in the HALs which support it.
872 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
873 AutoMutex lock(mHardwareLock);
874 AudioHwDevice *dev = mAudioHwDevs.valueAt(i);
John Grossman4ff14ba2012-02-08 16:37:41 -0800875
John Grossmanee578c02012-07-23 17:05:46 -0700876 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
877 if (dev->canSetMasterVolume()) {
Mikhail Naganove4f1f632016-08-31 11:35:10 -0700878 dev->hwDevice()->setMasterVolume(value);
Eric Laurent93575202011-01-18 18:39:02 -0800879 }
John Grossmanee578c02012-07-23 17:05:46 -0700880 mHardwareStatus = AUDIO_HW_IDLE;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700881 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700882
John Grossmanee578c02012-07-23 17:05:46 -0700883 // Now set the master volume in each playback thread. Playback threads
884 // assigned to HALs which do not have master volume support will apply
885 // master volume during the mix operation. Threads with HALs which do
886 // support master volume will simply ignore the setting.
Eric Laurentf6870ae2015-05-08 10:50:03 -0700887 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
888 if (mPlaybackThreads.valueAt(i)->isDuplicating()) {
889 continue;
890 }
John Grossmanee578c02012-07-23 17:05:46 -0700891 mPlaybackThreads.valueAt(i)->setMasterVolume(value);
Eric Laurentf6870ae2015-05-08 10:50:03 -0700892 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700893
894 return NO_ERROR;
895}
896
Glenn Kastenf78aee72012-01-04 11:00:47 -0800897status_t AudioFlinger::setMode(audio_mode_t mode)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700898{
Eric Laurenta1884f92011-08-23 08:25:03 -0700899 status_t ret = initCheck();
900 if (ret != NO_ERROR) {
901 return ret;
902 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700903
904 // check calling permissions
905 if (!settingsAllowed()) {
906 return PERMISSION_DENIED;
907 }
Glenn Kasten930f4ca2012-01-06 16:47:31 -0800908 if (uint32_t(mode) >= AUDIO_MODE_CNT) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000909 ALOGW("Illegal value: setMode(%d)", mode);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700910 return BAD_VALUE;
911 }
912
913 { // scope for the lock
914 AutoMutex lock(mHardwareLock);
Mikhail Naganove4f1f632016-08-31 11:35:10 -0700915 sp<DeviceHalInterface> dev = mPrimaryHardwareDev->hwDevice();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700916 mHardwareStatus = AUDIO_HW_SET_MODE;
Mikhail Naganove4f1f632016-08-31 11:35:10 -0700917 ret = dev->setMode(mode);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700918 mHardwareStatus = AUDIO_HW_IDLE;
919 }
920
921 if (NO_ERROR == ret) {
922 Mutex::Autolock _l(mLock);
923 mMode = mode;
Glenn Kasten8d6a2442012-02-08 14:04:28 -0800924 for (size_t i = 0; i < mPlaybackThreads.size(); i++)
Glenn Kastene53b9ea2012-03-12 16:29:55 -0700925 mPlaybackThreads.valueAt(i)->setMode(mode);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700926 }
927
928 return ret;
929}
930
931status_t AudioFlinger::setMicMute(bool state)
932{
Eric Laurenta1884f92011-08-23 08:25:03 -0700933 status_t ret = initCheck();
934 if (ret != NO_ERROR) {
935 return ret;
936 }
937
Mathias Agopian65ab4712010-07-14 17:59:35 -0700938 // check calling permissions
939 if (!settingsAllowed()) {
940 return PERMISSION_DENIED;
941 }
942
943 AutoMutex lock(mHardwareLock);
944 mHardwareStatus = AUDIO_HW_SET_MIC_MUTE;
Eric Laurent2f035f52014-09-14 12:11:52 -0700945 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
Mikhail Naganove4f1f632016-08-31 11:35:10 -0700946 sp<DeviceHalInterface> dev = mAudioHwDevs.valueAt(i)->hwDevice();
947 status_t result = dev->setMicMute(state);
Eric Laurent2f035f52014-09-14 12:11:52 -0700948 if (result != NO_ERROR) {
949 ret = result;
950 }
951 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700952 mHardwareStatus = AUDIO_HW_IDLE;
953 return ret;
954}
955
956bool AudioFlinger::getMicMute() const
957{
Eric Laurenta1884f92011-08-23 08:25:03 -0700958 status_t ret = initCheck();
959 if (ret != NO_ERROR) {
960 return false;
961 }
Ricardo Garcia3e91b5d2015-02-19 10:54:52 -0800962 bool mute = true;
Dima Zavinfce7a472011-04-19 22:30:36 -0700963 bool state = AUDIO_MODE_INVALID;
Glenn Kasten2b213bc2012-02-02 14:05:20 -0800964 AutoMutex lock(mHardwareLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700965 mHardwareStatus = AUDIO_HW_GET_MIC_MUTE;
Ricardo Garcia3e91b5d2015-02-19 10:54:52 -0800966 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
Mikhail Naganove4f1f632016-08-31 11:35:10 -0700967 sp<DeviceHalInterface> dev = mAudioHwDevs.valueAt(i)->hwDevice();
968 status_t result = dev->getMicMute(&state);
Ricardo Garcia3e91b5d2015-02-19 10:54:52 -0800969 if (result == NO_ERROR) {
970 mute = mute && state;
971 }
972 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700973 mHardwareStatus = AUDIO_HW_IDLE;
Ricardo Garcia3e91b5d2015-02-19 10:54:52 -0800974
975 return mute;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700976}
977
978status_t AudioFlinger::setMasterMute(bool muted)
979{
John Grossmand8f178d2012-07-20 14:51:35 -0700980 status_t ret = initCheck();
981 if (ret != NO_ERROR) {
982 return ret;
983 }
984
Mathias Agopian65ab4712010-07-14 17:59:35 -0700985 // check calling permissions
986 if (!settingsAllowed()) {
987 return PERMISSION_DENIED;
988 }
989
John Grossmanee578c02012-07-23 17:05:46 -0700990 Mutex::Autolock _l(mLock);
991 mMasterMute = muted;
John Grossmand8f178d2012-07-20 14:51:35 -0700992
John Grossmanee578c02012-07-23 17:05:46 -0700993 // Set master mute in the HALs which support it.
994 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
995 AutoMutex lock(mHardwareLock);
996 AudioHwDevice *dev = mAudioHwDevs.valueAt(i);
John Grossmand8f178d2012-07-20 14:51:35 -0700997
John Grossmanee578c02012-07-23 17:05:46 -0700998 mHardwareStatus = AUDIO_HW_SET_MASTER_MUTE;
999 if (dev->canSetMasterMute()) {
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001000 dev->hwDevice()->setMasterMute(muted);
John Grossmand8f178d2012-07-20 14:51:35 -07001001 }
John Grossmanee578c02012-07-23 17:05:46 -07001002 mHardwareStatus = AUDIO_HW_IDLE;
John Grossmand8f178d2012-07-20 14:51:35 -07001003 }
1004
John Grossmanee578c02012-07-23 17:05:46 -07001005 // Now set the master mute in each playback thread. Playback threads
1006 // assigned to HALs which do not have master mute support will apply master
1007 // mute during the mix operation. Threads with HALs which do support master
1008 // mute will simply ignore the setting.
Eric Laurent6acd1d42017-01-04 14:23:29 -08001009 Vector<VolumeInterface *> volumeInterfaces = getAllVolumeInterfaces_l();
1010 for (size_t i = 0; i < volumeInterfaces.size(); i++) {
1011 volumeInterfaces[i]->setMasterMute(muted);
Eric Laurentf6870ae2015-05-08 10:50:03 -07001012 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001013
1014 return NO_ERROR;
1015}
1016
1017float AudioFlinger::masterVolume() const
1018{
Glenn Kasten98067102011-12-13 11:47:54 -08001019 Mutex::Autolock _l(mLock);
1020 return masterVolume_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001021}
1022
1023bool AudioFlinger::masterMute() const
1024{
Glenn Kasten98067102011-12-13 11:47:54 -08001025 Mutex::Autolock _l(mLock);
1026 return masterMute_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001027}
1028
John Grossman4ff14ba2012-02-08 16:37:41 -08001029float AudioFlinger::masterVolume_l() const
1030{
John Grossman4ff14ba2012-02-08 16:37:41 -08001031 return mMasterVolume;
1032}
1033
John Grossmand8f178d2012-07-20 14:51:35 -07001034bool AudioFlinger::masterMute_l() const
1035{
John Grossmanee578c02012-07-23 17:05:46 -07001036 return mMasterMute;
John Grossmand8f178d2012-07-20 14:51:35 -07001037}
1038
Eric Laurent223fd5c2014-11-11 13:43:36 -08001039status_t AudioFlinger::checkStreamType(audio_stream_type_t stream) const
1040{
1041 if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
Eric Laurent6acd1d42017-01-04 14:23:29 -08001042 ALOGW("checkStreamType() invalid stream %d", stream);
Eric Laurent223fd5c2014-11-11 13:43:36 -08001043 return BAD_VALUE;
1044 }
1045 pid_t caller = IPCThreadState::self()->getCallingPid();
1046 if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT && caller != getpid_cached) {
Eric Laurent6acd1d42017-01-04 14:23:29 -08001047 ALOGW("checkStreamType() pid %d cannot use internal stream type %d", caller, stream);
Eric Laurent223fd5c2014-11-11 13:43:36 -08001048 return PERMISSION_DENIED;
1049 }
1050
1051 return NO_ERROR;
1052}
1053
Glenn Kasten72ef00d2012-01-17 11:09:42 -08001054status_t AudioFlinger::setStreamVolume(audio_stream_type_t stream, float value,
1055 audio_io_handle_t output)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001056{
1057 // check calling permissions
1058 if (!settingsAllowed()) {
1059 return PERMISSION_DENIED;
1060 }
1061
Eric Laurent223fd5c2014-11-11 13:43:36 -08001062 status_t status = checkStreamType(stream);
1063 if (status != NO_ERROR) {
1064 return status;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001065 }
Eric Laurent223fd5c2014-11-11 13:43:36 -08001066 ALOG_ASSERT(stream != AUDIO_STREAM_PATCH, "attempt to change AUDIO_STREAM_PATCH volume");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001067
1068 AutoMutex lock(mLock);
Eric Laurent6acd1d42017-01-04 14:23:29 -08001069 Vector<VolumeInterface *> volumeInterfaces;
Glenn Kasten142f5192014-03-25 17:44:59 -07001070 if (output != AUDIO_IO_HANDLE_NONE) {
Eric Laurent6acd1d42017-01-04 14:23:29 -08001071 VolumeInterface *volumeInterface = getVolumeInterface_l(output);
1072 if (volumeInterface == NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001073 return BAD_VALUE;
1074 }
Eric Laurent6acd1d42017-01-04 14:23:29 -08001075 volumeInterfaces.add(volumeInterface);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001076 }
1077
1078 mStreamTypes[stream].volume = value;
1079
Eric Laurent6acd1d42017-01-04 14:23:29 -08001080 if (volumeInterfaces.size() == 0) {
1081 volumeInterfaces = getAllVolumeInterfaces_l();
1082 }
1083 for (size_t i = 0; i < volumeInterfaces.size(); i++) {
1084 volumeInterfaces[i]->setStreamVolume(stream, value);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001085 }
1086
1087 return NO_ERROR;
1088}
1089
Glenn Kastenfff6d712012-01-12 16:38:12 -08001090status_t AudioFlinger::setStreamMute(audio_stream_type_t stream, bool muted)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001091{
1092 // check calling permissions
1093 if (!settingsAllowed()) {
1094 return PERMISSION_DENIED;
1095 }
1096
Eric Laurent223fd5c2014-11-11 13:43:36 -08001097 status_t status = checkStreamType(stream);
1098 if (status != NO_ERROR) {
1099 return status;
1100 }
1101 ALOG_ASSERT(stream != AUDIO_STREAM_PATCH, "attempt to mute AUDIO_STREAM_PATCH");
1102
1103 if (uint32_t(stream) == AUDIO_STREAM_ENFORCED_AUDIBLE) {
Steve Block29357bc2012-01-06 19:20:56 +00001104 ALOGE("setStreamMute() invalid stream %d", stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001105 return BAD_VALUE;
1106 }
1107
Eric Laurent93575202011-01-18 18:39:02 -08001108 AutoMutex lock(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001109 mStreamTypes[stream].mute = muted;
Eric Laurent6acd1d42017-01-04 14:23:29 -08001110 Vector<VolumeInterface *> volumeInterfaces = getAllVolumeInterfaces_l();
1111 for (size_t i = 0; i < volumeInterfaces.size(); i++) {
1112 volumeInterfaces[i]->setStreamMute(stream, muted);
1113 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001114
1115 return NO_ERROR;
1116}
1117
Glenn Kasten72ef00d2012-01-17 11:09:42 -08001118float AudioFlinger::streamVolume(audio_stream_type_t stream, audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07001119{
Eric Laurent223fd5c2014-11-11 13:43:36 -08001120 status_t status = checkStreamType(stream);
1121 if (status != NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001122 return 0.0f;
1123 }
1124
1125 AutoMutex lock(mLock);
1126 float volume;
Glenn Kasten142f5192014-03-25 17:44:59 -07001127 if (output != AUDIO_IO_HANDLE_NONE) {
Eric Laurent6acd1d42017-01-04 14:23:29 -08001128 VolumeInterface *volumeInterface = getVolumeInterface_l(output);
1129 if (volumeInterface != NULL) {
1130 volume = volumeInterface->streamVolume(stream);
1131 } else {
1132 volume = 0.0f;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001133 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001134 } else {
Glenn Kasten6637baa2012-01-09 09:40:36 -08001135 volume = streamVolume_l(stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001136 }
1137
1138 return volume;
1139}
1140
Glenn Kastenfff6d712012-01-12 16:38:12 -08001141bool AudioFlinger::streamMute(audio_stream_type_t stream) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07001142{
Eric Laurent223fd5c2014-11-11 13:43:36 -08001143 status_t status = checkStreamType(stream);
1144 if (status != NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001145 return true;
1146 }
1147
Glenn Kasten6637baa2012-01-09 09:40:36 -08001148 AutoMutex lock(mLock);
1149 return streamMute_l(stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001150}
1151
Eric Laurent054d9d32015-04-24 08:48:48 -07001152
1153void AudioFlinger::broacastParametersToRecordThreads_l(const String8& keyValuePairs)
1154{
1155 for (size_t i = 0; i < mRecordThreads.size(); i++) {
1156 mRecordThreads.valueAt(i)->setParameters(keyValuePairs);
1157 }
1158}
1159
Glenn Kasten72ef00d2012-01-17 11:09:42 -08001160status_t AudioFlinger::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001161{
Glenn Kasten827e5f12012-11-02 10:00:06 -07001162 ALOGV("setParameters(): io %d, keyvalue %s, calling pid %d",
1163 ioHandle, keyValuePairs.string(), IPCThreadState::self()->getCallingPid());
Eric Laurent81784c32012-11-19 14:55:58 -08001164
Mathias Agopian65ab4712010-07-14 17:59:35 -07001165 // check calling permissions
1166 if (!settingsAllowed()) {
1167 return PERMISSION_DENIED;
1168 }
1169
Glenn Kasten142f5192014-03-25 17:44:59 -07001170 // AUDIO_IO_HANDLE_NONE means the parameters are global to the audio hardware interface
1171 if (ioHandle == AUDIO_IO_HANDLE_NONE) {
Eric Laurenta4c5a552012-03-29 10:12:40 -07001172 Mutex::Autolock _l(mLock);
Eric Laurentd21bcd22016-09-08 18:25:54 -07001173 // result will remain NO_INIT if no audio device is present
1174 status_t final_result = NO_INIT;
Glenn Kasten8abf44d2012-02-02 14:16:03 -08001175 {
Eric Laurenta4c5a552012-03-29 10:12:40 -07001176 AutoMutex lock(mHardwareLock);
1177 mHardwareStatus = AUDIO_HW_SET_PARAMETER;
1178 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001179 sp<DeviceHalInterface> dev = mAudioHwDevs.valueAt(i)->hwDevice();
1180 status_t result = dev->setParameters(keyValuePairs);
Eric Laurentd21bcd22016-09-08 18:25:54 -07001181 // return success if at least one audio device accepts the parameters as not all
1182 // HALs are requested to support all parameters. If no audio device supports the
1183 // requested parameters, the last error is reported.
1184 if (final_result != NO_ERROR) {
1185 final_result = result;
1186 }
Eric Laurenta4c5a552012-03-29 10:12:40 -07001187 }
1188 mHardwareStatus = AUDIO_HW_IDLE;
Glenn Kasten8abf44d2012-02-02 14:16:03 -08001189 }
Eric Laurent59bd0da2011-08-01 09:52:20 -07001190 // disable AEC and NS if the device is a BT SCO headset supporting those pre processings
1191 AudioParameter param = AudioParameter(keyValuePairs);
1192 String8 value;
Mikhail Naganov00260b52016-10-13 12:54:24 -07001193 if (param.get(String8(AudioParameter::keyBtNrec), value) == NO_ERROR) {
1194 bool btNrecIsOff = (value == AudioParameter::valueOff);
Eric Laurentbee53372011-08-29 12:42:48 -07001195 if (mBtNrecIsOff != btNrecIsOff) {
Eric Laurent59bd0da2011-08-01 09:52:20 -07001196 for (size_t i = 0; i < mRecordThreads.size(); i++) {
1197 sp<RecordThread> thread = mRecordThreads.valueAt(i);
Eric Laurentf1c04f92012-08-28 14:26:53 -07001198 audio_devices_t device = thread->inDevice();
Glenn Kasten510a3d62012-07-16 14:24:34 -07001199 bool suspend = audio_is_bluetooth_sco_device(device) && btNrecIsOff;
1200 // collect all of the thread's session IDs
Glenn Kastend848eb42016-03-08 13:42:11 -08001201 KeyedVector<audio_session_t, bool> ids = thread->sessionIds();
Glenn Kasten510a3d62012-07-16 14:24:34 -07001202 // suspend effects associated with those session IDs
1203 for (size_t j = 0; j < ids.size(); ++j) {
Glenn Kastend848eb42016-03-08 13:42:11 -08001204 audio_session_t sessionId = ids.keyAt(j);
Eric Laurent59bd0da2011-08-01 09:52:20 -07001205 thread->setEffectSuspended(FX_IID_AEC,
1206 suspend,
Glenn Kasten510a3d62012-07-16 14:24:34 -07001207 sessionId);
Eric Laurent59bd0da2011-08-01 09:52:20 -07001208 thread->setEffectSuspended(FX_IID_NS,
1209 suspend,
Glenn Kasten510a3d62012-07-16 14:24:34 -07001210 sessionId);
Eric Laurent59bd0da2011-08-01 09:52:20 -07001211 }
1212 }
Eric Laurentbee53372011-08-29 12:42:48 -07001213 mBtNrecIsOff = btNrecIsOff;
Eric Laurent59bd0da2011-08-01 09:52:20 -07001214 }
1215 }
Glenn Kasten28ed2f92012-06-07 10:17:54 -07001216 String8 screenState;
1217 if (param.get(String8(AudioParameter::keyScreenState), screenState) == NO_ERROR) {
Mikhail Naganov00260b52016-10-13 12:54:24 -07001218 bool isOff = (screenState == AudioParameter::valueOff);
Eric Laurent81784c32012-11-19 14:55:58 -08001219 if (isOff != (AudioFlinger::mScreenState & 1)) {
1220 AudioFlinger::mScreenState = ((AudioFlinger::mScreenState & ~1) + 2) | isOff;
Glenn Kasten28ed2f92012-06-07 10:17:54 -07001221 }
1222 }
Dima Zavin799a70e2011-04-18 16:57:27 -07001223 return final_result;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001224 }
1225
1226 // hold a strong ref on thread in case closeOutput() or closeInput() is called
1227 // and the thread is exited once the lock is released
1228 sp<ThreadBase> thread;
1229 {
1230 Mutex::Autolock _l(mLock);
1231 thread = checkPlaybackThread_l(ioHandle);
Glenn Kastend5903ec2012-03-18 10:33:27 -07001232 if (thread == 0) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001233 thread = checkRecordThread_l(ioHandle);
Eric Laurent6acd1d42017-01-04 14:23:29 -08001234 if (thread == 0) {
1235 thread = checkMmapThread_l(ioHandle);
1236 }
Glenn Kasten7fc9a6f2012-01-10 10:46:34 -08001237 } else if (thread == primaryPlaybackThread_l()) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07001238 // indicate output device change to all input threads for pre processing
1239 AudioParameter param = AudioParameter(keyValuePairs);
1240 int value;
Eric Laurent89d94e72012-03-16 20:37:59 -07001241 if ((param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) &&
1242 (value != 0)) {
Eric Laurent054d9d32015-04-24 08:48:48 -07001243 broacastParametersToRecordThreads_l(keyValuePairs);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07001244 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001245 }
1246 }
Glenn Kasten7378ca52012-01-20 13:44:40 -08001247 if (thread != 0) {
1248 return thread->setParameters(keyValuePairs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001249 }
1250 return BAD_VALUE;
1251}
1252
Glenn Kasten72ef00d2012-01-17 11:09:42 -08001253String8 AudioFlinger::getParameters(audio_io_handle_t ioHandle, const String8& keys) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07001254{
Glenn Kasten827e5f12012-11-02 10:00:06 -07001255 ALOGVV("getParameters() io %d, keys %s, calling pid %d",
1256 ioHandle, keys.string(), IPCThreadState::self()->getCallingPid());
Mathias Agopian65ab4712010-07-14 17:59:35 -07001257
Eric Laurenta4c5a552012-03-29 10:12:40 -07001258 Mutex::Autolock _l(mLock);
1259
Glenn Kasten142f5192014-03-25 17:44:59 -07001260 if (ioHandle == AUDIO_IO_HANDLE_NONE) {
Dima Zavinfce7a472011-04-19 22:30:36 -07001261 String8 out_s8;
1262
Dima Zavin799a70e2011-04-18 16:57:27 -07001263 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001264 String8 s;
1265 status_t result;
Glenn Kasten8abf44d2012-02-02 14:16:03 -08001266 {
1267 AutoMutex lock(mHardwareLock);
1268 mHardwareStatus = AUDIO_HW_GET_PARAMETER;
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001269 sp<DeviceHalInterface> dev = mAudioHwDevs.valueAt(i)->hwDevice();
1270 result = dev->getParameters(keys, &s);
Glenn Kasten8abf44d2012-02-02 14:16:03 -08001271 mHardwareStatus = AUDIO_HW_IDLE;
1272 }
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001273 if (result == OK) out_s8 += s;
Dima Zavin799a70e2011-04-18 16:57:27 -07001274 }
Dima Zavinfce7a472011-04-19 22:30:36 -07001275 return out_s8;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001276 }
1277
Eric Laurent6acd1d42017-01-04 14:23:29 -08001278 ThreadBase *thread = (ThreadBase *)checkPlaybackThread_l(ioHandle);
1279 if (thread == NULL) {
1280 thread = (ThreadBase *)checkRecordThread_l(ioHandle);
1281 if (thread == NULL) {
1282 thread = (ThreadBase *)checkMmapThread_l(ioHandle);
1283 if (thread == NULL) {
1284 String8("");
1285 }
1286 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001287 }
Eric Laurent6acd1d42017-01-04 14:23:29 -08001288 return thread->getParameters(keys);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001289}
1290
Glenn Kastendd8104c2012-07-02 12:42:44 -07001291size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, audio_format_t format,
1292 audio_channel_mask_t channelMask) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07001293{
Eric Laurenta1884f92011-08-23 08:25:03 -07001294 status_t ret = initCheck();
1295 if (ret != NO_ERROR) {
1296 return 0;
1297 }
Eric Laurentcdf924a2016-02-04 15:57:56 -08001298 if ((sampleRate == 0) ||
Phil Burkfdb3c072016-02-09 10:47:02 -08001299 !audio_is_valid_format(format) || !audio_has_proportional_frames(format) ||
Eric Laurentcdf924a2016-02-04 15:57:56 -08001300 !audio_is_input_channel(channelMask)) {
Andy Hung6770c6f2015-04-07 13:43:36 -07001301 return 0;
1302 }
Eric Laurenta1884f92011-08-23 08:25:03 -07001303
Glenn Kasten2b213bc2012-02-02 14:05:20 -08001304 AutoMutex lock(mHardwareLock);
1305 mHardwareStatus = AUDIO_HW_GET_INPUT_BUFFER_SIZE;
Andy Hung6770c6f2015-04-07 13:43:36 -07001306 audio_config_t config, proposed;
1307 memset(&proposed, 0, sizeof(proposed));
1308 proposed.sample_rate = sampleRate;
1309 proposed.channel_mask = channelMask;
1310 proposed.format = format;
Richard Fitzgeraldad3af332013-03-25 16:54:37 +00001311
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001312 sp<DeviceHalInterface> dev = mPrimaryHardwareDev->hwDevice();
Andy Hung6770c6f2015-04-07 13:43:36 -07001313 size_t frames;
1314 for (;;) {
1315 // Note: config is currently a const parameter for get_input_buffer_size()
1316 // but we use a copy from proposed in case config changes from the call.
1317 config = proposed;
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001318 status_t result = dev->getInputBufferSize(&config, &frames);
1319 if (result == OK && frames != 0) {
Andy Hung6770c6f2015-04-07 13:43:36 -07001320 break; // hal success, config is the result
1321 }
1322 // change one parameter of the configuration each iteration to a more "common" value
1323 // to see if the device will support it.
1324 if (proposed.format != AUDIO_FORMAT_PCM_16_BIT) {
1325 proposed.format = AUDIO_FORMAT_PCM_16_BIT;
1326 } else if (proposed.sample_rate != 44100) { // 44.1 is claimed as must in CDD as well as
1327 proposed.sample_rate = 44100; // legacy AudioRecord.java. TODO: Query hw?
1328 } else {
1329 ALOGW("getInputBufferSize failed with minimum buffer size sampleRate %u, "
1330 "format %#x, channelMask 0x%X",
1331 sampleRate, format, channelMask);
1332 break; // retries failed, break out of loop with frames == 0.
1333 }
1334 }
Glenn Kasten2b213bc2012-02-02 14:05:20 -08001335 mHardwareStatus = AUDIO_HW_IDLE;
Andy Hung6770c6f2015-04-07 13:43:36 -07001336 if (frames > 0 && config.sample_rate != sampleRate) {
1337 frames = destinationFramesPossible(frames, sampleRate, config.sample_rate);
1338 }
1339 return frames; // may be converted to bytes at the Java level.
Mathias Agopian65ab4712010-07-14 17:59:35 -07001340}
1341
Glenn Kasten5f972c02014-01-13 09:59:31 -08001342uint32_t AudioFlinger::getInputFramesLost(audio_io_handle_t ioHandle) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07001343{
Mathias Agopian65ab4712010-07-14 17:59:35 -07001344 Mutex::Autolock _l(mLock);
1345
1346 RecordThread *recordThread = checkRecordThread_l(ioHandle);
1347 if (recordThread != NULL) {
1348 return recordThread->getInputFramesLost();
1349 }
1350 return 0;
1351}
1352
1353status_t AudioFlinger::setVoiceVolume(float value)
1354{
Eric Laurenta1884f92011-08-23 08:25:03 -07001355 status_t ret = initCheck();
1356 if (ret != NO_ERROR) {
1357 return ret;
1358 }
1359
Mathias Agopian65ab4712010-07-14 17:59:35 -07001360 // check calling permissions
1361 if (!settingsAllowed()) {
1362 return PERMISSION_DENIED;
1363 }
1364
1365 AutoMutex lock(mHardwareLock);
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001366 sp<DeviceHalInterface> dev = mPrimaryHardwareDev->hwDevice();
Glenn Kasten8abf44d2012-02-02 14:16:03 -08001367 mHardwareStatus = AUDIO_HW_SET_VOICE_VOLUME;
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001368 ret = dev->setVoiceVolume(value);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001369 mHardwareStatus = AUDIO_HW_IDLE;
1370
1371 return ret;
1372}
1373
Kévin PETIT377b2ec2014-02-03 12:35:36 +00001374status_t AudioFlinger::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames,
Glenn Kasten72ef00d2012-01-17 11:09:42 -08001375 audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07001376{
Mathias Agopian65ab4712010-07-14 17:59:35 -07001377 Mutex::Autolock _l(mLock);
1378
1379 PlaybackThread *playbackThread = checkPlaybackThread_l(output);
1380 if (playbackThread != NULL) {
1381 return playbackThread->getRenderPosition(halFrames, dspFrames);
1382 }
1383
1384 return BAD_VALUE;
1385}
1386
1387void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
1388{
Mathias Agopian65ab4712010-07-14 17:59:35 -07001389 Mutex::Autolock _l(mLock);
Eric Laurent44622db2014-08-01 19:00:33 -07001390 if (client == 0) {
1391 return;
1392 }
Eric Laurent7c1ec5f2015-07-09 14:52:47 -07001393 pid_t pid = IPCThreadState::self()->getCallingPid();
Eric Laurent021cf962014-05-13 10:18:14 -07001394 {
1395 Mutex::Autolock _cl(mClientLock);
Eric Laurent021cf962014-05-13 10:18:14 -07001396 if (mNotificationClients.indexOfKey(pid) < 0) {
1397 sp<NotificationClient> notificationClient = new NotificationClient(this,
1398 client,
1399 pid);
1400 ALOGV("registerClient() client %p, pid %d", notificationClient.get(), pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001401
Eric Laurent021cf962014-05-13 10:18:14 -07001402 mNotificationClients.add(pid, notificationClient);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001403
Marco Nelissen06b46062014-11-14 07:58:25 -08001404 sp<IBinder> binder = IInterface::asBinder(client);
Eric Laurent021cf962014-05-13 10:18:14 -07001405 binder->linkToDeath(notificationClient);
Eric Laurent021cf962014-05-13 10:18:14 -07001406 }
1407 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001408
Eric Laurent021cf962014-05-13 10:18:14 -07001409 // mClientLock should not be held here because ThreadBase::sendIoConfigEvent() will lock the
Eric Laurentfe1a94e2014-05-26 16:03:08 -07001410 // ThreadBase mutex and the locking order is ThreadBase::mLock then AudioFlinger::mClientLock.
Eric Laurent7c1ec5f2015-07-09 14:52:47 -07001411 // the config change is always sent from playback or record threads to avoid deadlock
1412 // with AudioSystem::gLock
1413 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
1414 mPlaybackThreads.valueAt(i)->sendIoConfigEvent(AUDIO_OUTPUT_OPENED, pid);
1415 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001416
Eric Laurent7c1ec5f2015-07-09 14:52:47 -07001417 for (size_t i = 0; i < mRecordThreads.size(); i++) {
1418 mRecordThreads.valueAt(i)->sendIoConfigEvent(AUDIO_INPUT_OPENED, pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001419 }
1420}
1421
1422void AudioFlinger::removeNotificationClient(pid_t pid)
1423{
1424 Mutex::Autolock _l(mLock);
Eric Laurent021cf962014-05-13 10:18:14 -07001425 {
1426 Mutex::Autolock _cl(mClientLock);
1427 mNotificationClients.removeItem(pid);
1428 }
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001429
Steve Block3856b092011-10-20 11:56:00 +01001430 ALOGV("%d died, releasing its sessions", pid);
Glenn Kasten8d6a2442012-02-08 14:04:28 -08001431 size_t num = mAudioSessionRefs.size();
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001432 bool removed = false;
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001433 for (size_t i = 0; i < num; ) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001434 AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001435 ALOGV(" pid %d @ %zu", ref->mPid, i);
Glenn Kasten012ca6b2012-03-06 11:22:01 -08001436 if (ref->mPid == pid) {
1437 ALOGV(" removing entry for pid %d session %d", pid, ref->mSessionid);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001438 mAudioSessionRefs.removeAt(i);
1439 delete ref;
1440 removed = true;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001441 num--;
Glenn Kasten8d6a2442012-02-08 14:04:28 -08001442 } else {
1443 i++;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001444 }
1445 }
1446 if (removed) {
1447 purgeStaleEffects_l();
1448 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001449}
1450
Eric Laurent73e26b62015-04-27 16:55:58 -07001451void AudioFlinger::ioConfigChanged(audio_io_config_event event,
Eric Laurent7c1ec5f2015-07-09 14:52:47 -07001452 const sp<AudioIoDescriptor>& ioDesc,
1453 pid_t pid)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001454{
Eric Laurent021cf962014-05-13 10:18:14 -07001455 Mutex::Autolock _l(mClientLock);
1456 size_t size = mNotificationClients.size();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001457 for (size_t i = 0; i < size; i++) {
Eric Laurent7c1ec5f2015-07-09 14:52:47 -07001458 if ((pid == 0) || (mNotificationClients.keyAt(i) == pid)) {
1459 mNotificationClients.valueAt(i)->audioFlingerClient()->ioConfigChanged(event, ioDesc);
1460 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001461 }
1462}
1463
Eric Laurent021cf962014-05-13 10:18:14 -07001464// removeClient_l() must be called with AudioFlinger::mClientLock held
Mathias Agopian65ab4712010-07-14 17:59:35 -07001465void AudioFlinger::removeClient_l(pid_t pid)
1466{
Glenn Kasten827e5f12012-11-02 10:00:06 -07001467 ALOGV("removeClient_l() pid %d, calling pid %d", pid,
Glenn Kasten85ab62c2012-11-01 11:11:38 -07001468 IPCThreadState::self()->getCallingPid());
Mathias Agopian65ab4712010-07-14 17:59:35 -07001469 mClients.removeItem(pid);
1470}
1471
Eric Laurent717e1282012-06-29 16:36:52 -07001472// getEffectThread_l() must be called with AudioFlinger::mLock held
Glenn Kastend848eb42016-03-08 13:42:11 -08001473sp<AudioFlinger::PlaybackThread> AudioFlinger::getEffectThread_l(audio_session_t sessionId,
1474 int EffectId)
Eric Laurent717e1282012-06-29 16:36:52 -07001475{
1476 sp<PlaybackThread> thread;
1477
1478 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
1479 if (mPlaybackThreads.valueAt(i)->getEffect(sessionId, EffectId) != 0) {
1480 ALOG_ASSERT(thread == 0);
1481 thread = mPlaybackThreads.valueAt(i);
1482 }
1483 }
1484
1485 return thread;
1486}
Mathias Agopian65ab4712010-07-14 17:59:35 -07001487
Mathias Agopian65ab4712010-07-14 17:59:35 -07001488
Mathias Agopian65ab4712010-07-14 17:59:35 -07001489
1490// ----------------------------------------------------------------------------
1491
1492AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
1493 : RefBase(),
1494 mAudioFlinger(audioFlinger),
Glenn Kastend79072e2016-01-06 08:41:20 -08001495 mPid(pid)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001496{
Sumit Bhattacharyacd64e0e2016-02-11 01:37:20 +05301497 size_t heapSize = property_get_int32("ro.af.client_heap_size_kbyte", 0);
1498 heapSize *= 1024;
1499 if (!heapSize) {
1500 heapSize = kClientSharedHeapSizeBytes;
1501 // Increase heap size on non low ram devices to limit risk of reconnection failure for
1502 // invalidated tracks
1503 if (!audioFlinger->isLowRamDevice()) {
1504 heapSize *= kClientSharedHeapSizeMultiplier;
1505 }
Eric Laurentda73b6c2015-08-20 16:18:53 -07001506 }
1507 mMemoryDealer = new MemoryDealer(heapSize, "AudioFlinger::Client");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001508}
1509
Eric Laurent021cf962014-05-13 10:18:14 -07001510// Client destructor must be called with AudioFlinger::mClientLock held
Mathias Agopian65ab4712010-07-14 17:59:35 -07001511AudioFlinger::Client::~Client()
1512{
1513 mAudioFlinger->removeClient_l(mPid);
1514}
1515
Glenn Kasten435dbe62012-01-30 10:15:48 -08001516sp<MemoryDealer> AudioFlinger::Client::heap() const
Mathias Agopian65ab4712010-07-14 17:59:35 -07001517{
1518 return mMemoryDealer;
1519}
1520
1521// ----------------------------------------------------------------------------
1522
1523AudioFlinger::NotificationClient::NotificationClient(const sp<AudioFlinger>& audioFlinger,
1524 const sp<IAudioFlingerClient>& client,
1525 pid_t pid)
Glenn Kasten84afa3b2012-01-25 15:28:08 -08001526 : mAudioFlinger(audioFlinger), mPid(pid), mAudioFlingerClient(client)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001527{
1528}
1529
1530AudioFlinger::NotificationClient::~NotificationClient()
1531{
Mathias Agopian65ab4712010-07-14 17:59:35 -07001532}
1533
Glenn Kasten0f11b512014-01-31 16:18:54 -08001534void AudioFlinger::NotificationClient::binderDied(const wp<IBinder>& who __unused)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001535{
1536 sp<NotificationClient> keep(this);
Glenn Kastena1117922012-01-26 10:53:32 -08001537 mAudioFlinger->removeNotificationClient(mPid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001538}
1539
Nicolas Rouletdcdfaec2017-02-14 10:18:39 -08001540// ----------------------------------------------------------------------------
1541AudioFlinger::MediaLogNotifier::MediaLogNotifier()
1542 : mPendingRequests(false) {}
1543
1544
1545void AudioFlinger::MediaLogNotifier::requestMerge() {
1546 AutoMutex _l(mMutex);
1547 mPendingRequests = true;
1548 mCond.signal();
1549}
1550
1551bool AudioFlinger::MediaLogNotifier::threadLoop() {
Glenn Kasten3ac24a12017-04-10 14:58:47 -07001552 // Should already have been checked, but just in case
1553 if (sMediaLogService == 0) {
1554 return false;
1555 }
Nicolas Rouletdcdfaec2017-02-14 10:18:39 -08001556 // Wait until there are pending requests
1557 {
1558 AutoMutex _l(mMutex);
1559 mPendingRequests = false; // to ignore past requests
1560 while (!mPendingRequests) {
1561 mCond.wait(mMutex);
1562 // TODO may also need an exitPending check
1563 }
1564 mPendingRequests = false;
1565 }
1566 // Execute the actual MediaLogService binder call and ignore extra requests for a while
Glenn Kasten3ac24a12017-04-10 14:58:47 -07001567 sMediaLogService->requestMergeWakeup();
Nicolas Rouletdcdfaec2017-02-14 10:18:39 -08001568 usleep(kPostTriggerSleepPeriod);
1569 return true;
1570}
1571
1572void AudioFlinger::requestLogMerge() {
1573 mMediaLogNotifier->requestMerge();
1574}
Mathias Agopian65ab4712010-07-14 17:59:35 -07001575
1576// ----------------------------------------------------------------------------
1577
1578sp<IAudioRecord> AudioFlinger::openRecord(
Glenn Kasten72ef00d2012-01-17 11:09:42 -08001579 audio_io_handle_t input,
Mathias Agopian65ab4712010-07-14 17:59:35 -07001580 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08001581 audio_format_t format,
Glenn Kasten254af182012-07-03 14:59:05 -07001582 audio_channel_mask_t channelMask,
Svet Ganovbe71aa22015-04-28 12:06:02 -07001583 const String16& opPackageName,
Glenn Kasten74935e42013-12-19 08:56:45 -08001584 size_t *frameCount,
Eric Laurent05067782016-06-01 18:27:28 -07001585 audio_input_flags_t *flags,
Haynes Mathew George9ea77cd2016-04-06 17:07:48 -07001586 pid_t pid,
Glenn Kasten1879fff2012-07-11 15:36:59 -07001587 pid_t tid,
Jean-Michel Trivi4cb66832015-05-01 18:34:17 -07001588 int clientUid,
Glenn Kastend848eb42016-03-08 13:42:11 -08001589 audio_session_t *sessionId,
Glenn Kasten7df8c0b2014-07-03 12:23:29 -07001590 size_t *notificationFrames,
Glenn Kastend776ac62014-05-07 09:16:09 -07001591 sp<IMemory>& cblk,
1592 sp<IMemory>& buffers,
Eric Laurent20b9ef02016-12-05 11:03:16 -08001593 status_t *status,
1594 audio_port_handle_t portId)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001595{
1596 sp<RecordThread::RecordTrack> recordTrack;
1597 sp<RecordHandle> recordHandle;
1598 sp<Client> client;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001599 status_t lStatus;
Glenn Kastend848eb42016-03-08 13:42:11 -08001600 audio_session_t lSessionId;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001601
Glenn Kastend776ac62014-05-07 09:16:09 -07001602 cblk.clear();
1603 buffers.clear();
1604
Haynes Mathew George9ea77cd2016-04-06 17:07:48 -07001605 bool updatePid = (pid == -1);
Marco Nelissendcb346b2015-09-09 10:47:29 -07001606 const uid_t callingUid = IPCThreadState::self()->getCallingUid();
1607 if (!isTrustedCallingUid(callingUid)) {
Andy Hung879db192016-01-05 16:00:34 -08001608 ALOGW_IF((uid_t)clientUid != callingUid,
Marco Nelissendcb346b2015-09-09 10:47:29 -07001609 "%s uid %d tried to pass itself off as %d", __FUNCTION__, callingUid, clientUid);
1610 clientUid = callingUid;
Haynes Mathew George9ea77cd2016-04-06 17:07:48 -07001611 updatePid = true;
1612 }
1613
1614 if (updatePid) {
1615 const pid_t callingPid = IPCThreadState::self()->getCallingPid();
1616 ALOGW_IF(pid != -1 && pid != callingPid,
1617 "%s uid %d pid %d tried to pass itself off as pid %d",
1618 __func__, callingUid, callingPid, pid);
1619 pid = callingPid;
Marco Nelissendcb346b2015-09-09 10:47:29 -07001620 }
1621
Mathias Agopian65ab4712010-07-14 17:59:35 -07001622 // check calling permissions
Marco Nelissendcb346b2015-09-09 10:47:29 -07001623 if (!recordingAllowed(opPackageName, tid, clientUid)) {
Glenn Kastene93cf2c2013-09-24 11:52:37 -07001624 ALOGE("openRecord() permission denied: recording not allowed");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001625 lStatus = PERMISSION_DENIED;
1626 goto Exit;
1627 }
1628
Glenn Kasten53b5d092014-02-05 10:00:23 -08001629 // further sample rate checks are performed by createRecordTrack_l()
1630 if (sampleRate == 0) {
1631 ALOGE("openRecord() invalid sample rate %u", sampleRate);
1632 lStatus = BAD_VALUE;
1633 goto Exit;
1634 }
1635
Andy Hung6770c6f2015-04-07 13:43:36 -07001636 // we don't yet support anything other than linear PCM
1637 if (!audio_is_valid_format(format) || !audio_is_linear_pcm(format)) {
Glenn Kastencac3daa2014-02-07 09:47:14 -08001638 ALOGE("openRecord() invalid format %#x", format);
Glenn Kasten291bb6d2013-07-16 17:23:39 -07001639 lStatus = BAD_VALUE;
1640 goto Exit;
1641 }
1642
Glenn Kasten53b5d092014-02-05 10:00:23 -08001643 // further channel mask checks are performed by createRecordTrack_l()
1644 if (!audio_is_input_channel(channelMask)) {
1645 ALOGE("openRecord() invalid channel mask %#x", channelMask);
1646 lStatus = BAD_VALUE;
1647 goto Exit;
1648 }
1649
Glenn Kasten05997e22014-03-13 15:08:33 -07001650 {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001651 Mutex::Autolock _l(mLock);
Glenn Kastene848bd92014-03-13 15:00:32 -07001652 RecordThread *thread = checkRecordThread_l(input);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001653 if (thread == NULL) {
Glenn Kastene93cf2c2013-09-24 11:52:37 -07001654 ALOGE("openRecord() checkRecordThread_l failed");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001655 lStatus = BAD_VALUE;
1656 goto Exit;
1657 }
1658
Eric Laurent021cf962014-05-13 10:18:14 -07001659 client = registerPid(pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001660
Glenn Kastenaea7ea02013-06-26 09:25:47 -07001661 if (sessionId != NULL && *sessionId != AUDIO_SESSION_ALLOCATE) {
Glenn Kasteneeecb982016-02-26 10:44:04 -08001662 if (audio_unique_id_get_use(*sessionId) != AUDIO_UNIQUE_ID_USE_SESSION) {
1663 lStatus = BAD_VALUE;
1664 goto Exit;
1665 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001666 lSessionId = *sessionId;
1667 } else {
Glenn Kasten570f6332014-03-13 15:01:06 -07001668 // if no audio session id is provided, create one here
Glenn Kastend848eb42016-03-08 13:42:11 -08001669 lSessionId = (audio_session_t) nextUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001670 if (sessionId != NULL) {
1671 *sessionId = lSessionId;
1672 }
1673 }
Eric Laurentaaa44472014-09-12 17:41:50 -07001674 ALOGV("openRecord() lSessionId: %d input %d", lSessionId, input);
Glenn Kasten570f6332014-03-13 15:01:06 -07001675
Glenn Kasten1879fff2012-07-11 15:36:59 -07001676 recordTrack = thread->createRecordTrack_l(client, sampleRate, format, channelMask,
Glenn Kasten7df8c0b2014-07-03 12:23:29 -07001677 frameCount, lSessionId, notificationFrames,
Eric Laurent20b9ef02016-12-05 11:03:16 -08001678 clientUid, flags, tid, &lStatus, portId);
Haynes Mathew George03e9e832013-12-13 15:40:13 -08001679 LOG_ALWAYS_FATAL_IF((lStatus == NO_ERROR) && (recordTrack == 0));
Eric Laurent1b928682014-10-02 19:41:47 -07001680
1681 if (lStatus == NO_ERROR) {
1682 // Check if one effect chain was awaiting for an AudioRecord to be created on this
1683 // session and move it to this thread.
Glenn Kastend848eb42016-03-08 13:42:11 -08001684 sp<EffectChain> chain = getOrphanEffectChain_l(lSessionId);
Eric Laurent1b928682014-10-02 19:41:47 -07001685 if (chain != 0) {
1686 Mutex::Autolock _l(thread->mLock);
1687 thread->addEffectChain_l(chain);
1688 }
1689 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001690 }
Glenn Kastene198c362013-08-13 09:13:36 -07001691
Eric Laurent7c7f10b2011-06-17 21:29:58 -07001692 if (lStatus != NO_ERROR) {
Glenn Kasten85ab62c2012-11-01 11:11:38 -07001693 // remove local strong reference to Client before deleting the RecordTrack so that the
Eric Laurent021cf962014-05-13 10:18:14 -07001694 // Client destructor is called by the TrackBase destructor with mClientLock held
Eric Laurentfe1a94e2014-05-26 16:03:08 -07001695 // Don't hold mClientLock when releasing the reference on the track as the
1696 // destructor will acquire it.
1697 {
1698 Mutex::Autolock _cl(mClientLock);
1699 client.clear();
1700 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001701 recordTrack.clear();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001702 goto Exit;
1703 }
1704
Glenn Kastend776ac62014-05-07 09:16:09 -07001705 cblk = recordTrack->getCblk();
1706 buffers = recordTrack->getBuffers();
1707
Glenn Kasten2fc14732013-08-05 14:58:14 -07001708 // return handle to client
Mathias Agopian65ab4712010-07-14 17:59:35 -07001709 recordHandle = new RecordHandle(recordTrack);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001710
1711Exit:
Glenn Kasten9156ef32013-08-06 15:39:08 -07001712 *status = lStatus;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001713 return recordHandle;
1714}
1715
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001716
1717
Mathias Agopian65ab4712010-07-14 17:59:35 -07001718// ----------------------------------------------------------------------------
1719
Eric Laurenta4c5a552012-03-29 10:12:40 -07001720audio_module_handle_t AudioFlinger::loadHwModule(const char *name)
1721{
Eric Laurent44622db2014-08-01 19:00:33 -07001722 if (name == NULL) {
Glenn Kastena13cde92016-03-28 15:26:02 -07001723 return AUDIO_MODULE_HANDLE_NONE;
Eric Laurent44622db2014-08-01 19:00:33 -07001724 }
Eric Laurenta4c5a552012-03-29 10:12:40 -07001725 if (!settingsAllowed()) {
Glenn Kastena13cde92016-03-28 15:26:02 -07001726 return AUDIO_MODULE_HANDLE_NONE;
Eric Laurenta4c5a552012-03-29 10:12:40 -07001727 }
1728 Mutex::Autolock _l(mLock);
1729 return loadHwModule_l(name);
1730}
1731
1732// loadHwModule_l() must be called with AudioFlinger::mLock held
1733audio_module_handle_t AudioFlinger::loadHwModule_l(const char *name)
1734{
1735 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
1736 if (strncmp(mAudioHwDevs.valueAt(i)->moduleName(), name, strlen(name)) == 0) {
1737 ALOGW("loadHwModule() module %s already loaded", name);
1738 return mAudioHwDevs.keyAt(i);
1739 }
1740 }
1741
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001742 sp<DeviceHalInterface> dev;
Eric Laurenta4c5a552012-03-29 10:12:40 -07001743
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001744 int rc = mDevicesFactoryHal->openDevice(name, &dev);
Eric Laurenta4c5a552012-03-29 10:12:40 -07001745 if (rc) {
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001746 ALOGE("loadHwModule() error %d loading module %s", rc, name);
Glenn Kastena13cde92016-03-28 15:26:02 -07001747 return AUDIO_MODULE_HANDLE_NONE;
Eric Laurenta4c5a552012-03-29 10:12:40 -07001748 }
1749
1750 mHardwareStatus = AUDIO_HW_INIT;
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001751 rc = dev->initCheck();
Eric Laurenta4c5a552012-03-29 10:12:40 -07001752 mHardwareStatus = AUDIO_HW_IDLE;
1753 if (rc) {
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001754 ALOGE("loadHwModule() init check error %d for module %s", rc, name);
Glenn Kastena13cde92016-03-28 15:26:02 -07001755 return AUDIO_MODULE_HANDLE_NONE;
Eric Laurenta4c5a552012-03-29 10:12:40 -07001756 }
1757
John Grossmanee578c02012-07-23 17:05:46 -07001758 // Check and cache this HAL's level of support for master mute and master
1759 // volume. If this is the first HAL opened, and it supports the get
1760 // methods, use the initial values provided by the HAL as the current
1761 // master mute and volume settings.
1762
1763 AudioHwDevice::Flags flags = static_cast<AudioHwDevice::Flags>(0);
1764 { // scope for auto-lock pattern
Eric Laurenta4c5a552012-03-29 10:12:40 -07001765 AutoMutex lock(mHardwareLock);
John Grossmanee578c02012-07-23 17:05:46 -07001766
1767 if (0 == mAudioHwDevs.size()) {
1768 mHardwareStatus = AUDIO_HW_GET_MASTER_VOLUME;
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001769 float mv;
1770 if (OK == dev->getMasterVolume(&mv)) {
1771 mMasterVolume = mv;
John Grossmanee578c02012-07-23 17:05:46 -07001772 }
1773
1774 mHardwareStatus = AUDIO_HW_GET_MASTER_MUTE;
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001775 bool mm;
1776 if (OK == dev->getMasterMute(&mm)) {
1777 mMasterMute = mm;
John Grossmanee578c02012-07-23 17:05:46 -07001778 }
1779 }
1780
Eric Laurenta4c5a552012-03-29 10:12:40 -07001781 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001782 if (OK == dev->setMasterVolume(mMasterVolume)) {
John Grossmanee578c02012-07-23 17:05:46 -07001783 flags = static_cast<AudioHwDevice::Flags>(flags |
1784 AudioHwDevice::AHWD_CAN_SET_MASTER_VOLUME);
1785 }
1786
1787 mHardwareStatus = AUDIO_HW_SET_MASTER_MUTE;
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001788 if (OK == dev->setMasterMute(mMasterMute)) {
John Grossmanee578c02012-07-23 17:05:46 -07001789 flags = static_cast<AudioHwDevice::Flags>(flags |
1790 AudioHwDevice::AHWD_CAN_SET_MASTER_MUTE);
1791 }
1792
Eric Laurenta4c5a552012-03-29 10:12:40 -07001793 mHardwareStatus = AUDIO_HW_IDLE;
1794 }
1795
Glenn Kastena13cde92016-03-28 15:26:02 -07001796 audio_module_handle_t handle = (audio_module_handle_t) nextUniqueId(AUDIO_UNIQUE_ID_USE_MODULE);
Eric Laurent83b88082014-06-20 18:31:16 -07001797 mAudioHwDevs.add(handle, new AudioHwDevice(handle, name, dev, flags));
Eric Laurenta4c5a552012-03-29 10:12:40 -07001798
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001799 ALOGI("loadHwModule() Loaded %s audio interface, handle %d", name, handle);
Eric Laurenta4c5a552012-03-29 10:12:40 -07001800
1801 return handle;
1802
1803}
1804
Glenn Kastencc0f1cf2012-09-24 11:27:18 -07001805// ----------------------------------------------------------------------------
1806
Glenn Kasten3b16c762012-11-14 08:44:39 -08001807uint32_t AudioFlinger::getPrimaryOutputSamplingRate()
Glenn Kastencc0f1cf2012-09-24 11:27:18 -07001808{
1809 Mutex::Autolock _l(mLock);
Glenn Kastena7335632016-06-09 17:09:53 -07001810 PlaybackThread *thread = fastPlaybackThread_l();
Glenn Kastencc0f1cf2012-09-24 11:27:18 -07001811 return thread != NULL ? thread->sampleRate() : 0;
1812}
1813
Glenn Kastene33054e2012-11-14 12:54:39 -08001814size_t AudioFlinger::getPrimaryOutputFrameCount()
Glenn Kastencc0f1cf2012-09-24 11:27:18 -07001815{
1816 Mutex::Autolock _l(mLock);
Glenn Kastena7335632016-06-09 17:09:53 -07001817 PlaybackThread *thread = fastPlaybackThread_l();
Glenn Kastencc0f1cf2012-09-24 11:27:18 -07001818 return thread != NULL ? thread->frameCountHAL() : 0;
1819}
1820
1821// ----------------------------------------------------------------------------
1822
Glenn Kasten4182c4e2013-07-15 14:45:07 -07001823status_t AudioFlinger::setLowRamDevice(bool isLowRamDevice)
1824{
1825 uid_t uid = IPCThreadState::self()->getCallingUid();
1826 if (uid != AID_SYSTEM) {
1827 return PERMISSION_DENIED;
1828 }
1829 Mutex::Autolock _l(mLock);
1830 if (mIsDeviceTypeKnown) {
1831 return INVALID_OPERATION;
1832 }
1833 mIsLowRamDevice = isLowRamDevice;
1834 mIsDeviceTypeKnown = true;
1835 return NO_ERROR;
1836}
1837
Eric Laurent93c3d412014-08-01 14:48:35 -07001838audio_hw_sync_t AudioFlinger::getAudioHwSyncForSession(audio_session_t sessionId)
1839{
1840 Mutex::Autolock _l(mLock);
Eric Laurentfa90e842014-10-17 18:12:31 -07001841
1842 ssize_t index = mHwAvSyncIds.indexOfKey(sessionId);
1843 if (index >= 0) {
1844 ALOGV("getAudioHwSyncForSession found ID %d for session %d",
1845 mHwAvSyncIds.valueAt(index), sessionId);
1846 return mHwAvSyncIds.valueAt(index);
1847 }
1848
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001849 sp<DeviceHalInterface> dev = mPrimaryHardwareDev->hwDevice();
Eric Laurentfa90e842014-10-17 18:12:31 -07001850 if (dev == NULL) {
1851 return AUDIO_HW_SYNC_INVALID;
1852 }
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001853 String8 reply;
1854 AudioParameter param;
Mikhail Naganov00260b52016-10-13 12:54:24 -07001855 if (dev->getParameters(String8(AudioParameter::keyHwAvSync), &reply) == OK) {
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001856 param = AudioParameter(reply);
1857 }
Eric Laurentfa90e842014-10-17 18:12:31 -07001858
1859 int value;
Mikhail Naganov00260b52016-10-13 12:54:24 -07001860 if (param.getInt(String8(AudioParameter::keyHwAvSync), value) != NO_ERROR) {
Eric Laurentfa90e842014-10-17 18:12:31 -07001861 ALOGW("getAudioHwSyncForSession error getting sync for session %d", sessionId);
1862 return AUDIO_HW_SYNC_INVALID;
1863 }
1864
1865 // allow only one session for a given HW A/V sync ID.
1866 for (size_t i = 0; i < mHwAvSyncIds.size(); i++) {
1867 if (mHwAvSyncIds.valueAt(i) == (audio_hw_sync_t)value) {
1868 ALOGV("getAudioHwSyncForSession removing ID %d for session %d",
1869 value, mHwAvSyncIds.keyAt(i));
1870 mHwAvSyncIds.removeItemsAt(i);
Eric Laurent93c3d412014-08-01 14:48:35 -07001871 break;
1872 }
1873 }
Eric Laurentfa90e842014-10-17 18:12:31 -07001874
1875 mHwAvSyncIds.add(sessionId, value);
1876
1877 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
1878 sp<PlaybackThread> thread = mPlaybackThreads.valueAt(i);
1879 uint32_t sessions = thread->hasAudioSession(sessionId);
Eric Laurent4c415062016-06-17 16:14:16 -07001880 if (sessions & ThreadBase::TRACK_SESSION) {
Eric Laurentfa90e842014-10-17 18:12:31 -07001881 AudioParameter param = AudioParameter();
Mikhail Naganov00260b52016-10-13 12:54:24 -07001882 param.addInt(String8(AudioParameter::keyStreamHwAvSync), value);
Eric Laurentfa90e842014-10-17 18:12:31 -07001883 thread->setParameters(param.toString());
1884 break;
1885 }
1886 }
1887
1888 ALOGV("getAudioHwSyncForSession adding ID %d for session %d", value, sessionId);
1889 return (audio_hw_sync_t)value;
Eric Laurent93c3d412014-08-01 14:48:35 -07001890}
1891
Eric Laurent72e3f392015-05-20 14:43:50 -07001892status_t AudioFlinger::systemReady()
1893{
1894 Mutex::Autolock _l(mLock);
1895 ALOGI("%s", __FUNCTION__);
1896 if (mSystemReady) {
1897 ALOGW("%s called twice", __FUNCTION__);
1898 return NO_ERROR;
1899 }
1900 mSystemReady = true;
1901 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
1902 ThreadBase *thread = (ThreadBase *)mPlaybackThreads.valueAt(i).get();
1903 thread->systemReady();
1904 }
1905 for (size_t i = 0; i < mRecordThreads.size(); i++) {
1906 ThreadBase *thread = (ThreadBase *)mRecordThreads.valueAt(i).get();
1907 thread->systemReady();
1908 }
1909 return NO_ERROR;
1910}
1911
Eric Laurentfa90e842014-10-17 18:12:31 -07001912// setAudioHwSyncForSession_l() must be called with AudioFlinger::mLock held
1913void AudioFlinger::setAudioHwSyncForSession_l(PlaybackThread *thread, audio_session_t sessionId)
1914{
1915 ssize_t index = mHwAvSyncIds.indexOfKey(sessionId);
1916 if (index >= 0) {
1917 audio_hw_sync_t syncId = mHwAvSyncIds.valueAt(index);
1918 ALOGV("setAudioHwSyncForSession_l found ID %d for session %d", syncId, sessionId);
1919 AudioParameter param = AudioParameter();
Mikhail Naganov00260b52016-10-13 12:54:24 -07001920 param.addInt(String8(AudioParameter::keyStreamHwAvSync), syncId);
Eric Laurentfa90e842014-10-17 18:12:31 -07001921 thread->setParameters(param.toString());
1922 }
1923}
1924
1925
Glenn Kasten4182c4e2013-07-15 14:45:07 -07001926// ----------------------------------------------------------------------------
1927
Eric Laurent83b88082014-06-20 18:31:16 -07001928
Eric Laurent6acd1d42017-01-04 14:23:29 -08001929sp<AudioFlinger::ThreadBase> AudioFlinger::openOutput_l(audio_module_handle_t module,
Eric Laurentcf2c0212014-07-25 16:20:43 -07001930 audio_io_handle_t *output,
1931 audio_config_t *config,
1932 audio_devices_t devices,
1933 const String8& address,
Eric Laurent83b88082014-06-20 18:31:16 -07001934 audio_output_flags_t flags)
1935{
Eric Laurentcf2c0212014-07-25 16:20:43 -07001936 AudioHwDevice *outHwDev = findSuitableHwDev_l(module, devices);
Eric Laurent83b88082014-06-20 18:31:16 -07001937 if (outHwDev == NULL) {
Eric Laurentcf2c0212014-07-25 16:20:43 -07001938 return 0;
Eric Laurent83b88082014-06-20 18:31:16 -07001939 }
1940
Eric Laurentcf2c0212014-07-25 16:20:43 -07001941 if (*output == AUDIO_IO_HANDLE_NONE) {
Glenn Kasteneeecb982016-02-26 10:44:04 -08001942 *output = nextUniqueId(AUDIO_UNIQUE_ID_USE_OUTPUT);
1943 } else {
1944 // Audio Policy does not currently request a specific output handle.
1945 // If this is ever needed, see openInput_l() for example code.
1946 ALOGE("openOutput_l requested output handle %d is not AUDIO_IO_HANDLE_NONE", *output);
1947 return 0;
Eric Laurentcf2c0212014-07-25 16:20:43 -07001948 }
Eric Laurent83b88082014-06-20 18:31:16 -07001949
1950 mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
1951
Eric Laurent83b88082014-06-20 18:31:16 -07001952 // FOR TESTING ONLY:
Andy Hung9a592762014-07-21 21:56:01 -07001953 // This if statement allows overriding the audio policy settings
1954 // and forcing a specific format or channel mask to the HAL/Sink device for testing.
1955 if (!(flags & (AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD | AUDIO_OUTPUT_FLAG_DIRECT))) {
1956 // Check only for Normal Mixing mode
1957 if (kEnableExtendedPrecision) {
1958 // Specify format (uncomment one below to choose)
1959 //config->format = AUDIO_FORMAT_PCM_FLOAT;
1960 //config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1961 //config->format = AUDIO_FORMAT_PCM_32_BIT;
1962 //config->format = AUDIO_FORMAT_PCM_8_24_BIT;
Eric Laurentcf2c0212014-07-25 16:20:43 -07001963 // ALOGV("openOutput_l() upgrading format to %#08x", config->format);
Andy Hung9a592762014-07-21 21:56:01 -07001964 }
1965 if (kEnableExtendedChannels) {
1966 // Specify channel mask (uncomment one below to choose)
1967 //config->channel_mask = audio_channel_out_mask_from_count(4); // for USB 4ch
1968 //config->channel_mask = audio_channel_mask_from_representation_and_bits(
1969 // AUDIO_CHANNEL_REPRESENTATION_INDEX, (1 << 4) - 1); // another 4ch example
1970 }
Eric Laurent83b88082014-06-20 18:31:16 -07001971 }
1972
Phil Burk062e67a2015-02-11 13:40:50 -08001973 AudioStreamOut *outputStream = NULL;
1974 status_t status = outHwDev->openOutputStream(
1975 &outputStream,
1976 *output,
1977 devices,
1978 flags,
1979 config,
1980 address.string());
Eric Laurent83b88082014-06-20 18:31:16 -07001981
1982 mHardwareStatus = AUDIO_HW_IDLE;
Eric Laurent83b88082014-06-20 18:31:16 -07001983
Phil Burk062e67a2015-02-11 13:40:50 -08001984 if (status == NO_ERROR) {
Eric Laurent6acd1d42017-01-04 14:23:29 -08001985 if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
1986 sp<MmapPlaybackThread> thread =
1987 new MmapPlaybackThread(this, *output, outHwDev, outputStream,
1988 devices, AUDIO_DEVICE_NONE, mSystemReady);
1989 mMmapThreads.add(*output, thread);
1990 ALOGV("openOutput_l() created mmap playback thread: ID %d thread %p",
1991 *output, thread.get());
1992 return thread;
Eric Laurent83b88082014-06-20 18:31:16 -07001993 } else {
Eric Laurent6acd1d42017-01-04 14:23:29 -08001994 sp<PlaybackThread> thread;
1995 if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
1996 thread = new OffloadThread(this, outputStream, *output, devices, mSystemReady);
1997 ALOGV("openOutput_l() created offload output: ID %d thread %p",
1998 *output, thread.get());
1999 } else if ((flags & AUDIO_OUTPUT_FLAG_DIRECT)
2000 || !isValidPcmSinkFormat(config->format)
2001 || !isValidPcmSinkChannelMask(config->channel_mask)) {
2002 thread = new DirectOutputThread(this, outputStream, *output, devices, mSystemReady);
2003 ALOGV("openOutput_l() created direct output: ID %d thread %p",
2004 *output, thread.get());
2005 } else {
2006 thread = new MixerThread(this, outputStream, *output, devices, mSystemReady);
2007 ALOGV("openOutput_l() created mixer output: ID %d thread %p",
2008 *output, thread.get());
2009 }
2010 mPlaybackThreads.add(*output, thread);
2011 return thread;
Eric Laurent83b88082014-06-20 18:31:16 -07002012 }
Eric Laurent83b88082014-06-20 18:31:16 -07002013 }
2014
2015 return 0;
2016}
2017
Eric Laurentcf2c0212014-07-25 16:20:43 -07002018status_t AudioFlinger::openOutput(audio_module_handle_t module,
2019 audio_io_handle_t *output,
2020 audio_config_t *config,
2021 audio_devices_t *devices,
2022 const String8& address,
2023 uint32_t *latencyMs,
2024 audio_output_flags_t flags)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002025{
Glenn Kastend3bb6452016-12-05 18:14:37 -08002026 ALOGI("openOutput() this %p, module %d Device %x, SamplingRate %d, Format %#08x, Channels %x, "
2027 "flags %x",
Eric Laurent6acd1d42017-01-04 14:23:29 -08002028 this, module,
Eric Laurentcf2c0212014-07-25 16:20:43 -07002029 (devices != NULL) ? *devices : 0,
2030 config->sample_rate,
2031 config->format,
2032 config->channel_mask,
Eric Laurenta4c5a552012-03-29 10:12:40 -07002033 flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002034
Yunlian Jiang32ba9862017-01-31 15:55:00 -08002035 if (devices == NULL || *devices == AUDIO_DEVICE_NONE) {
Eric Laurentcf2c0212014-07-25 16:20:43 -07002036 return BAD_VALUE;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002037 }
Dima Zavin799a70e2011-04-18 16:57:27 -07002038
Mathias Agopian65ab4712010-07-14 17:59:35 -07002039 Mutex::Autolock _l(mLock);
2040
Eric Laurent6acd1d42017-01-04 14:23:29 -08002041 sp<ThreadBase> thread = openOutput_l(module, output, config, *devices, address, flags);
Eric Laurent83b88082014-06-20 18:31:16 -07002042 if (thread != 0) {
Eric Laurent6acd1d42017-01-04 14:23:29 -08002043 if ((flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0) {
2044 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
2045 *latencyMs = playbackThread->latency();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002046
Eric Laurent6acd1d42017-01-04 14:23:29 -08002047 // notify client processes of the new output creation
2048 playbackThread->ioConfigChanged(AUDIO_OUTPUT_OPENED);
Eric Laurenta4c5a552012-03-29 10:12:40 -07002049
Eric Laurent6acd1d42017-01-04 14:23:29 -08002050 // the first primary output opened designates the primary hw device
2051 if ((mPrimaryHardwareDev == NULL) && (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
2052 ALOGI("Using module %d has the primary audio interface", module);
2053 mPrimaryHardwareDev = playbackThread->getOutput()->audioHwDev;
Eric Laurenta4c5a552012-03-29 10:12:40 -07002054
Eric Laurent6acd1d42017-01-04 14:23:29 -08002055 AutoMutex lock(mHardwareLock);
2056 mHardwareStatus = AUDIO_HW_SET_MODE;
2057 mPrimaryHardwareDev->hwDevice()->setMode(mMode);
2058 mHardwareStatus = AUDIO_HW_IDLE;
2059 }
2060 } else {
2061 MmapThread *mmapThread = (MmapThread *)thread.get();
2062 mmapThread->ioConfigChanged(AUDIO_OUTPUT_OPENED);
Eric Laurenta4c5a552012-03-29 10:12:40 -07002063 }
Eric Laurentcf2c0212014-07-25 16:20:43 -07002064 return NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002065 }
2066
Eric Laurentcf2c0212014-07-25 16:20:43 -07002067 return NO_INIT;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002068}
2069
Glenn Kasten72ef00d2012-01-17 11:09:42 -08002070audio_io_handle_t AudioFlinger::openDuplicateOutput(audio_io_handle_t output1,
2071 audio_io_handle_t output2)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002072{
2073 Mutex::Autolock _l(mLock);
2074 MixerThread *thread1 = checkMixerThread_l(output1);
2075 MixerThread *thread2 = checkMixerThread_l(output2);
2076
2077 if (thread1 == NULL || thread2 == NULL) {
Glenn Kasten85ab62c2012-11-01 11:11:38 -07002078 ALOGW("openDuplicateOutput() wrong output mixer type for output %d or %d", output1,
2079 output2);
Glenn Kasten142f5192014-03-25 17:44:59 -07002080 return AUDIO_IO_HANDLE_NONE;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002081 }
2082
Glenn Kasteneeecb982016-02-26 10:44:04 -08002083 audio_io_handle_t id = nextUniqueId(AUDIO_UNIQUE_ID_USE_OUTPUT);
Eric Laurent72e3f392015-05-20 14:43:50 -07002084 DuplicatingThread *thread = new DuplicatingThread(this, thread1, id, mSystemReady);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002085 thread->addOutputTrack(thread2);
2086 mPlaybackThreads.add(id, thread);
2087 // notify client processes of the new output creation
Eric Laurent73e26b62015-04-27 16:55:58 -07002088 thread->ioConfigChanged(AUDIO_OUTPUT_OPENED);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002089 return id;
2090}
2091
Glenn Kasten72ef00d2012-01-17 11:09:42 -08002092status_t AudioFlinger::closeOutput(audio_io_handle_t output)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002093{
Glenn Kastend96c5722012-04-25 13:44:49 -07002094 return closeOutput_nonvirtual(output);
2095}
2096
2097status_t AudioFlinger::closeOutput_nonvirtual(audio_io_handle_t output)
2098{
Mathias Agopian65ab4712010-07-14 17:59:35 -07002099 // keep strong reference on the playback thread so that
2100 // it is not destroyed while exit() is executed
Eric Laurent6acd1d42017-01-04 14:23:29 -08002101 sp<PlaybackThread> playbackThread;
2102 sp<MmapPlaybackThread> mmapThread;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002103 {
2104 Mutex::Autolock _l(mLock);
Eric Laurent6acd1d42017-01-04 14:23:29 -08002105 playbackThread = checkPlaybackThread_l(output);
2106 if (playbackThread != NULL) {
2107 ALOGV("closeOutput() %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002108
Eric Laurent6acd1d42017-01-04 14:23:29 -08002109 if (playbackThread->type() == ThreadBase::MIXER) {
2110 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
2111 if (mPlaybackThreads.valueAt(i)->isDuplicating()) {
2112 DuplicatingThread *dupThread =
2113 (DuplicatingThread *)mPlaybackThreads.valueAt(i).get();
2114 dupThread->removeOutputTrack((MixerThread *)playbackThread.get());
2115 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08002116 }
2117 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08002118
2119
Eric Laurent6acd1d42017-01-04 14:23:29 -08002120 mPlaybackThreads.removeItem(output);
2121 // save all effects to the default thread
2122 if (mPlaybackThreads.size()) {
2123 PlaybackThread *dstThread = checkPlaybackThread_l(mPlaybackThreads.keyAt(0));
2124 if (dstThread != NULL) {
Glenn Kastend3bb6452016-12-05 18:14:37 -08002125 // audioflinger lock is held so order of thread lock acquisition doesn't matter
Eric Laurent6acd1d42017-01-04 14:23:29 -08002126 Mutex::Autolock _dl(dstThread->mLock);
2127 Mutex::Autolock _sl(playbackThread->mLock);
2128 Vector< sp<EffectChain> > effectChains = playbackThread->getEffectChains_l();
2129 for (size_t i = 0; i < effectChains.size(); i ++) {
Glenn Kastend3bb6452016-12-05 18:14:37 -08002130 moveEffectChain_l(effectChains[i]->sessionId(), playbackThread.get(),
2131 dstThread, true);
Eric Laurent6acd1d42017-01-04 14:23:29 -08002132 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002133 }
2134 }
Eric Laurent6acd1d42017-01-04 14:23:29 -08002135 } else {
2136 mmapThread = (MmapPlaybackThread *)checkMmapThread_l(output);
2137 if (mmapThread == 0) {
2138 return BAD_VALUE;
2139 }
2140 mMmapThreads.removeItem(output);
2141 ALOGV("closing mmapThread %p", mmapThread.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002142 }
Eric Laurent73e26b62015-04-27 16:55:58 -07002143 const sp<AudioIoDescriptor> ioDesc = new AudioIoDescriptor();
2144 ioDesc->mIoHandle = output;
2145 ioConfigChanged(AUDIO_OUTPUT_CLOSED, ioDesc);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002146 }
Glenn Kastenb28686f2012-01-06 08:39:38 -08002147 // The thread entity (active unit of execution) is no longer running here,
2148 // but the ThreadBase container still exists.
Mathias Agopian65ab4712010-07-14 17:59:35 -07002149
Eric Laurent6acd1d42017-01-04 14:23:29 -08002150 if (playbackThread != 0) {
2151 playbackThread->exit();
2152 if (!playbackThread->isDuplicating()) {
2153 closeOutputFinish(playbackThread);
2154 }
2155 } else if (mmapThread != 0) {
2156 ALOGV("mmapThread exit()");
2157 mmapThread->exit();
2158 AudioStreamOut *out = mmapThread->clearOutput();
2159 ALOG_ASSERT(out != NULL, "out shouldn't be NULL");
2160 // from now on thread->mOutput is NULL
2161 delete out;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002162 }
2163 return NO_ERROR;
2164}
2165
Chih-Hung Hsieh36d0ca12016-08-09 14:31:32 -07002166void AudioFlinger::closeOutputFinish(const sp<PlaybackThread>& thread)
Eric Laurent83b88082014-06-20 18:31:16 -07002167{
2168 AudioStreamOut *out = thread->clearOutput();
2169 ALOG_ASSERT(out != NULL, "out shouldn't be NULL");
2170 // from now on thread->mOutput is NULL
Eric Laurent83b88082014-06-20 18:31:16 -07002171 delete out;
2172}
2173
Chih-Hung Hsieh36d0ca12016-08-09 14:31:32 -07002174void AudioFlinger::closeOutputInternal_l(const sp<PlaybackThread>& thread)
Eric Laurent83b88082014-06-20 18:31:16 -07002175{
2176 mPlaybackThreads.removeItem(thread->mId);
2177 thread->exit();
2178 closeOutputFinish(thread);
2179}
2180
Glenn Kasten72ef00d2012-01-17 11:09:42 -08002181status_t AudioFlinger::suspendOutput(audio_io_handle_t output)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002182{
2183 Mutex::Autolock _l(mLock);
2184 PlaybackThread *thread = checkPlaybackThread_l(output);
2185
2186 if (thread == NULL) {
2187 return BAD_VALUE;
2188 }
2189
Steve Block3856b092011-10-20 11:56:00 +01002190 ALOGV("suspendOutput() %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002191 thread->suspend();
2192
2193 return NO_ERROR;
2194}
2195
Glenn Kasten72ef00d2012-01-17 11:09:42 -08002196status_t AudioFlinger::restoreOutput(audio_io_handle_t output)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002197{
2198 Mutex::Autolock _l(mLock);
2199 PlaybackThread *thread = checkPlaybackThread_l(output);
2200
2201 if (thread == NULL) {
2202 return BAD_VALUE;
2203 }
2204
Steve Block3856b092011-10-20 11:56:00 +01002205 ALOGV("restoreOutput() %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002206
2207 thread->restore();
2208
2209 return NO_ERROR;
2210}
2211
Eric Laurentcf2c0212014-07-25 16:20:43 -07002212status_t AudioFlinger::openInput(audio_module_handle_t module,
2213 audio_io_handle_t *input,
2214 audio_config_t *config,
Glenn Kastene7d66712015-03-05 13:46:52 -08002215 audio_devices_t *devices,
Eric Laurentcf2c0212014-07-25 16:20:43 -07002216 const String8& address,
2217 audio_source_t source,
Glenn Kastenec40d282014-07-15 15:31:26 -07002218 audio_input_flags_t flags)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002219{
Eric Laurent83b88082014-06-20 18:31:16 -07002220 Mutex::Autolock _l(mLock);
2221
Glenn Kastene7d66712015-03-05 13:46:52 -08002222 if (*devices == AUDIO_DEVICE_NONE) {
Eric Laurentcf2c0212014-07-25 16:20:43 -07002223 return BAD_VALUE;
Eric Laurent83b88082014-06-20 18:31:16 -07002224 }
2225
Eric Laurent6acd1d42017-01-04 14:23:29 -08002226 sp<ThreadBase> thread = openInput_l(module, input, config, *devices, address, source, flags);
Eric Laurent83b88082014-06-20 18:31:16 -07002227
2228 if (thread != 0) {
Eric Laurent83b88082014-06-20 18:31:16 -07002229 // notify client processes of the new input creation
Eric Laurent73e26b62015-04-27 16:55:58 -07002230 thread->ioConfigChanged(AUDIO_INPUT_OPENED);
Eric Laurentcf2c0212014-07-25 16:20:43 -07002231 return NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002232 }
Eric Laurentcf2c0212014-07-25 16:20:43 -07002233 return NO_INIT;
Eric Laurent83b88082014-06-20 18:31:16 -07002234}
Dima Zavin799a70e2011-04-18 16:57:27 -07002235
Eric Laurent6acd1d42017-01-04 14:23:29 -08002236sp<AudioFlinger::ThreadBase> AudioFlinger::openInput_l(audio_module_handle_t module,
Eric Laurentcf2c0212014-07-25 16:20:43 -07002237 audio_io_handle_t *input,
2238 audio_config_t *config,
Glenn Kastene7d66712015-03-05 13:46:52 -08002239 audio_devices_t devices,
Eric Laurentcf2c0212014-07-25 16:20:43 -07002240 const String8& address,
2241 audio_source_t source,
Eric Laurent83b88082014-06-20 18:31:16 -07002242 audio_input_flags_t flags)
2243{
Glenn Kastene7d66712015-03-05 13:46:52 -08002244 AudioHwDevice *inHwDev = findSuitableHwDev_l(module, devices);
Glenn Kasten6e2ebe92013-08-13 09:14:51 -07002245 if (inHwDev == NULL) {
Eric Laurentcf2c0212014-07-25 16:20:43 -07002246 *input = AUDIO_IO_HANDLE_NONE;
Dima Zavin799a70e2011-04-18 16:57:27 -07002247 return 0;
Glenn Kasten6e2ebe92013-08-13 09:14:51 -07002248 }
Dima Zavin799a70e2011-04-18 16:57:27 -07002249
Glenn Kasteneeecb982016-02-26 10:44:04 -08002250 // Audio Policy can request a specific handle for hardware hotword.
2251 // The goal here is not to re-open an already opened input.
2252 // It is to use a pre-assigned I/O handle.
Eric Laurentcf2c0212014-07-25 16:20:43 -07002253 if (*input == AUDIO_IO_HANDLE_NONE) {
Glenn Kasteneeecb982016-02-26 10:44:04 -08002254 *input = nextUniqueId(AUDIO_UNIQUE_ID_USE_INPUT);
2255 } else if (audio_unique_id_get_use(*input) != AUDIO_UNIQUE_ID_USE_INPUT) {
2256 ALOGE("openInput_l() requested input handle %d is invalid", *input);
2257 return 0;
2258 } else if (mRecordThreads.indexOfKey(*input) >= 0) {
2259 // This should not happen in a transient state with current design.
2260 ALOGE("openInput_l() requested input handle %d is already assigned", *input);
2261 return 0;
Eric Laurentcf2c0212014-07-25 16:20:43 -07002262 }
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07002263
Eric Laurentcf2c0212014-07-25 16:20:43 -07002264 audio_config_t halconfig = *config;
Mikhail Naganove4f1f632016-08-31 11:35:10 -07002265 sp<DeviceHalInterface> inHwHal = inHwDev->hwDevice();
Mikhail Naganov1dc98672016-08-18 17:50:29 -07002266 sp<StreamInHalInterface> inStream;
2267 status_t status = inHwHal->openInputStream(
Mikhail Naganove4f1f632016-08-31 11:35:10 -07002268 *input, devices, &halconfig, flags, address.string(), source, &inStream);
Mikhail Naganovf558e022016-11-14 17:45:17 -08002269 ALOGV("openInput_l() openInputStream returned input %p, devices %x, SamplingRate %d"
Jean-Michel Trivifd4c1482014-08-06 16:02:28 -07002270 ", Format %#x, Channels %x, flags %#x, status %d addr %s",
Mikhail Naganov1dc98672016-08-18 17:50:29 -07002271 inStream.get(),
Mikhail Naganovf558e022016-11-14 17:45:17 -08002272 devices,
Eric Laurentcf2c0212014-07-25 16:20:43 -07002273 halconfig.sample_rate,
2274 halconfig.format,
2275 halconfig.channel_mask,
Glenn Kastenec40d282014-07-15 15:31:26 -07002276 flags,
Jean-Michel Trivifd4c1482014-08-06 16:02:28 -07002277 status, address.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002278
Glenn Kasten85ab62c2012-11-01 11:11:38 -07002279 // If the input could not be opened with the requested parameters and we can handle the
Andy Hung6770c6f2015-04-07 13:43:36 -07002280 // conversion internally, try to open again with the proposed parameters.
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07002281 if (status == BAD_VALUE &&
Andy Hung6770c6f2015-04-07 13:43:36 -07002282 audio_is_linear_pcm(config->format) &&
2283 audio_is_linear_pcm(halconfig.format) &&
2284 (halconfig.sample_rate <= AUDIO_RESAMPLER_DOWN_RATIO_MAX * config->sample_rate) &&
vivek mehta75346662016-05-04 18:45:46 -07002285 (audio_channel_count_from_in_mask(halconfig.channel_mask) <= FCC_8) &&
2286 (audio_channel_count_from_in_mask(config->channel_mask) <= FCC_8)) {
Glenn Kasten85948432013-08-19 12:09:05 -07002287 // FIXME describe the change proposed by HAL (save old values so we can log them here)
Eric Laurentcf2c0212014-07-25 16:20:43 -07002288 ALOGV("openInput_l() reopening with proposed sampling rate and channel mask");
Mikhail Naganov1dc98672016-08-18 17:50:29 -07002289 inStream.clear();
2290 status = inHwHal->openInputStream(
Mikhail Naganove4f1f632016-08-31 11:35:10 -07002291 *input, devices, &halconfig, flags, address.string(), source, &inStream);
Glenn Kasten85948432013-08-19 12:09:05 -07002292 // FIXME log this new status; HAL should not propose any further changes
Mathias Agopian65ab4712010-07-14 17:59:35 -07002293 }
2294
Mikhail Naganov1dc98672016-08-18 17:50:29 -07002295 if (status == NO_ERROR && inStream != 0) {
Eric Laurent05067782016-06-01 18:27:28 -07002296 AudioStreamIn *inputStream = new AudioStreamIn(inHwDev, inStream, flags);
Eric Laurent6acd1d42017-01-04 14:23:29 -08002297 if ((flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0) {
2298 sp<MmapCaptureThread> thread =
2299 new MmapCaptureThread(this, *input,
2300 inHwDev, inputStream,
2301 primaryOutputDevice_l(), devices, mSystemReady);
2302 mMmapThreads.add(*input, thread);
Glenn Kastend3bb6452016-12-05 18:14:37 -08002303 ALOGV("openInput_l() created mmap capture thread: ID %d thread %p", *input,
2304 thread.get());
Eric Laurent6acd1d42017-01-04 14:23:29 -08002305 return thread;
2306 } else {
Glenn Kasten46909e72013-02-26 09:20:22 -08002307#ifdef TEE_SINK
Eric Laurent6acd1d42017-01-04 14:23:29 -08002308 // Try to re-use most recently used Pipe to archive a copy of input for dumpsys,
2309 // or (re-)create if current Pipe is idle and does not match the new format
2310 sp<NBAIO_Sink> teeSink;
2311 enum {
2312 TEE_SINK_NO, // don't copy input
2313 TEE_SINK_NEW, // copy input using a new pipe
2314 TEE_SINK_OLD, // copy input using an existing pipe
2315 } kind;
2316 NBAIO_Format format = Format_from_SR_C(halconfig.sample_rate,
2317 audio_channel_count_from_in_mask(halconfig.channel_mask), halconfig.format);
2318 if (!mTeeSinkInputEnabled) {
2319 kind = TEE_SINK_NO;
2320 } else if (!Format_isValid(format)) {
2321 kind = TEE_SINK_NO;
2322 } else if (mRecordTeeSink == 0) {
2323 kind = TEE_SINK_NEW;
2324 } else if (mRecordTeeSink->getStrongCount() != 1) {
2325 kind = TEE_SINK_NO;
2326 } else if (Format_isEqual(format, mRecordTeeSink->format())) {
2327 kind = TEE_SINK_OLD;
2328 } else {
2329 kind = TEE_SINK_NEW;
2330 }
2331 switch (kind) {
2332 case TEE_SINK_NEW: {
2333 Pipe *pipe = new Pipe(mTeeSinkInputFrames, format);
2334 size_t numCounterOffers = 0;
2335 const NBAIO_Format offers[1] = {format};
2336 ssize_t index = pipe->negotiate(offers, 1, NULL, numCounterOffers);
2337 ALOG_ASSERT(index == 0);
2338 PipeReader *pipeReader = new PipeReader(*pipe);
2339 numCounterOffers = 0;
2340 index = pipeReader->negotiate(offers, 1, NULL, numCounterOffers);
2341 ALOG_ASSERT(index == 0);
2342 mRecordTeeSink = pipe;
2343 mRecordTeeSource = pipeReader;
2344 teeSink = pipe;
2345 }
2346 break;
2347 case TEE_SINK_OLD:
2348 teeSink = mRecordTeeSink;
2349 break;
2350 case TEE_SINK_NO:
2351 default:
2352 break;
2353 }
Glenn Kasten46909e72013-02-26 09:20:22 -08002354#endif
Eric Laurent6acd1d42017-01-04 14:23:29 -08002355
2356 // Start record thread
2357 // RecordThread requires both input and output device indication to forward to audio
2358 // pre processing modules
2359 sp<RecordThread> thread = new RecordThread(this,
2360 inputStream,
2361 *input,
2362 primaryOutputDevice_l(),
2363 devices,
2364 mSystemReady
2365#ifdef TEE_SINK
2366 , teeSink
2367#endif
2368 );
2369 mRecordThreads.add(*input, thread);
2370 ALOGV("openInput_l() created record thread: ID %d thread %p", *input, thread.get());
2371 return thread;
2372 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002373 }
2374
Eric Laurentcf2c0212014-07-25 16:20:43 -07002375 *input = AUDIO_IO_HANDLE_NONE;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002376 return 0;
2377}
2378
Glenn Kasten72ef00d2012-01-17 11:09:42 -08002379status_t AudioFlinger::closeInput(audio_io_handle_t input)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002380{
Glenn Kastend96c5722012-04-25 13:44:49 -07002381 return closeInput_nonvirtual(input);
2382}
2383
2384status_t AudioFlinger::closeInput_nonvirtual(audio_io_handle_t input)
2385{
Mathias Agopian65ab4712010-07-14 17:59:35 -07002386 // keep strong reference on the record thread so that
2387 // it is not destroyed while exit() is executed
Eric Laurent6acd1d42017-01-04 14:23:29 -08002388 sp<RecordThread> recordThread;
2389 sp<MmapCaptureThread> mmapThread;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002390 {
2391 Mutex::Autolock _l(mLock);
Eric Laurent6acd1d42017-01-04 14:23:29 -08002392 recordThread = checkRecordThread_l(input);
2393 if (recordThread != 0) {
2394 ALOGV("closeInput() %d", input);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002395
Eric Laurent6acd1d42017-01-04 14:23:29 -08002396 // If we still have effect chains, it means that a client still holds a handle
2397 // on at least one effect. We must either move the chain to an existing thread with the
2398 // same session ID or put it aside in case a new record thread is opened for a
2399 // new capture on the same session
2400 sp<EffectChain> chain;
2401 {
2402 Mutex::Autolock _sl(recordThread->mLock);
2403 Vector< sp<EffectChain> > effectChains = recordThread->getEffectChains_l();
2404 // Note: maximum one chain per record thread
2405 if (effectChains.size() != 0) {
2406 chain = effectChains[0];
Eric Laurent1b928682014-10-02 19:41:47 -07002407 }
2408 }
Eric Laurent6acd1d42017-01-04 14:23:29 -08002409 if (chain != 0) {
Glenn Kastend3bb6452016-12-05 18:14:37 -08002410 // first check if a record thread is already opened with a client on same session.
Eric Laurent6acd1d42017-01-04 14:23:29 -08002411 // This should only happen in case of overlap between one thread tear down and the
2412 // creation of its replacement
2413 size_t i;
2414 for (i = 0; i < mRecordThreads.size(); i++) {
2415 sp<RecordThread> t = mRecordThreads.valueAt(i);
2416 if (t == recordThread) {
2417 continue;
2418 }
2419 if (t->hasAudioSession(chain->sessionId()) != 0) {
2420 Mutex::Autolock _l(t->mLock);
2421 ALOGV("closeInput() found thread %d for effect session %d",
2422 t->id(), chain->sessionId());
2423 t->addEffectChain_l(chain);
2424 break;
2425 }
2426 }
Glenn Kastend3bb6452016-12-05 18:14:37 -08002427 // put the chain aside if we could not find a record thread with the same session id
Eric Laurent6acd1d42017-01-04 14:23:29 -08002428 if (i == mRecordThreads.size()) {
2429 putOrphanEffectChain_l(chain);
2430 }
Eric Laurentaaa44472014-09-12 17:41:50 -07002431 }
Eric Laurent6acd1d42017-01-04 14:23:29 -08002432 mRecordThreads.removeItem(input);
2433 } else {
2434 mmapThread = (MmapCaptureThread *)checkMmapThread_l(input);
2435 if (mmapThread == 0) {
2436 return BAD_VALUE;
2437 }
2438 mMmapThreads.removeItem(input);
Eric Laurentaaa44472014-09-12 17:41:50 -07002439 }
Eric Laurent73e26b62015-04-27 16:55:58 -07002440 const sp<AudioIoDescriptor> ioDesc = new AudioIoDescriptor();
2441 ioDesc->mIoHandle = input;
2442 ioConfigChanged(AUDIO_INPUT_CLOSED, ioDesc);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002443 }
Eric Laurent83b88082014-06-20 18:31:16 -07002444 // FIXME: calling thread->exit() without mLock held should not be needed anymore now that
2445 // we have a different lock for notification client
Eric Laurent6acd1d42017-01-04 14:23:29 -08002446 if (recordThread != 0) {
2447 closeInputFinish(recordThread);
2448 } else if (mmapThread != 0) {
2449 mmapThread->exit();
2450 AudioStreamIn *in = mmapThread->clearInput();
2451 ALOG_ASSERT(in != NULL, "in shouldn't be NULL");
2452 // from now on thread->mInput is NULL
2453 delete in;
2454 }
Eric Laurent83b88082014-06-20 18:31:16 -07002455 return NO_ERROR;
2456}
Mathias Agopian65ab4712010-07-14 17:59:35 -07002457
Chih-Hung Hsieh36d0ca12016-08-09 14:31:32 -07002458void AudioFlinger::closeInputFinish(const sp<RecordThread>& thread)
Eric Laurent83b88082014-06-20 18:31:16 -07002459{
2460 thread->exit();
Eric Laurentb8ba0a92011-08-07 16:32:26 -07002461 AudioStreamIn *in = thread->clearInput();
Glenn Kasten5798d4e2012-03-08 12:18:35 -08002462 ALOG_ASSERT(in != NULL, "in shouldn't be NULL");
Eric Laurentb8ba0a92011-08-07 16:32:26 -07002463 // from now on thread->mInput is NULL
Dima Zavin799a70e2011-04-18 16:57:27 -07002464 delete in;
Eric Laurent83b88082014-06-20 18:31:16 -07002465}
Mathias Agopian65ab4712010-07-14 17:59:35 -07002466
Chih-Hung Hsieh36d0ca12016-08-09 14:31:32 -07002467void AudioFlinger::closeInputInternal_l(const sp<RecordThread>& thread)
Eric Laurent83b88082014-06-20 18:31:16 -07002468{
2469 mRecordThreads.removeItem(thread->mId);
2470 closeInputFinish(thread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002471}
2472
Glenn Kastend2304db2014-02-03 07:40:31 -08002473status_t AudioFlinger::invalidateStream(audio_stream_type_t stream)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002474{
2475 Mutex::Autolock _l(mLock);
Glenn Kastend2304db2014-02-03 07:40:31 -08002476 ALOGV("invalidateStream() stream %d", stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002477
2478 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
2479 PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
Eric Laurent22167852012-06-20 12:26:32 -07002480 thread->invalidateTracks(stream);
Eric Laurentde070132010-07-13 04:45:46 -07002481 }
Eric Laurent6acd1d42017-01-04 14:23:29 -08002482 for (size_t i = 0; i < mMmapThreads.size(); i++) {
2483 mMmapThreads[i]->invalidateTracks(stream);
2484 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002485 return NO_ERROR;
2486}
2487
2488
Glenn Kasteneeecb982016-02-26 10:44:04 -08002489audio_unique_id_t AudioFlinger::newAudioUniqueId(audio_unique_id_use_t use)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002490{
Glenn Kasten9d003132016-04-06 14:38:09 -07002491 // This is a binder API, so a malicious client could pass in a bad parameter.
2492 // Check for that before calling the internal API nextUniqueId().
2493 if ((unsigned) use >= (unsigned) AUDIO_UNIQUE_ID_USE_MAX) {
2494 ALOGE("newAudioUniqueId invalid use %d", use);
2495 return AUDIO_UNIQUE_ID_ALLOCATE;
2496 }
Glenn Kasteneeecb982016-02-26 10:44:04 -08002497 return nextUniqueId(use);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002498}
2499
Glenn Kastend848eb42016-03-08 13:42:11 -08002500void AudioFlinger::acquireAudioSessionId(audio_session_t audioSession, pid_t pid)
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002501{
2502 Mutex::Autolock _l(mLock);
Glenn Kastenbb001922012-02-03 11:10:26 -08002503 pid_t caller = IPCThreadState::self()->getCallingPid();
Marco Nelissend457c972014-02-11 08:47:07 -08002504 ALOGV("acquiring %d from %d, for %d", audioSession, caller, pid);
2505 if (pid != -1 && (caller == getpid_cached)) {
2506 caller = pid;
2507 }
Eric Laurentd1b28d42013-09-18 18:47:13 -07002508
Eric Laurent021cf962014-05-13 10:18:14 -07002509 {
2510 Mutex::Autolock _cl(mClientLock);
2511 // Ignore requests received from processes not known as notification client. The request
2512 // is likely proxied by mediaserver (e.g CameraService) and releaseAudioSessionId() can be
2513 // called from a different pid leaving a stale session reference. Also we don't know how
2514 // to clear this reference if the client process dies.
2515 if (mNotificationClients.indexOfKey(caller) < 0) {
2516 ALOGW("acquireAudioSessionId() unknown client %d for session %d", caller, audioSession);
2517 return;
2518 }
Eric Laurentd1b28d42013-09-18 18:47:13 -07002519 }
2520
Glenn Kasten8d6a2442012-02-08 14:04:28 -08002521 size_t num = mAudioSessionRefs.size();
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08002522 for (size_t i = 0; i < num; i++) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002523 AudioSessionRef *ref = mAudioSessionRefs.editItemAt(i);
Glenn Kasten012ca6b2012-03-06 11:22:01 -08002524 if (ref->mSessionid == audioSession && ref->mPid == caller) {
2525 ref->mCnt++;
2526 ALOGV(" incremented refcount to %d", ref->mCnt);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002527 return;
2528 }
2529 }
Glenn Kasten84afa3b2012-01-25 15:28:08 -08002530 mAudioSessionRefs.push(new AudioSessionRef(audioSession, caller));
2531 ALOGV(" added new entry for %d", audioSession);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002532}
2533
Glenn Kastend848eb42016-03-08 13:42:11 -08002534void AudioFlinger::releaseAudioSessionId(audio_session_t audioSession, pid_t pid)
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002535{
2536 Mutex::Autolock _l(mLock);
Glenn Kastenbb001922012-02-03 11:10:26 -08002537 pid_t caller = IPCThreadState::self()->getCallingPid();
Marco Nelissend457c972014-02-11 08:47:07 -08002538 ALOGV("releasing %d from %d for %d", audioSession, caller, pid);
2539 if (pid != -1 && (caller == getpid_cached)) {
2540 caller = pid;
2541 }
Glenn Kasten8d6a2442012-02-08 14:04:28 -08002542 size_t num = mAudioSessionRefs.size();
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08002543 for (size_t i = 0; i < num; i++) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002544 AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
Glenn Kasten012ca6b2012-03-06 11:22:01 -08002545 if (ref->mSessionid == audioSession && ref->mPid == caller) {
2546 ref->mCnt--;
2547 ALOGV(" decremented refcount to %d", ref->mCnt);
2548 if (ref->mCnt == 0) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002549 mAudioSessionRefs.removeAt(i);
2550 delete ref;
2551 purgeStaleEffects_l();
2552 }
2553 return;
2554 }
2555 }
Eric Laurentd1b28d42013-09-18 18:47:13 -07002556 // If the caller is mediaserver it is likely that the session being released was acquired
2557 // on behalf of a process not in notification clients and we ignore the warning.
2558 ALOGW_IF(caller != getpid_cached, "session id %d not found for pid %d", audioSession, caller);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002559}
2560
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08002561bool AudioFlinger::isSessionAcquired_l(audio_session_t audioSession)
2562{
2563 size_t num = mAudioSessionRefs.size();
2564 for (size_t i = 0; i < num; i++) {
2565 AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
2566 if (ref->mSessionid == audioSession) {
2567 return true;
2568 }
2569 }
2570 return false;
2571}
2572
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002573void AudioFlinger::purgeStaleEffects_l() {
2574
Steve Block3856b092011-10-20 11:56:00 +01002575 ALOGV("purging stale effects");
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002576
2577 Vector< sp<EffectChain> > chains;
2578
2579 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
2580 sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
2581 for (size_t j = 0; j < t->mEffectChains.size(); j++) {
2582 sp<EffectChain> ec = t->mEffectChains[j];
Marco Nelissen0270b182011-08-12 14:14:39 -07002583 if (ec->sessionId() > AUDIO_SESSION_OUTPUT_MIX) {
2584 chains.push(ec);
2585 }
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002586 }
2587 }
2588 for (size_t i = 0; i < mRecordThreads.size(); i++) {
2589 sp<RecordThread> t = mRecordThreads.valueAt(i);
2590 for (size_t j = 0; j < t->mEffectChains.size(); j++) {
2591 sp<EffectChain> ec = t->mEffectChains[j];
2592 chains.push(ec);
2593 }
2594 }
2595
2596 for (size_t i = 0; i < chains.size(); i++) {
2597 sp<EffectChain> ec = chains[i];
2598 int sessionid = ec->sessionId();
2599 sp<ThreadBase> t = ec->mThread.promote();
2600 if (t == 0) {
2601 continue;
2602 }
2603 size_t numsessionrefs = mAudioSessionRefs.size();
2604 bool found = false;
2605 for (size_t k = 0; k < numsessionrefs; k++) {
2606 AudioSessionRef *ref = mAudioSessionRefs.itemAt(k);
Glenn Kasten012ca6b2012-03-06 11:22:01 -08002607 if (ref->mSessionid == sessionid) {
Steve Block3856b092011-10-20 11:56:00 +01002608 ALOGV(" session %d still exists for %d with %d refs",
Glenn Kastene53b9ea2012-03-12 16:29:55 -07002609 sessionid, ref->mPid, ref->mCnt);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002610 found = true;
2611 break;
2612 }
2613 }
2614 if (!found) {
Glenn Kastene198c362013-08-13 09:13:36 -07002615 Mutex::Autolock _l(t->mLock);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002616 // remove all effects from the chain
2617 while (ec->mEffects.size()) {
2618 sp<EffectModule> effect = ec->mEffects[0];
2619 effect->unPin();
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002620 t->removeEffect_l(effect);
Eric Laurenta5f44eb2012-06-25 11:38:29 -07002621 if (effect->purgeHandles()) {
2622 t->checkSuspendOnEffectEnabled_l(effect, false, effect->sessionId());
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002623 }
2624 AudioSystem::unregisterEffect(effect->id());
2625 }
2626 }
2627 }
2628 return;
2629}
2630
Glenn Kasteneeecb982016-02-26 10:44:04 -08002631// checkThread_l() must be called with AudioFlinger::mLock held
2632AudioFlinger::ThreadBase *AudioFlinger::checkThread_l(audio_io_handle_t ioHandle) const
2633{
Eric Laurent6acd1d42017-01-04 14:23:29 -08002634 ThreadBase *thread = checkMmapThread_l(ioHandle);
2635 if (thread == 0) {
2636 switch (audio_unique_id_get_use(ioHandle)) {
2637 case AUDIO_UNIQUE_ID_USE_OUTPUT:
2638 thread = checkPlaybackThread_l(ioHandle);
2639 break;
2640 case AUDIO_UNIQUE_ID_USE_INPUT:
2641 thread = checkRecordThread_l(ioHandle);
2642 break;
2643 default:
2644 break;
2645 }
Glenn Kasteneeecb982016-02-26 10:44:04 -08002646 }
2647 return thread;
2648}
2649
Mathias Agopian65ab4712010-07-14 17:59:35 -07002650// checkPlaybackThread_l() must be called with AudioFlinger::mLock held
Glenn Kasten72ef00d2012-01-17 11:09:42 -08002651AudioFlinger::PlaybackThread *AudioFlinger::checkPlaybackThread_l(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07002652{
Glenn Kastena1117922012-01-26 10:53:32 -08002653 return mPlaybackThreads.valueFor(output).get();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002654}
2655
2656// checkMixerThread_l() must be called with AudioFlinger::mLock held
Glenn Kasten72ef00d2012-01-17 11:09:42 -08002657AudioFlinger::MixerThread *AudioFlinger::checkMixerThread_l(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07002658{
2659 PlaybackThread *thread = checkPlaybackThread_l(output);
Glenn Kastena1117922012-01-26 10:53:32 -08002660 return thread != NULL && thread->type() != ThreadBase::DIRECT ? (MixerThread *) thread : NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002661}
2662
2663// checkRecordThread_l() must be called with AudioFlinger::mLock held
Glenn Kasten72ef00d2012-01-17 11:09:42 -08002664AudioFlinger::RecordThread *AudioFlinger::checkRecordThread_l(audio_io_handle_t input) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07002665{
Glenn Kastena1117922012-01-26 10:53:32 -08002666 return mRecordThreads.valueFor(input).get();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002667}
2668
Eric Laurent6acd1d42017-01-04 14:23:29 -08002669// checkMmapThread_l() must be called with AudioFlinger::mLock held
2670AudioFlinger::MmapThread *AudioFlinger::checkMmapThread_l(audio_io_handle_t io) const
2671{
2672 return mMmapThreads.valueFor(io).get();
2673}
2674
2675
2676// checkPlaybackThread_l() must be called with AudioFlinger::mLock held
2677AudioFlinger::VolumeInterface *AudioFlinger::getVolumeInterface_l(audio_io_handle_t output) const
2678{
2679 VolumeInterface *volumeInterface = (VolumeInterface *)mPlaybackThreads.valueFor(output).get();
2680 if (volumeInterface == nullptr) {
2681 MmapThread *mmapThread = mMmapThreads.valueFor(output).get();
2682 if (mmapThread != nullptr) {
2683 if (mmapThread->isOutput()) {
2684 volumeInterface = (VolumeInterface *)mmapThread;
2685 }
2686 }
2687 }
2688 return volumeInterface;
2689}
2690
2691Vector <AudioFlinger::VolumeInterface *> AudioFlinger::getAllVolumeInterfaces_l() const
2692{
2693 Vector <VolumeInterface *> volumeInterfaces;
2694 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
2695 volumeInterfaces.add((VolumeInterface *)mPlaybackThreads.valueAt(i).get());
2696 }
2697 for (size_t i = 0; i < mMmapThreads.size(); i++) {
2698 if (mMmapThreads.valueAt(i)->isOutput()) {
2699 volumeInterfaces.add((VolumeInterface *)mMmapThreads.valueAt(i).get());
2700 }
2701 }
2702 return volumeInterfaces;
2703}
2704
Glenn Kasteneeecb982016-02-26 10:44:04 -08002705audio_unique_id_t AudioFlinger::nextUniqueId(audio_unique_id_use_t use)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002706{
Glenn Kasten9d003132016-04-06 14:38:09 -07002707 // This is the internal API, so it is OK to assert on bad parameter.
Glenn Kasteneeecb982016-02-26 10:44:04 -08002708 LOG_ALWAYS_FATAL_IF((unsigned) use >= (unsigned) AUDIO_UNIQUE_ID_USE_MAX);
Glenn Kastend2e67e12016-04-11 08:26:37 -07002709 const int maxRetries = use == AUDIO_UNIQUE_ID_USE_SESSION ? 3 : 1;
2710 for (int retry = 0; retry < maxRetries; retry++) {
2711 // The cast allows wraparound from max positive to min negative instead of abort
2712 uint32_t base = (uint32_t) atomic_fetch_add_explicit(&mNextUniqueIds[use],
2713 (uint_fast32_t) AUDIO_UNIQUE_ID_USE_MAX, memory_order_acq_rel);
2714 ALOG_ASSERT(audio_unique_id_get_use(base) == AUDIO_UNIQUE_ID_USE_UNSPECIFIED);
2715 // allow wrap by skipping 0 and -1 for session ids
2716 if (!(base == 0 || base == (~0u & ~AUDIO_UNIQUE_ID_USE_MASK))) {
2717 ALOGW_IF(retry != 0, "unique ID overflow for use %d", use);
2718 return (audio_unique_id_t) (base | use);
2719 }
2720 }
2721 // We have no way of recovering from wraparound
2722 LOG_ALWAYS_FATAL("unique ID overflow for use %d", use);
2723 // TODO Use a floor after wraparound. This may need a mutex.
Mathias Agopian65ab4712010-07-14 17:59:35 -07002724}
2725
Glenn Kasten02fe1bf2012-02-24 15:42:17 -08002726AudioFlinger::PlaybackThread *AudioFlinger::primaryPlaybackThread_l() const
Eric Laurent7c7f10b2011-06-17 21:29:58 -07002727{
2728 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
2729 PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
Eric Laurentf6870ae2015-05-08 10:50:03 -07002730 if(thread->isDuplicating()) {
2731 continue;
2732 }
Eric Laurentb8ba0a92011-08-07 16:32:26 -07002733 AudioStreamOut *output = thread->getOutput();
John Grossmanee578c02012-07-23 17:05:46 -07002734 if (output != NULL && output->audioHwDev == mPrimaryHardwareDev) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07002735 return thread;
2736 }
2737 }
2738 return NULL;
2739}
2740
Glenn Kastenbb4350d2012-07-03 15:56:38 -07002741audio_devices_t AudioFlinger::primaryOutputDevice_l() const
Eric Laurent7c7f10b2011-06-17 21:29:58 -07002742{
2743 PlaybackThread *thread = primaryPlaybackThread_l();
2744
2745 if (thread == NULL) {
2746 return 0;
2747 }
2748
Eric Laurentf1c04f92012-08-28 14:26:53 -07002749 return thread->outDevice();
Eric Laurent7c7f10b2011-06-17 21:29:58 -07002750}
2751
Glenn Kastena7335632016-06-09 17:09:53 -07002752AudioFlinger::PlaybackThread *AudioFlinger::fastPlaybackThread_l() const
2753{
2754 size_t minFrameCount = 0;
2755 PlaybackThread *minThread = NULL;
2756 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
2757 PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
2758 if (!thread->isDuplicating()) {
2759 size_t frameCount = thread->frameCountHAL();
2760 if (frameCount != 0 && (minFrameCount == 0 || frameCount < minFrameCount ||
2761 (frameCount == minFrameCount && thread->hasFastMixer() &&
2762 /*minThread != NULL &&*/ !minThread->hasFastMixer()))) {
2763 minFrameCount = frameCount;
2764 minThread = thread;
2765 }
2766 }
2767 }
2768 return minThread;
2769}
2770
Eric Laurenta011e352012-03-29 15:51:43 -07002771sp<AudioFlinger::SyncEvent> AudioFlinger::createSyncEvent(AudioSystem::sync_event_t type,
Glenn Kastend848eb42016-03-08 13:42:11 -08002772 audio_session_t triggerSession,
2773 audio_session_t listenerSession,
Eric Laurenta011e352012-03-29 15:51:43 -07002774 sync_event_callback_t callBack,
Chih-Hung Hsieh36d0ca12016-08-09 14:31:32 -07002775 const wp<RefBase>& cookie)
Eric Laurenta011e352012-03-29 15:51:43 -07002776{
2777 Mutex::Autolock _l(mLock);
2778
2779 sp<SyncEvent> event = new SyncEvent(type, triggerSession, listenerSession, callBack, cookie);
2780 status_t playStatus = NAME_NOT_FOUND;
2781 status_t recStatus = NAME_NOT_FOUND;
2782 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
2783 playStatus = mPlaybackThreads.valueAt(i)->setSyncEvent(event);
2784 if (playStatus == NO_ERROR) {
2785 return event;
2786 }
2787 }
2788 for (size_t i = 0; i < mRecordThreads.size(); i++) {
2789 recStatus = mRecordThreads.valueAt(i)->setSyncEvent(event);
2790 if (recStatus == NO_ERROR) {
2791 return event;
2792 }
2793 }
2794 if (playStatus == NAME_NOT_FOUND || recStatus == NAME_NOT_FOUND) {
2795 mPendingSyncEvents.add(event);
2796 } else {
2797 ALOGV("createSyncEvent() invalid event %d", event->type());
2798 event.clear();
2799 }
2800 return event;
2801}
Eric Laurent7c7f10b2011-06-17 21:29:58 -07002802
Mathias Agopian65ab4712010-07-14 17:59:35 -07002803// ----------------------------------------------------------------------------
2804// Effect management
2805// ----------------------------------------------------------------------------
2806
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -07002807sp<EffectsFactoryHalInterface> AudioFlinger::getEffectsFactory() {
2808 return mEffectsFactoryHal;
2809}
Mathias Agopian65ab4712010-07-14 17:59:35 -07002810
Glenn Kastenf587ba52012-01-26 16:25:10 -08002811status_t AudioFlinger::queryNumberEffects(uint32_t *numEffects) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07002812{
2813 Mutex::Autolock _l(mLock);
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -07002814 if (mEffectsFactoryHal.get()) {
2815 return mEffectsFactoryHal->queryNumberEffects(numEffects);
2816 } else {
2817 return -ENODEV;
2818 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002819}
2820
Glenn Kastenf587ba52012-01-26 16:25:10 -08002821status_t AudioFlinger::queryEffect(uint32_t index, effect_descriptor_t *descriptor) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07002822{
2823 Mutex::Autolock _l(mLock);
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -07002824 if (mEffectsFactoryHal.get()) {
2825 return mEffectsFactoryHal->getDescriptor(index, descriptor);
2826 } else {
2827 return -ENODEV;
2828 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002829}
2830
Glenn Kasten5e92a782012-01-30 07:40:52 -08002831status_t AudioFlinger::getEffectDescriptor(const effect_uuid_t *pUuid,
Glenn Kastenf587ba52012-01-26 16:25:10 -08002832 effect_descriptor_t *descriptor) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07002833{
2834 Mutex::Autolock _l(mLock);
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -07002835 if (mEffectsFactoryHal.get()) {
2836 return mEffectsFactoryHal->getDescriptor(pUuid, descriptor);
2837 } else {
2838 return -ENODEV;
2839 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002840}
2841
2842
Glenn Kasten8d6cc842012-02-03 11:06:53 -08002843sp<IEffect> AudioFlinger::createEffect(
Mathias Agopian65ab4712010-07-14 17:59:35 -07002844 effect_descriptor_t *pDesc,
2845 const sp<IEffectClient>& effectClient,
2846 int32_t priority,
Glenn Kasten72ef00d2012-01-17 11:09:42 -08002847 audio_io_handle_t io,
Glenn Kastend848eb42016-03-08 13:42:11 -08002848 audio_session_t sessionId,
Svet Ganovbe71aa22015-04-28 12:06:02 -07002849 const String16& opPackageName,
Eric Laurentb6436272016-12-07 19:24:50 -08002850 pid_t pid,
Mathias Agopian65ab4712010-07-14 17:59:35 -07002851 status_t *status,
2852 int *id,
2853 int *enabled)
2854{
2855 status_t lStatus = NO_ERROR;
2856 sp<EffectHandle> handle;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002857 effect_descriptor_t desc;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002858
Eric Laurentb6436272016-12-07 19:24:50 -08002859 const uid_t callingUid = IPCThreadState::self()->getCallingUid();
2860 if (pid == -1 || !isTrustedCallingUid(callingUid)) {
2861 const pid_t callingPid = IPCThreadState::self()->getCallingPid();
2862 ALOGW_IF(pid != -1 && pid != callingPid,
2863 "%s uid %d pid %d tried to pass itself off as pid %d",
2864 __func__, callingUid, callingPid, pid);
2865 pid = callingPid;
2866 }
2867
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -07002868 ALOGV("createEffect pid %d, effectClient %p, priority %d, sessionId %d, io %d, factory %p",
2869 pid, effectClient.get(), priority, sessionId, io, mEffectsFactoryHal.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002870
2871 if (pDesc == NULL) {
2872 lStatus = BAD_VALUE;
2873 goto Exit;
2874 }
2875
Eric Laurent84e9a102010-09-23 16:10:16 -07002876 // check audio settings permission for global effects
Dima Zavinfce7a472011-04-19 22:30:36 -07002877 if (sessionId == AUDIO_SESSION_OUTPUT_MIX && !settingsAllowed()) {
Eric Laurent84e9a102010-09-23 16:10:16 -07002878 lStatus = PERMISSION_DENIED;
2879 goto Exit;
2880 }
2881
Dima Zavinfce7a472011-04-19 22:30:36 -07002882 // Session AUDIO_SESSION_OUTPUT_STAGE is reserved for output stage effects
Eric Laurent84e9a102010-09-23 16:10:16 -07002883 // that can only be created by audio policy manager (running in same process)
Glenn Kasten44deb052012-02-05 18:09:08 -08002884 if (sessionId == AUDIO_SESSION_OUTPUT_STAGE && getpid_cached != pid) {
Eric Laurent84e9a102010-09-23 16:10:16 -07002885 lStatus = PERMISSION_DENIED;
2886 goto Exit;
2887 }
2888
Mikhail Naganov1dc98672016-08-18 17:50:29 -07002889 if (mEffectsFactoryHal == 0) {
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -07002890 lStatus = NO_INIT;
2891 goto Exit;
2892 }
2893
Mathias Agopian65ab4712010-07-14 17:59:35 -07002894 {
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -07002895 if (!EffectsFactoryHalInterface::isNullUuid(&pDesc->uuid)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002896 // if uuid is specified, request effect descriptor
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -07002897 lStatus = mEffectsFactoryHal->getDescriptor(&pDesc->uuid, &desc);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002898 if (lStatus < 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00002899 ALOGW("createEffect() error %d from EffectGetDescriptor", lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002900 goto Exit;
2901 }
2902 } else {
2903 // if uuid is not specified, look for an available implementation
2904 // of the required type in effect factory
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -07002905 if (EffectsFactoryHalInterface::isNullUuid(&pDesc->type)) {
Steve Block5ff1dd52012-01-05 23:22:43 +00002906 ALOGW("createEffect() no effect type");
Mathias Agopian65ab4712010-07-14 17:59:35 -07002907 lStatus = BAD_VALUE;
2908 goto Exit;
2909 }
2910 uint32_t numEffects = 0;
2911 effect_descriptor_t d;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002912 d.flags = 0; // prevent compiler warning
Mathias Agopian65ab4712010-07-14 17:59:35 -07002913 bool found = false;
2914
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -07002915 lStatus = mEffectsFactoryHal->queryNumberEffects(&numEffects);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002916 if (lStatus < 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00002917 ALOGW("createEffect() error %d from EffectQueryNumberEffects", lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002918 goto Exit;
2919 }
2920 for (uint32_t i = 0; i < numEffects; i++) {
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -07002921 lStatus = mEffectsFactoryHal->getDescriptor(i, &desc);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002922 if (lStatus < 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00002923 ALOGW("createEffect() error %d from EffectQueryEffect", lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002924 continue;
2925 }
2926 if (memcmp(&desc.type, &pDesc->type, sizeof(effect_uuid_t)) == 0) {
2927 // If matching type found save effect descriptor. If the session is
2928 // 0 and the effect is not auxiliary, continue enumeration in case
2929 // an auxiliary version of this effect type is available
2930 found = true;
Glenn Kastena189a682012-02-20 12:16:30 -08002931 d = desc;
Dima Zavinfce7a472011-04-19 22:30:36 -07002932 if (sessionId != AUDIO_SESSION_OUTPUT_MIX ||
Mathias Agopian65ab4712010-07-14 17:59:35 -07002933 (desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
2934 break;
2935 }
2936 }
2937 }
2938 if (!found) {
2939 lStatus = BAD_VALUE;
Steve Block5ff1dd52012-01-05 23:22:43 +00002940 ALOGW("createEffect() effect not found");
Mathias Agopian65ab4712010-07-14 17:59:35 -07002941 goto Exit;
2942 }
2943 // For same effect type, chose auxiliary version over insert version if
2944 // connect to output mix (Compliance to OpenSL ES)
Dima Zavinfce7a472011-04-19 22:30:36 -07002945 if (sessionId == AUDIO_SESSION_OUTPUT_MIX &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07002946 (d.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_AUXILIARY) {
Glenn Kastena189a682012-02-20 12:16:30 -08002947 desc = d;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002948 }
2949 }
2950
2951 // Do not allow auxiliary effects on a session different from 0 (output mix)
Dima Zavinfce7a472011-04-19 22:30:36 -07002952 if (sessionId != AUDIO_SESSION_OUTPUT_MIX &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07002953 (desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
2954 lStatus = INVALID_OPERATION;
2955 goto Exit;
2956 }
2957
Eric Laurent59255e42011-07-27 19:49:51 -07002958 // check recording permission for visualizer
2959 if ((memcmp(&desc.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) &&
Marco Nelissendcb346b2015-09-09 10:47:29 -07002960 !recordingAllowed(opPackageName, pid, IPCThreadState::self()->getCallingUid())) {
Eric Laurent59255e42011-07-27 19:49:51 -07002961 lStatus = PERMISSION_DENIED;
2962 goto Exit;
2963 }
2964
Mathias Agopian65ab4712010-07-14 17:59:35 -07002965 // return effect descriptor
Glenn Kastena189a682012-02-20 12:16:30 -08002966 *pDesc = desc;
Glenn Kasten142f5192014-03-25 17:44:59 -07002967 if (io == AUDIO_IO_HANDLE_NONE && sessionId == AUDIO_SESSION_OUTPUT_MIX) {
Eric Laurenteb3c3372013-09-25 12:25:29 -07002968 // if the output returned by getOutputForEffect() is removed before we lock the
2969 // mutex below, the call to checkPlaybackThread_l(io) below will detect it
2970 // and we will exit safely
2971 io = AudioSystem::getOutputForEffect(&desc);
2972 ALOGV("createEffect got output %d", io);
2973 }
2974
2975 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002976
2977 // If output is not specified try to find a matching audio session ID in one of the
2978 // output threads.
Eric Laurent84e9a102010-09-23 16:10:16 -07002979 // If output is 0 here, sessionId is neither SESSION_OUTPUT_STAGE nor SESSION_OUTPUT_MIX
2980 // because of code checking output when entering the function.
Eric Laurent7c7f10b2011-06-17 21:29:58 -07002981 // Note: io is never 0 when creating an effect on an input
Glenn Kasten142f5192014-03-25 17:44:59 -07002982 if (io == AUDIO_IO_HANDLE_NONE) {
Eric Laurent5baf2af2013-09-12 17:37:00 -07002983 if (sessionId == AUDIO_SESSION_OUTPUT_STAGE) {
2984 // output must be specified by AudioPolicyManager when using session
2985 // AUDIO_SESSION_OUTPUT_STAGE
2986 lStatus = BAD_VALUE;
2987 goto Exit;
2988 }
Eric Laurenteb3c3372013-09-25 12:25:29 -07002989 // look for the thread where the specified audio session is present
2990 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
2991 if (mPlaybackThreads.valueAt(i)->hasAudioSession(sessionId) != 0) {
2992 io = mPlaybackThreads.keyAt(i);
2993 break;
2994 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002995 }
Eric Laurent6acd1d42017-01-04 14:23:29 -08002996 if (io == AUDIO_IO_HANDLE_NONE) {
Eric Laurenteb3c3372013-09-25 12:25:29 -07002997 for (size_t i = 0; i < mRecordThreads.size(); i++) {
2998 if (mRecordThreads.valueAt(i)->hasAudioSession(sessionId) != 0) {
2999 io = mRecordThreads.keyAt(i);
Glenn Kastene53b9ea2012-03-12 16:29:55 -07003000 break;
3001 }
3002 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07003003 }
Eric Laurent6acd1d42017-01-04 14:23:29 -08003004 if (io == AUDIO_IO_HANDLE_NONE) {
3005 for (size_t i = 0; i < mMmapThreads.size(); i++) {
3006 if (mMmapThreads.valueAt(i)->hasAudioSession(sessionId) != 0) {
3007 io = mMmapThreads.keyAt(i);
3008 break;
3009 }
3010 }
3011 }
Eric Laurent84e9a102010-09-23 16:10:16 -07003012 // If no output thread contains the requested session ID, default to
3013 // first output. The effect chain will be moved to the correct output
3014 // thread when a track with the same session ID is created
Glenn Kasten142f5192014-03-25 17:44:59 -07003015 if (io == AUDIO_IO_HANDLE_NONE && mPlaybackThreads.size() > 0) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07003016 io = mPlaybackThreads.keyAt(0);
3017 }
Steve Block3856b092011-10-20 11:56:00 +01003018 ALOGV("createEffect() got io %d for effect %s", io, desc.name);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07003019 }
3020 ThreadBase *thread = checkRecordThread_l(io);
3021 if (thread == NULL) {
3022 thread = checkPlaybackThread_l(io);
3023 if (thread == NULL) {
Eric Laurent6acd1d42017-01-04 14:23:29 -08003024 thread = checkMmapThread_l(io);
3025 if (thread == NULL) {
3026 ALOGE("createEffect() unknown output thread");
3027 lStatus = BAD_VALUE;
3028 goto Exit;
3029 }
Eric Laurent84e9a102010-09-23 16:10:16 -07003030 }
Eric Laurentaaa44472014-09-12 17:41:50 -07003031 } else {
3032 // Check if one effect chain was awaiting for an effect to be created on this
3033 // session and used it instead of creating a new one.
Glenn Kastend848eb42016-03-08 13:42:11 -08003034 sp<EffectChain> chain = getOrphanEffectChain_l(sessionId);
Eric Laurentaaa44472014-09-12 17:41:50 -07003035 if (chain != 0) {
Eric Laurent1b928682014-10-02 19:41:47 -07003036 Mutex::Autolock _l(thread->mLock);
Eric Laurentaaa44472014-09-12 17:41:50 -07003037 thread->addEffectChain_l(chain);
3038 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003039 }
Eric Laurent84e9a102010-09-23 16:10:16 -07003040
Eric Laurent021cf962014-05-13 10:18:14 -07003041 sp<Client> client = registerPid(pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003042
Marco Nelissen3a34bef2011-08-02 13:33:41 -07003043 // create effect on selected output thread
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08003044 bool pinned = (sessionId > AUDIO_SESSION_OUTPUT_MIX) && isSessionAcquired_l(sessionId);
Eric Laurentde070132010-07-13 04:45:46 -07003045 handle = thread->createEffect_l(client, effectClient, priority, sessionId,
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08003046 &desc, enabled, &lStatus, pinned);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003047 if (handle != 0 && id != NULL) {
3048 *id = handle->id();
3049 }
Eric Laurentfe1a94e2014-05-26 16:03:08 -07003050 if (handle == 0) {
3051 // remove local strong reference to Client with mClientLock held
3052 Mutex::Autolock _cl(mClientLock);
3053 client.clear();
3054 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003055 }
3056
3057Exit:
Glenn Kasten9156ef32013-08-06 15:39:08 -07003058 *status = lStatus;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003059 return handle;
3060}
3061
Glenn Kastend848eb42016-03-08 13:42:11 -08003062status_t AudioFlinger::moveEffects(audio_session_t sessionId, audio_io_handle_t srcOutput,
Glenn Kasten72ef00d2012-01-17 11:09:42 -08003063 audio_io_handle_t dstOutput)
Eric Laurentde070132010-07-13 04:45:46 -07003064{
Steve Block3856b092011-10-20 11:56:00 +01003065 ALOGV("moveEffects() session %d, srcOutput %d, dstOutput %d",
Eric Laurent59255e42011-07-27 19:49:51 -07003066 sessionId, srcOutput, dstOutput);
Eric Laurentde070132010-07-13 04:45:46 -07003067 Mutex::Autolock _l(mLock);
3068 if (srcOutput == dstOutput) {
Steve Block5ff1dd52012-01-05 23:22:43 +00003069 ALOGW("moveEffects() same dst and src outputs %d", dstOutput);
Eric Laurentde070132010-07-13 04:45:46 -07003070 return NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003071 }
Eric Laurentde070132010-07-13 04:45:46 -07003072 PlaybackThread *srcThread = checkPlaybackThread_l(srcOutput);
3073 if (srcThread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00003074 ALOGW("moveEffects() bad srcOutput %d", srcOutput);
Eric Laurentde070132010-07-13 04:45:46 -07003075 return BAD_VALUE;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003076 }
Eric Laurentde070132010-07-13 04:45:46 -07003077 PlaybackThread *dstThread = checkPlaybackThread_l(dstOutput);
3078 if (dstThread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00003079 ALOGW("moveEffects() bad dstOutput %d", dstOutput);
Eric Laurentde070132010-07-13 04:45:46 -07003080 return BAD_VALUE;
3081 }
3082
3083 Mutex::Autolock _dl(dstThread->mLock);
3084 Mutex::Autolock _sl(srcThread->mLock);
Eric Laurent5baf2af2013-09-12 17:37:00 -07003085 return moveEffectChain_l(sessionId, srcThread, dstThread, false);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003086}
3087
Marco Nelissen3a34bef2011-08-02 13:33:41 -07003088// moveEffectChain_l must be called with both srcThread and dstThread mLocks held
Glenn Kastend848eb42016-03-08 13:42:11 -08003089status_t AudioFlinger::moveEffectChain_l(audio_session_t sessionId,
Eric Laurentde070132010-07-13 04:45:46 -07003090 AudioFlinger::PlaybackThread *srcThread,
Eric Laurent39e94f82010-07-28 01:32:47 -07003091 AudioFlinger::PlaybackThread *dstThread,
3092 bool reRegister)
Eric Laurentde070132010-07-13 04:45:46 -07003093{
Steve Block3856b092011-10-20 11:56:00 +01003094 ALOGV("moveEffectChain_l() session %d from thread %p to thread %p",
Eric Laurent59255e42011-07-27 19:49:51 -07003095 sessionId, srcThread, dstThread);
Eric Laurentde070132010-07-13 04:45:46 -07003096
Eric Laurent59255e42011-07-27 19:49:51 -07003097 sp<EffectChain> chain = srcThread->getEffectChain_l(sessionId);
Eric Laurentde070132010-07-13 04:45:46 -07003098 if (chain == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00003099 ALOGW("moveEffectChain_l() effect chain for session %d not on source thread %p",
Eric Laurent59255e42011-07-27 19:49:51 -07003100 sessionId, srcThread);
Eric Laurentde070132010-07-13 04:45:46 -07003101 return INVALID_OPERATION;
3102 }
3103
Eric Laurent4c415062016-06-17 16:14:16 -07003104 // Check whether the destination thread and all effects in the chain are compatible
3105 if (!chain->isCompatibleWithThread_l(dstThread)) {
Andy Hung9a592762014-07-21 21:56:01 -07003106 ALOGW("moveEffectChain_l() effect chain failed because"
Eric Laurent4c415062016-06-17 16:14:16 -07003107 " destination thread %p is not compatible with effects in the chain",
3108 dstThread);
Andy Hung9a592762014-07-21 21:56:01 -07003109 return INVALID_OPERATION;
3110 }
3111
Eric Laurent39e94f82010-07-28 01:32:47 -07003112 // remove chain first. This is useful only if reconfiguring effect chain on same output thread,
Eric Laurentde070132010-07-13 04:45:46 -07003113 // so that a new chain is created with correct parameters when first effect is added. This is
Eric Laurentec35a142011-10-05 17:42:25 -07003114 // otherwise unnecessary as removeEffect_l() will remove the chain when last effect is
Eric Laurentde070132010-07-13 04:45:46 -07003115 // removed.
3116 srcThread->removeEffectChain_l(chain);
3117
3118 // transfer all effects one by one so that new effect chain is created on new thread with
3119 // correct buffer sizes and audio parameters and effect engines reconfigured accordingly
Eric Laurent39e94f82010-07-28 01:32:47 -07003120 sp<EffectChain> dstChain;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07003121 uint32_t strategy = 0; // prevent compiler warning
Eric Laurentde070132010-07-13 04:45:46 -07003122 sp<EffectModule> effect = chain->getEffectFromId_l(0);
Eric Laurent5baf2af2013-09-12 17:37:00 -07003123 Vector< sp<EffectModule> > removed;
3124 status_t status = NO_ERROR;
Eric Laurentde070132010-07-13 04:45:46 -07003125 while (effect != 0) {
3126 srcThread->removeEffect_l(effect);
Eric Laurent5baf2af2013-09-12 17:37:00 -07003127 removed.add(effect);
3128 status = dstThread->addEffect_l(effect);
3129 if (status != NO_ERROR) {
3130 break;
3131 }
Eric Laurentec35a142011-10-05 17:42:25 -07003132 // removeEffect_l() has stopped the effect if it was active so it must be restarted
3133 if (effect->state() == EffectModule::ACTIVE ||
3134 effect->state() == EffectModule::STOPPING) {
3135 effect->start();
3136 }
Eric Laurent39e94f82010-07-28 01:32:47 -07003137 // if the move request is not received from audio policy manager, the effect must be
3138 // re-registered with the new strategy and output
3139 if (dstChain == 0) {
3140 dstChain = effect->chain().promote();
3141 if (dstChain == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00003142 ALOGW("moveEffectChain_l() cannot get chain from effect %p", effect.get());
Eric Laurent5baf2af2013-09-12 17:37:00 -07003143 status = NO_INIT;
3144 break;
Eric Laurent39e94f82010-07-28 01:32:47 -07003145 }
3146 strategy = dstChain->strategy();
3147 }
3148 if (reRegister) {
3149 AudioSystem::unregisterEffect(effect->id());
3150 AudioSystem::registerEffect(&effect->desc(),
Eric Laurent5baf2af2013-09-12 17:37:00 -07003151 dstThread->id(),
Eric Laurent39e94f82010-07-28 01:32:47 -07003152 strategy,
Eric Laurent59255e42011-07-27 19:49:51 -07003153 sessionId,
Eric Laurent39e94f82010-07-28 01:32:47 -07003154 effect->id());
Eric Laurentd72b7c02013-10-12 16:17:46 -07003155 AudioSystem::setEffectEnabled(effect->id(), effect->isEnabled());
Eric Laurent39e94f82010-07-28 01:32:47 -07003156 }
Eric Laurentde070132010-07-13 04:45:46 -07003157 effect = chain->getEffectFromId_l(0);
3158 }
3159
Eric Laurent5baf2af2013-09-12 17:37:00 -07003160 if (status != NO_ERROR) {
3161 for (size_t i = 0; i < removed.size(); i++) {
3162 srcThread->addEffect_l(removed[i]);
3163 if (dstChain != 0 && reRegister) {
3164 AudioSystem::unregisterEffect(removed[i]->id());
3165 AudioSystem::registerEffect(&removed[i]->desc(),
3166 srcThread->id(),
3167 strategy,
3168 sessionId,
3169 removed[i]->id());
Eric Laurentd72b7c02013-10-12 16:17:46 -07003170 AudioSystem::setEffectEnabled(effect->id(), effect->isEnabled());
Eric Laurent5baf2af2013-09-12 17:37:00 -07003171 }
3172 }
3173 }
3174
3175 return status;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003176}
3177
Eric Laurent5baf2af2013-09-12 17:37:00 -07003178bool AudioFlinger::isNonOffloadableGlobalEffectEnabled_l()
Eric Laurent813e2a72013-08-31 12:59:48 -07003179{
3180 if (mGlobalEffectEnableTime != 0 &&
3181 ((systemTime() - mGlobalEffectEnableTime) < kMinGlobalEffectEnabletimeNs)) {
3182 return true;
3183 }
3184
3185 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
3186 sp<EffectChain> ec =
3187 mPlaybackThreads.valueAt(i)->getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
Eric Laurent5baf2af2013-09-12 17:37:00 -07003188 if (ec != 0 && ec->isNonOffloadableEnabled()) {
Eric Laurent813e2a72013-08-31 12:59:48 -07003189 return true;
3190 }
3191 }
3192 return false;
3193}
3194
Eric Laurent5baf2af2013-09-12 17:37:00 -07003195void AudioFlinger::onNonOffloadableGlobalEffectEnable()
Eric Laurent813e2a72013-08-31 12:59:48 -07003196{
3197 Mutex::Autolock _l(mLock);
3198
3199 mGlobalEffectEnableTime = systemTime();
3200
3201 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
3202 sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
3203 if (t->mType == ThreadBase::OFFLOAD) {
3204 t->invalidateTracks(AUDIO_STREAM_MUSIC);
3205 }
3206 }
3207
3208}
3209
Eric Laurentaaa44472014-09-12 17:41:50 -07003210status_t AudioFlinger::putOrphanEffectChain_l(const sp<AudioFlinger::EffectChain>& chain)
3211{
Glenn Kastend848eb42016-03-08 13:42:11 -08003212 audio_session_t session = chain->sessionId();
Eric Laurentaaa44472014-09-12 17:41:50 -07003213 ssize_t index = mOrphanEffectChains.indexOfKey(session);
Glenn Kastenc42e9b42016-03-21 11:35:03 -07003214 ALOGV("putOrphanEffectChain_l session %d index %zd", session, index);
Eric Laurentaaa44472014-09-12 17:41:50 -07003215 if (index >= 0) {
3216 ALOGW("putOrphanEffectChain_l chain for session %d already present", session);
3217 return ALREADY_EXISTS;
3218 }
3219 mOrphanEffectChains.add(session, chain);
3220 return NO_ERROR;
3221}
3222
3223sp<AudioFlinger::EffectChain> AudioFlinger::getOrphanEffectChain_l(audio_session_t session)
3224{
3225 sp<EffectChain> chain;
3226 ssize_t index = mOrphanEffectChains.indexOfKey(session);
Glenn Kastenc42e9b42016-03-21 11:35:03 -07003227 ALOGV("getOrphanEffectChain_l session %d index %zd", session, index);
Eric Laurentaaa44472014-09-12 17:41:50 -07003228 if (index >= 0) {
3229 chain = mOrphanEffectChains.valueAt(index);
3230 mOrphanEffectChains.removeItemsAt(index);
3231 }
3232 return chain;
3233}
3234
3235bool AudioFlinger::updateOrphanEffectChains(const sp<AudioFlinger::EffectModule>& effect)
3236{
3237 Mutex::Autolock _l(mLock);
Glenn Kastend848eb42016-03-08 13:42:11 -08003238 audio_session_t session = effect->sessionId();
Eric Laurentaaa44472014-09-12 17:41:50 -07003239 ssize_t index = mOrphanEffectChains.indexOfKey(session);
Glenn Kastenc42e9b42016-03-21 11:35:03 -07003240 ALOGV("updateOrphanEffectChains session %d index %zd", session, index);
Eric Laurentaaa44472014-09-12 17:41:50 -07003241 if (index >= 0) {
3242 sp<EffectChain> chain = mOrphanEffectChains.valueAt(index);
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08003243 if (chain->removeEffect_l(effect, true) == 0) {
Glenn Kastenc42e9b42016-03-21 11:35:03 -07003244 ALOGV("updateOrphanEffectChains removing effect chain at index %zd", index);
Eric Laurentaaa44472014-09-12 17:41:50 -07003245 mOrphanEffectChains.removeItemsAt(index);
3246 }
3247 return true;
3248 }
3249 return false;
3250}
3251
3252
Glenn Kastenda6ef132013-01-10 12:31:01 -08003253struct Entry {
Glenn Kasten2f55e762015-03-05 16:05:08 -08003254#define TEE_MAX_FILENAME 32 // %Y%m%d%H%M%S_%d.wav = 4+2+2+2+2+2+1+1+4+1 = 21
3255 char mFileName[TEE_MAX_FILENAME];
Glenn Kastenda6ef132013-01-10 12:31:01 -08003256};
3257
3258int comparEntry(const void *p1, const void *p2)
3259{
Glenn Kasten2f55e762015-03-05 16:05:08 -08003260 return strcmp(((const Entry *) p1)->mFileName, ((const Entry *) p2)->mFileName);
Glenn Kastenda6ef132013-01-10 12:31:01 -08003261}
3262
Glenn Kasten46909e72013-02-26 09:20:22 -08003263#ifdef TEE_SINK
Eric Laurent81784c32012-11-19 14:55:58 -08003264void AudioFlinger::dumpTee(int fd, const sp<NBAIO_Source>& source, audio_io_handle_t id)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003265{
Eric Laurent81784c32012-11-19 14:55:58 -08003266 NBAIO_Source *teeSource = source.get();
3267 if (teeSource != NULL) {
Glenn Kastenda6ef132013-01-10 12:31:01 -08003268 // .wav rotation
3269 // There is a benign race condition if 2 threads call this simultaneously.
3270 // They would both traverse the directory, but the result would simply be
3271 // failures at unlink() which are ignored. It's also unlikely since
3272 // normally dumpsys is only done by bugreport or from the command line.
3273 char teePath[32+256];
Glenn Kasten9a003992016-02-23 15:24:34 -08003274 strcpy(teePath, "/data/misc/audioserver");
Glenn Kastenda6ef132013-01-10 12:31:01 -08003275 size_t teePathLen = strlen(teePath);
3276 DIR *dir = opendir(teePath);
3277 teePath[teePathLen++] = '/';
3278 if (dir != NULL) {
Glenn Kasten2f55e762015-03-05 16:05:08 -08003279#define TEE_MAX_SORT 20 // number of entries to sort
3280#define TEE_MAX_KEEP 10 // number of entries to keep
3281 struct Entry entries[TEE_MAX_SORT];
Glenn Kastenda6ef132013-01-10 12:31:01 -08003282 size_t entryCount = 0;
Glenn Kasten2f55e762015-03-05 16:05:08 -08003283 while (entryCount < TEE_MAX_SORT) {
Glenn Kastenda6ef132013-01-10 12:31:01 -08003284 struct dirent de;
3285 struct dirent *result = NULL;
3286 int rc = readdir_r(dir, &de, &result);
3287 if (rc != 0) {
3288 ALOGW("readdir_r failed %d", rc);
3289 break;
3290 }
3291 if (result == NULL) {
3292 break;
3293 }
3294 if (result != &de) {
3295 ALOGW("readdir_r returned unexpected result %p != %p", result, &de);
3296 break;
3297 }
3298 // ignore non .wav file entries
3299 size_t nameLen = strlen(de.d_name);
Glenn Kasten2f55e762015-03-05 16:05:08 -08003300 if (nameLen <= 4 || nameLen >= TEE_MAX_FILENAME ||
Glenn Kastenda6ef132013-01-10 12:31:01 -08003301 strcmp(&de.d_name[nameLen - 4], ".wav")) {
3302 continue;
3303 }
Glenn Kasten2f55e762015-03-05 16:05:08 -08003304 strcpy(entries[entryCount++].mFileName, de.d_name);
Glenn Kastenda6ef132013-01-10 12:31:01 -08003305 }
3306 (void) closedir(dir);
Glenn Kasten2f55e762015-03-05 16:05:08 -08003307 if (entryCount > TEE_MAX_KEEP) {
Glenn Kastenda6ef132013-01-10 12:31:01 -08003308 qsort(entries, entryCount, sizeof(Entry), comparEntry);
Glenn Kasten2f55e762015-03-05 16:05:08 -08003309 for (size_t i = 0; i < entryCount - TEE_MAX_KEEP; ++i) {
3310 strcpy(&teePath[teePathLen], entries[i].mFileName);
Glenn Kastenda6ef132013-01-10 12:31:01 -08003311 (void) unlink(teePath);
3312 }
3313 }
3314 } else {
3315 if (fd >= 0) {
Glenn Kastenfbd87e82016-07-18 15:45:56 -07003316 dprintf(fd, "unable to rotate tees in %.*s: %s\n", (int) teePathLen, teePath,
Glenn Kasten9a003992016-02-23 15:24:34 -08003317 strerror(errno));
Glenn Kastenda6ef132013-01-10 12:31:01 -08003318 }
3319 }
Eric Laurent81784c32012-11-19 14:55:58 -08003320 char teeTime[16];
3321 struct timeval tv;
3322 gettimeofday(&tv, NULL);
3323 struct tm tm;
3324 localtime_r(&tv.tv_sec, &tm);
Glenn Kastenda6ef132013-01-10 12:31:01 -08003325 strftime(teeTime, sizeof(teeTime), "%Y%m%d%H%M%S", &tm);
3326 snprintf(&teePath[teePathLen], sizeof(teePath) - teePathLen, "%s_%d.wav", teeTime, id);
3327 // if 2 dumpsys are done within 1 second, and rotation didn't work, then discard 2nd
3328 int teeFd = open(teePath, O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW, S_IRUSR | S_IWUSR);
Eric Laurent81784c32012-11-19 14:55:58 -08003329 if (teeFd >= 0) {
Glenn Kasten329f6512014-08-28 16:23:16 -07003330 // FIXME use libsndfile
Eric Laurent81784c32012-11-19 14:55:58 -08003331 char wavHeader[44];
3332 memcpy(wavHeader,
3333 "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",
3334 sizeof(wavHeader));
3335 NBAIO_Format format = teeSource->format();
3336 unsigned channelCount = Format_channelCount(format);
Eric Laurent81784c32012-11-19 14:55:58 -08003337 uint32_t sampleRate = Format_sampleRate(format);
Glenn Kasten329f6512014-08-28 16:23:16 -07003338 size_t frameSize = Format_frameSize(format);
Eric Laurent81784c32012-11-19 14:55:58 -08003339 wavHeader[22] = channelCount; // number of channels
3340 wavHeader[24] = sampleRate; // sample rate
3341 wavHeader[25] = sampleRate >> 8;
Glenn Kasten329f6512014-08-28 16:23:16 -07003342 wavHeader[32] = frameSize; // block alignment
3343 wavHeader[33] = frameSize >> 8;
Eric Laurent81784c32012-11-19 14:55:58 -08003344 write(teeFd, wavHeader, sizeof(wavHeader));
3345 size_t total = 0;
3346 bool firstRead = true;
Glenn Kasten329f6512014-08-28 16:23:16 -07003347#define TEE_SINK_READ 1024 // frames per I/O operation
3348 void *buffer = malloc(TEE_SINK_READ * frameSize);
Eric Laurent81784c32012-11-19 14:55:58 -08003349 for (;;) {
Eric Laurent81784c32012-11-19 14:55:58 -08003350 size_t count = TEE_SINK_READ;
Glenn Kastend79072e2016-01-06 08:41:20 -08003351 ssize_t actual = teeSource->read(buffer, count);
Eric Laurent81784c32012-11-19 14:55:58 -08003352 bool wasFirstRead = firstRead;
3353 firstRead = false;
3354 if (actual <= 0) {
3355 if (actual == (ssize_t) OVERRUN && wasFirstRead) {
3356 continue;
Eric Laurent59255e42011-07-27 19:49:51 -07003357 }
Eric Laurent81784c32012-11-19 14:55:58 -08003358 break;
Eric Laurent59255e42011-07-27 19:49:51 -07003359 }
Eric Laurent81784c32012-11-19 14:55:58 -08003360 ALOG_ASSERT(actual <= (ssize_t)count);
Glenn Kasten329f6512014-08-28 16:23:16 -07003361 write(teeFd, buffer, actual * frameSize);
Eric Laurent81784c32012-11-19 14:55:58 -08003362 total += actual;
Eric Laurent59255e42011-07-27 19:49:51 -07003363 }
Glenn Kasten329f6512014-08-28 16:23:16 -07003364 free(buffer);
Eric Laurent81784c32012-11-19 14:55:58 -08003365 lseek(teeFd, (off_t) 4, SEEK_SET);
Glenn Kasten329f6512014-08-28 16:23:16 -07003366 uint32_t temp = 44 + total * frameSize - 8;
3367 // FIXME not big-endian safe
Eric Laurent81784c32012-11-19 14:55:58 -08003368 write(teeFd, &temp, sizeof(temp));
3369 lseek(teeFd, (off_t) 40, SEEK_SET);
Glenn Kasten329f6512014-08-28 16:23:16 -07003370 temp = total * frameSize;
3371 // FIXME not big-endian safe
Eric Laurent81784c32012-11-19 14:55:58 -08003372 write(teeFd, &temp, sizeof(temp));
3373 close(teeFd);
Glenn Kastenda6ef132013-01-10 12:31:01 -08003374 if (fd >= 0) {
Elliott Hughes8b5f6422014-05-22 01:22:06 -07003375 dprintf(fd, "tee copied to %s\n", teePath);
Glenn Kastenda6ef132013-01-10 12:31:01 -08003376 }
Eric Laurent59255e42011-07-27 19:49:51 -07003377 } else {
Glenn Kastenda6ef132013-01-10 12:31:01 -08003378 if (fd >= 0) {
Elliott Hughes8b5f6422014-05-22 01:22:06 -07003379 dprintf(fd, "unable to create tee %s: %s\n", teePath, strerror(errno));
Glenn Kastenda6ef132013-01-10 12:31:01 -08003380 }
Eric Laurent59255e42011-07-27 19:49:51 -07003381 }
3382 }
3383}
Glenn Kasten46909e72013-02-26 09:20:22 -08003384#endif
Eric Laurent59255e42011-07-27 19:49:51 -07003385
Mathias Agopian65ab4712010-07-14 17:59:35 -07003386// ----------------------------------------------------------------------------
3387
3388status_t AudioFlinger::onTransact(
3389 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
3390{
3391 return BnAudioFlinger::onTransact(code, data, reply, flags);
3392}
3393
Glenn Kasten63238ef2015-03-02 15:50:29 -08003394} // namespace android