blob: e56a0f45736a0e89c05c8952793cbd066980661c [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 Kasten04b96fc2017-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 Kasten04b96fc2017-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 Kasten04b96fc2017-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};
Eric Laurenta4c5a552012-03-29 10:12:40 -0700343
Phil Burk062e67a2015-02-11 13:40:50 -0800344AudioHwDevice* AudioFlinger::findSuitableHwDev_l(
John Grossmanee578c02012-07-23 17:05:46 -0700345 audio_module_handle_t module,
346 audio_devices_t devices)
Dima Zavin799a70e2011-04-18 16:57:27 -0700347{
Eric Laurenta4c5a552012-03-29 10:12:40 -0700348 // if module is 0, the request comes from an old policy manager and we should load
349 // well known modules
350 if (module == 0) {
351 ALOGW("findSuitableHwDev_l() loading well know audio hw modules");
Mikhail Naganovbf493082017-04-17 17:37:12 -0700352 for (size_t i = 0; i < arraysize(audio_interfaces); i++) {
Eric Laurenta4c5a552012-03-29 10:12:40 -0700353 loadHwModule_l(audio_interfaces[i]);
354 }
Eric Laurentf1c04f92012-08-28 14:26:53 -0700355 // then try to find a module supporting the requested device.
356 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
357 AudioHwDevice *audioHwDevice = mAudioHwDevs.valueAt(i);
Mikhail Naganove4f1f632016-08-31 11:35:10 -0700358 sp<DeviceHalInterface> dev = audioHwDevice->hwDevice();
359 uint32_t supportedDevices;
360 if (dev->getSupportedDevices(&supportedDevices) == OK &&
361 (supportedDevices & devices) == devices) {
Eric Laurentf1c04f92012-08-28 14:26:53 -0700362 return audioHwDevice;
Mikhail Naganove4f1f632016-08-31 11:35:10 -0700363 }
Eric Laurentf1c04f92012-08-28 14:26:53 -0700364 }
Eric Laurenta4c5a552012-03-29 10:12:40 -0700365 } else {
366 // check a match for the requested module handle
John Grossmanee578c02012-07-23 17:05:46 -0700367 AudioHwDevice *audioHwDevice = mAudioHwDevs.valueFor(module);
368 if (audioHwDevice != NULL) {
369 return audioHwDevice;
Eric Laurenta4c5a552012-03-29 10:12:40 -0700370 }
371 }
Eric Laurenta4c5a552012-03-29 10:12:40 -0700372
Dima Zavin799a70e2011-04-18 16:57:27 -0700373 return NULL;
374}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700375
Glenn Kasten0f11b512014-01-31 16:18:54 -0800376void AudioFlinger::dumpClients(int fd, const Vector<String16>& args __unused)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700377{
378 const size_t SIZE = 256;
379 char buffer[SIZE];
380 String8 result;
381
382 result.append("Clients:\n");
383 for (size_t i = 0; i < mClients.size(); ++i) {
Glenn Kasten77c11192012-01-25 14:27:41 -0800384 sp<Client> client = mClients.valueAt(i).promote();
385 if (client != 0) {
386 snprintf(buffer, SIZE, " pid: %d\n", client->pid());
387 result.append(buffer);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700388 }
389 }
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700390
Eric Laurentd1b28d42013-09-18 18:47:13 -0700391 result.append("Notification Clients:\n");
392 for (size_t i = 0; i < mNotificationClients.size(); ++i) {
393 snprintf(buffer, SIZE, " pid: %d\n", mNotificationClients.keyAt(i));
394 result.append(buffer);
395 }
396
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700397 result.append("Global session refs:\n");
Marco Nelissenb2208842014-02-07 14:00:50 -0800398 result.append(" session pid count\n");
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700399 for (size_t i = 0; i < mAudioSessionRefs.size(); i++) {
400 AudioSessionRef *r = mAudioSessionRefs[i];
Marco Nelissenb2208842014-02-07 14:00:50 -0800401 snprintf(buffer, SIZE, " %7d %5d %5d\n", r->mSessionid, r->mPid, r->mCnt);
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700402 result.append(buffer);
403 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700404 write(fd, result.string(), result.size());
Mathias Agopian65ab4712010-07-14 17:59:35 -0700405}
406
407
Glenn Kasten0f11b512014-01-31 16:18:54 -0800408void AudioFlinger::dumpInternals(int fd, const Vector<String16>& args __unused)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700409{
410 const size_t SIZE = 256;
411 char buffer[SIZE];
412 String8 result;
Glenn Kastena4454b42012-01-04 11:02:33 -0800413 hardware_call_state hardwareStatus = mHardwareStatus;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700414
John Grossman4ff14ba2012-02-08 16:37:41 -0800415 snprintf(buffer, SIZE, "Hardware status: %d\n"
416 "Standby Time mSec: %u\n",
417 hardwareStatus,
418 (uint32_t)(mStandbyTimeInNsecs / 1000000));
Mathias Agopian65ab4712010-07-14 17:59:35 -0700419 result.append(buffer);
420 write(fd, result.string(), result.size());
Mathias Agopian65ab4712010-07-14 17:59:35 -0700421}
422
Glenn Kasten0f11b512014-01-31 16:18:54 -0800423void AudioFlinger::dumpPermissionDenial(int fd, const Vector<String16>& args __unused)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700424{
425 const size_t SIZE = 256;
426 char buffer[SIZE];
427 String8 result;
428 snprintf(buffer, SIZE, "Permission Denial: "
429 "can't dump AudioFlinger from pid=%d, uid=%d\n",
430 IPCThreadState::self()->getCallingPid(),
431 IPCThreadState::self()->getCallingUid());
432 result.append(buffer);
433 write(fd, result.string(), result.size());
Mathias Agopian65ab4712010-07-14 17:59:35 -0700434}
435
Eric Laurent81784c32012-11-19 14:55:58 -0800436bool AudioFlinger::dumpTryLock(Mutex& mutex)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700437{
438 bool locked = false;
439 for (int i = 0; i < kDumpLockRetries; ++i) {
440 if (mutex.tryLock() == NO_ERROR) {
441 locked = true;
442 break;
443 }
Glenn Kasten7dede872011-12-13 11:04:14 -0800444 usleep(kDumpLockSleepUs);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700445 }
446 return locked;
447}
448
449status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
450{
Glenn Kasten44deb052012-02-05 18:09:08 -0800451 if (!dumpAllowed()) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700452 dumpPermissionDenial(fd, args);
453 } else {
454 // get state of hardware lock
Eric Laurent81784c32012-11-19 14:55:58 -0800455 bool hardwareLocked = dumpTryLock(mHardwareLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700456 if (!hardwareLocked) {
457 String8 result(kHardwareLockedString);
458 write(fd, result.string(), result.size());
459 } else {
460 mHardwareLock.unlock();
461 }
462
Eric Laurent81784c32012-11-19 14:55:58 -0800463 bool locked = dumpTryLock(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700464
465 // failed to lock - AudioFlinger is probably deadlocked
466 if (!locked) {
467 String8 result(kDeadlockedString);
468 write(fd, result.string(), result.size());
469 }
470
Eric Laurent021cf962014-05-13 10:18:14 -0700471 bool clientLocked = dumpTryLock(mClientLock);
472 if (!clientLocked) {
473 String8 result(kClientLockedString);
474 write(fd, result.string(), result.size());
475 }
Marco Nelissend89eadd2014-10-07 13:28:44 -0700476
Mikhail Naganov1dc98672016-08-18 17:50:29 -0700477 if (mEffectsFactoryHal != 0) {
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700478 mEffectsFactoryHal->dumpEffects(fd);
479 } else {
480 String8 result(kNoEffectsFactory);
481 write(fd, result.string(), result.size());
482 }
Marco Nelissend89eadd2014-10-07 13:28:44 -0700483
Mathias Agopian65ab4712010-07-14 17:59:35 -0700484 dumpClients(fd, args);
Eric Laurent021cf962014-05-13 10:18:14 -0700485 if (clientLocked) {
486 mClientLock.unlock();
487 }
488
Mathias Agopian65ab4712010-07-14 17:59:35 -0700489 dumpInternals(fd, args);
490
491 // dump playback threads
492 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
493 mPlaybackThreads.valueAt(i)->dump(fd, args);
494 }
495
496 // dump record threads
497 for (size_t i = 0; i < mRecordThreads.size(); i++) {
498 mRecordThreads.valueAt(i)->dump(fd, args);
499 }
500
Eric Laurent6acd1d42017-01-04 14:23:29 -0800501 // dump mmap threads
502 for (size_t i = 0; i < mMmapThreads.size(); i++) {
503 mMmapThreads.valueAt(i)->dump(fd, args);
504 }
505
Eric Laurentaaa44472014-09-12 17:41:50 -0700506 // dump orphan effect chains
507 if (mOrphanEffectChains.size() != 0) {
508 write(fd, " Orphan Effect Chains\n", strlen(" Orphan Effect Chains\n"));
509 for (size_t i = 0; i < mOrphanEffectChains.size(); i++) {
510 mOrphanEffectChains.valueAt(i)->dump(fd, args);
511 }
512 }
Dima Zavin799a70e2011-04-18 16:57:27 -0700513 // dump all hardware devs
514 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
Mikhail Naganove4f1f632016-08-31 11:35:10 -0700515 sp<DeviceHalInterface> dev = mAudioHwDevs.valueAt(i)->hwDevice();
516 dev->dump(fd);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700517 }
Glenn Kastend06785b2012-09-30 12:29:28 -0700518
Glenn Kasten46909e72013-02-26 09:20:22 -0800519#ifdef TEE_SINK
Glenn Kastend06785b2012-09-30 12:29:28 -0700520 // dump the serially shared record tee sink
521 if (mRecordTeeSource != 0) {
Glenn Kasten5b2191a2016-08-19 11:44:47 -0700522 dumpTee(fd, mRecordTeeSource, AUDIO_IO_HANDLE_NONE, 'C');
Glenn Kastend06785b2012-09-30 12:29:28 -0700523 }
Glenn Kasten46909e72013-02-26 09:20:22 -0800524#endif
Glenn Kastend06785b2012-09-30 12:29:28 -0700525
rago3bd1c872016-09-26 12:58:14 -0700526 BUFLOG_RESET;
527
Glenn Kastend65d73c2012-06-22 17:21:07 -0700528 if (locked) {
529 mLock.unlock();
530 }
Glenn Kasten9e58b552013-01-18 15:09:48 -0800531
532 // append a copy of media.log here by forwarding fd to it, but don't attempt
533 // to lookup the service if it's not running, as it will block for a second
Glenn Kasten04b96fc2017-04-10 14:58:47 -0700534 if (sMediaLogServiceAsBinder != 0) {
535 dprintf(fd, "\nmedia.log:\n");
536 Vector<String16> args;
537 sMediaLogServiceAsBinder->dump(fd, args);
Glenn Kasten9e58b552013-01-18 15:09:48 -0800538 }
Andy Hung35fec5f2016-04-13 14:21:48 -0700539
540 // check for optional arguments
Andy Hung07b745e2016-05-23 16:21:07 -0700541 bool dumpMem = false;
Andy Hung35fec5f2016-04-13 14:21:48 -0700542 bool unreachableMemory = false;
543 for (const auto &arg : args) {
Andy Hung07b745e2016-05-23 16:21:07 -0700544 if (arg == String16("-m")) {
545 dumpMem = true;
546 } else if (arg == String16("--unreachable")) {
Andy Hung35fec5f2016-04-13 14:21:48 -0700547 unreachableMemory = true;
548 }
549 }
550
Andy Hung07b745e2016-05-23 16:21:07 -0700551 if (dumpMem) {
552 dprintf(fd, "\nDumping memory:\n");
553 std::string s = dumpMemoryAddresses(100 /* limit */);
554 write(fd, s.c_str(), s.size());
555 }
Andy Hung35fec5f2016-04-13 14:21:48 -0700556 if (unreachableMemory) {
557 dprintf(fd, "\nDumping unreachable memory:\n");
558 // TODO - should limit be an argument parameter?
Andy Hung07b745e2016-05-23 16:21:07 -0700559 std::string s = GetUnreachableMemoryString(true /* contents */, 100 /* limit */);
Andy Hung35fec5f2016-04-13 14:21:48 -0700560 write(fd, s.c_str(), s.size());
561 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700562 }
563 return NO_ERROR;
564}
565
Eric Laurent021cf962014-05-13 10:18:14 -0700566sp<AudioFlinger::Client> AudioFlinger::registerPid(pid_t pid)
Glenn Kasten98ec94c2012-01-25 14:28:29 -0800567{
Eric Laurent021cf962014-05-13 10:18:14 -0700568 Mutex::Autolock _cl(mClientLock);
Glenn Kasten98ec94c2012-01-25 14:28:29 -0800569 // If pid is already in the mClients wp<> map, then use that entry
570 // (for which promote() is always != 0), otherwise create a new entry and Client.
571 sp<Client> client = mClients.valueFor(pid).promote();
572 if (client == 0) {
573 client = new Client(this, pid);
574 mClients.add(pid, client);
575 }
576
577 return client;
578}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700579
Glenn Kasten9e58b552013-01-18 15:09:48 -0800580sp<NBLog::Writer> AudioFlinger::newWriter_l(size_t size, const char *name)
581{
Glenn Kasten04b96fc2017-04-10 14:58:47 -0700582 // If there is no memory allocated for logs, return a dummy writer that does nothing.
583 // Similarly if we can't contact the media.log service, also return a dummy writer.
584 if (mLogMemoryDealer == 0 || sMediaLogService == 0) {
Glenn Kasten9e58b552013-01-18 15:09:48 -0800585 return new NBLog::Writer();
586 }
Glenn Kasten481fb672013-09-30 14:39:28 -0700587 sp<IMemory> shared = mLogMemoryDealer->allocate(NBLog::Timeline::sharedSize(size));
588 // If allocation fails, consult the vector of previously unregistered writers
589 // and garbage-collect one or more them until an allocation succeeds
590 if (shared == 0) {
591 Mutex::Autolock _l(mUnregisteredWritersLock);
592 for (size_t count = mUnregisteredWriters.size(); count > 0; count--) {
593 {
594 // Pick the oldest stale writer to garbage-collect
595 sp<IMemory> iMemory(mUnregisteredWriters[0]->getIMemory());
596 mUnregisteredWriters.removeAt(0);
Glenn Kasten04b96fc2017-04-10 14:58:47 -0700597 sMediaLogService->unregisterWriter(iMemory);
Glenn Kasten481fb672013-09-30 14:39:28 -0700598 // Now the media.log remote reference to IMemory is gone. When our last local
599 // reference to IMemory also drops to zero at end of this block,
600 // the IMemory destructor will deallocate the region from mLogMemoryDealer.
601 }
602 // Re-attempt the allocation
603 shared = mLogMemoryDealer->allocate(NBLog::Timeline::sharedSize(size));
604 if (shared != 0) {
605 goto success;
606 }
607 }
608 // Even after garbage-collecting all old writers, there is still not enough memory,
609 // so return a dummy writer
610 return new NBLog::Writer();
611 }
612success:
Glenn Kasten535e1612016-12-05 12:19:36 -0800613 NBLog::Shared *sharedRawPtr = (NBLog::Shared *) shared->pointer();
614 new((void *) sharedRawPtr) NBLog::Shared(); // placement new here, but the corresponding
615 // explicit destructor not needed since it is POD
Glenn Kasten04b96fc2017-04-10 14:58:47 -0700616 sMediaLogService->registerWriter(shared, size, name);
Glenn Kasten535e1612016-12-05 12:19:36 -0800617 return new NBLog::Writer(shared, size);
Glenn Kasten9e58b552013-01-18 15:09:48 -0800618}
619
620void AudioFlinger::unregisterWriter(const sp<NBLog::Writer>& writer)
621{
Glenn Kasten685ef092013-02-04 08:15:34 -0800622 if (writer == 0) {
623 return;
624 }
Glenn Kasten9e58b552013-01-18 15:09:48 -0800625 sp<IMemory> iMemory(writer->getIMemory());
626 if (iMemory == 0) {
627 return;
628 }
Glenn Kasten481fb672013-09-30 14:39:28 -0700629 // Rather than removing the writer immediately, append it to a queue of old writers to
630 // be garbage-collected later. This allows us to continue to view old logs for a while.
631 Mutex::Autolock _l(mUnregisteredWritersLock);
632 mUnregisteredWriters.push(writer);
Glenn Kasten9e58b552013-01-18 15:09:48 -0800633}
634
Mathias Agopian65ab4712010-07-14 17:59:35 -0700635// IAudioFlinger interface
636
637
638sp<IAudioTrack> AudioFlinger::createTrack(
Glenn Kastenfff6d712012-01-12 16:38:12 -0800639 audio_stream_type_t streamType,
Mathias Agopian65ab4712010-07-14 17:59:35 -0700640 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -0800641 audio_format_t format,
Glenn Kasten254af182012-07-03 14:59:05 -0700642 audio_channel_mask_t channelMask,
Glenn Kasten74935e42013-12-19 08:56:45 -0800643 size_t *frameCount,
Eric Laurent05067782016-06-01 18:27:28 -0700644 audio_output_flags_t *flags,
Mathias Agopian65ab4712010-07-14 17:59:35 -0700645 const sp<IMemory>& sharedBuffer,
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800646 audio_io_handle_t output,
Haynes Mathew George9ea77cd2016-04-06 17:07:48 -0700647 pid_t pid,
Glenn Kasten3acbd052012-02-28 10:39:56 -0800648 pid_t tid,
Glenn Kastend848eb42016-03-08 13:42:11 -0800649 audio_session_t *sessionId,
Marco Nelissen462fd2f2013-01-14 14:12:05 -0800650 int clientUid,
Eric Laurent20b9ef02016-12-05 11:03:16 -0800651 status_t *status,
652 audio_port_handle_t portId)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700653{
654 sp<PlaybackThread::Track> track;
655 sp<TrackHandle> trackHandle;
656 sp<Client> client;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700657 status_t lStatus;
Glenn Kastend848eb42016-03-08 13:42:11 -0800658 audio_session_t lSessionId;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700659
Haynes Mathew George9ea77cd2016-04-06 17:07:48 -0700660 const uid_t callingUid = IPCThreadState::self()->getCallingUid();
661 if (pid == -1 || !isTrustedCallingUid(callingUid)) {
662 const pid_t callingPid = IPCThreadState::self()->getCallingPid();
663 ALOGW_IF(pid != -1 && pid != callingPid,
664 "%s uid %d pid %d tried to pass itself off as pid %d",
665 __func__, callingUid, callingPid, pid);
666 pid = callingPid;
667 }
668
Glenn Kasten263709e2012-01-06 08:40:01 -0800669 // client AudioTrack::set already implements AUDIO_STREAM_DEFAULT => AUDIO_STREAM_MUSIC,
670 // but if someone uses binder directly they could bypass that and cause us to crash
671 if (uint32_t(streamType) >= AUDIO_STREAM_CNT) {
Steve Block29357bc2012-01-06 19:20:56 +0000672 ALOGE("createTrack() invalid stream type %d", streamType);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700673 lStatus = BAD_VALUE;
674 goto Exit;
675 }
676
Glenn Kasten53b5d092014-02-05 10:00:23 -0800677 // further sample rate checks are performed by createTrack_l() depending on the thread type
678 if (sampleRate == 0) {
679 ALOGE("createTrack() invalid sample rate %u", sampleRate);
680 lStatus = BAD_VALUE;
681 goto Exit;
682 }
683
684 // further channel mask checks are performed by createTrack_l() depending on the thread type
685 if (!audio_is_output_channel(channelMask)) {
686 ALOGE("createTrack() invalid channel mask %#x", channelMask);
687 lStatus = BAD_VALUE;
688 goto Exit;
689 }
690
Glenn Kastenc4b88a82014-04-30 16:54:30 -0700691 // further format checks are performed by createTrack_l() depending on the thread type
692 if (!audio_is_valid_format(format)) {
Glenn Kastencac3daa2014-02-07 09:47:14 -0800693 ALOGE("createTrack() invalid format %#x", format);
Glenn Kasten60a83922012-06-21 12:56:37 -0700694 lStatus = BAD_VALUE;
695 goto Exit;
696 }
697
Glenn Kasten663c2242013-09-24 11:52:37 -0700698 if (sharedBuffer != 0 && sharedBuffer->pointer() == NULL) {
699 ALOGE("createTrack() sharedBuffer is non-0 but has NULL pointer()");
700 lStatus = BAD_VALUE;
701 goto Exit;
702 }
703
Mathias Agopian65ab4712010-07-14 17:59:35 -0700704 {
705 Mutex::Autolock _l(mLock);
706 PlaybackThread *thread = checkPlaybackThread_l(output);
707 if (thread == NULL) {
Glenn Kastenc9b2e202013-02-26 11:32:32 -0800708 ALOGE("no playback thread found for output handle %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700709 lStatus = BAD_VALUE;
710 goto Exit;
711 }
712
Eric Laurent021cf962014-05-13 10:18:14 -0700713 client = registerPid(pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700714
Glenn Kastene848bd92014-03-13 15:00:32 -0700715 PlaybackThread *effectThread = NULL;
Glenn Kastenaea7ea02013-06-26 09:25:47 -0700716 if (sessionId != NULL && *sessionId != AUDIO_SESSION_ALLOCATE) {
Glenn Kasteneeecb982016-02-26 10:44:04 -0800717 if (audio_unique_id_get_use(*sessionId) != AUDIO_UNIQUE_ID_USE_SESSION) {
718 ALOGE("createTrack() invalid session ID %d", *sessionId);
719 lStatus = BAD_VALUE;
720 goto Exit;
721 }
Glenn Kasten570f6332014-03-13 15:01:06 -0700722 lSessionId = *sessionId;
Eric Laurentf436fdc2012-05-24 11:07:14 -0700723 // check if an effect chain with the same session ID is present on another
724 // output thread and move it here.
Eric Laurentde070132010-07-13 04:45:46 -0700725 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurent39e94f82010-07-28 01:32:47 -0700726 sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
727 if (mPlaybackThreads.keyAt(i) != output) {
Glenn Kasten570f6332014-03-13 15:01:06 -0700728 uint32_t sessions = t->hasAudioSession(lSessionId);
Eric Laurent4c415062016-06-17 16:14:16 -0700729 if (sessions & ThreadBase::EFFECT_SESSION) {
Eric Laurent39e94f82010-07-28 01:32:47 -0700730 effectThread = t.get();
Eric Laurentf436fdc2012-05-24 11:07:14 -0700731 break;
Eric Laurent39e94f82010-07-28 01:32:47 -0700732 }
Eric Laurentde070132010-07-13 04:45:46 -0700733 }
734 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700735 } else {
Eric Laurentde070132010-07-13 04:45:46 -0700736 // if no audio session id is provided, create one here
Glenn Kastend848eb42016-03-08 13:42:11 -0800737 lSessionId = (audio_session_t) nextUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700738 if (sessionId != NULL) {
739 *sessionId = lSessionId;
740 }
741 }
Steve Block3856b092011-10-20 11:56:00 +0100742 ALOGV("createTrack() lSessionId: %d", lSessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700743
744 track = thread->createTrack_l(client, streamType, sampleRate, format,
Eric Laurent20b9ef02016-12-05 11:03:16 -0800745 channelMask, frameCount, sharedBuffer, lSessionId, flags, tid,
746 clientUid, &lStatus, portId);
Haynes Mathew George03e9e832013-12-13 15:40:13 -0800747 LOG_ALWAYS_FATAL_IF((lStatus == NO_ERROR) && (track == 0));
Glenn Kasten2fc14732013-08-05 14:58:14 -0700748 // we don't abort yet if lStatus != NO_ERROR; there is still work to be done regardless
Eric Laurent39e94f82010-07-28 01:32:47 -0700749
750 // move effect chain to this output thread if an effect on same session was waiting
751 // for a track to be created
752 if (lStatus == NO_ERROR && effectThread != NULL) {
Glenn Kasten2fc14732013-08-05 14:58:14 -0700753 // no risk of deadlock because AudioFlinger::mLock is held
Eric Laurent39e94f82010-07-28 01:32:47 -0700754 Mutex::Autolock _dl(thread->mLock);
755 Mutex::Autolock _sl(effectThread->mLock);
756 moveEffectChain_l(lSessionId, effectThread, thread, true);
757 }
Eric Laurenta011e352012-03-29 15:51:43 -0700758
759 // Look for sync events awaiting for a session to be used.
Mark Salyzyn3ab368e2014-04-15 14:55:53 -0700760 for (size_t i = 0; i < mPendingSyncEvents.size(); i++) {
Eric Laurenta011e352012-03-29 15:51:43 -0700761 if (mPendingSyncEvents[i]->triggerSession() == lSessionId) {
762 if (thread->isValidSyncEvent(mPendingSyncEvents[i])) {
Eric Laurent29864602012-05-08 18:57:51 -0700763 if (lStatus == NO_ERROR) {
Glenn Kastend23eedc2012-08-02 13:35:47 -0700764 (void) track->setSyncEvent(mPendingSyncEvents[i]);
Eric Laurent29864602012-05-08 18:57:51 -0700765 } else {
766 mPendingSyncEvents[i]->cancel();
767 }
Eric Laurenta011e352012-03-29 15:51:43 -0700768 mPendingSyncEvents.removeAt(i);
769 i--;
770 }
771 }
772 }
Glenn Kastene198c362013-08-13 09:13:36 -0700773
Glenn Kastend848eb42016-03-08 13:42:11 -0800774 setAudioHwSyncForSession_l(thread, lSessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700775 }
Glenn Kastene198c362013-08-13 09:13:36 -0700776
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700777 if (lStatus != NO_ERROR) {
778 // remove local strong reference to Client before deleting the Track so that the
Eric Laurent021cf962014-05-13 10:18:14 -0700779 // Client destructor is called by the TrackBase destructor with mClientLock held
Eric Laurentfe1a94e2014-05-26 16:03:08 -0700780 // Don't hold mClientLock when releasing the reference on the track as the
781 // destructor will acquire it.
782 {
783 Mutex::Autolock _cl(mClientLock);
784 client.clear();
785 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700786 track.clear();
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700787 goto Exit;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700788 }
789
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700790 // return handle to client
791 trackHandle = new TrackHandle(track);
792
Mathias Agopian65ab4712010-07-14 17:59:35 -0700793Exit:
Glenn Kasten9156ef32013-08-06 15:39:08 -0700794 *status = lStatus;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700795 return trackHandle;
796}
797
Glenn Kasten2c073da2016-02-26 09:14:08 -0800798uint32_t AudioFlinger::sampleRate(audio_io_handle_t ioHandle) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700799{
800 Mutex::Autolock _l(mLock);
Glenn Kasten2c073da2016-02-26 09:14:08 -0800801 ThreadBase *thread = checkThread_l(ioHandle);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700802 if (thread == NULL) {
Glenn Kasten2c073da2016-02-26 09:14:08 -0800803 ALOGW("sampleRate() unknown thread %d", ioHandle);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700804 return 0;
805 }
806 return thread->sampleRate();
807}
808
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800809audio_format_t AudioFlinger::format(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700810{
811 Mutex::Autolock _l(mLock);
812 PlaybackThread *thread = checkPlaybackThread_l(output);
813 if (thread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000814 ALOGW("format() unknown thread %d", output);
Glenn Kasten58f30212012-01-12 12:27:51 -0800815 return AUDIO_FORMAT_INVALID;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700816 }
817 return thread->format();
818}
819
Glenn Kasten2c073da2016-02-26 09:14:08 -0800820size_t AudioFlinger::frameCount(audio_io_handle_t ioHandle) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700821{
822 Mutex::Autolock _l(mLock);
Glenn Kasten2c073da2016-02-26 09:14:08 -0800823 ThreadBase *thread = checkThread_l(ioHandle);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700824 if (thread == NULL) {
Glenn Kasten2c073da2016-02-26 09:14:08 -0800825 ALOGW("frameCount() unknown thread %d", ioHandle);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700826 return 0;
827 }
Glenn Kasten58912562012-04-03 10:45:00 -0700828 // FIXME currently returns the normal mixer's frame count to avoid confusing legacy callers;
829 // should examine all callers and fix them to handle smaller counts
Mathias Agopian65ab4712010-07-14 17:59:35 -0700830 return thread->frameCount();
831}
832
Glenn Kasten4a8308b2016-04-18 14:10:01 -0700833size_t AudioFlinger::frameCountHAL(audio_io_handle_t ioHandle) const
834{
835 Mutex::Autolock _l(mLock);
836 ThreadBase *thread = checkThread_l(ioHandle);
837 if (thread == NULL) {
838 ALOGW("frameCountHAL() unknown thread %d", ioHandle);
839 return 0;
840 }
841 return thread->frameCountHAL();
842}
843
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800844uint32_t AudioFlinger::latency(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700845{
846 Mutex::Autolock _l(mLock);
847 PlaybackThread *thread = checkPlaybackThread_l(output);
848 if (thread == NULL) {
Glenn Kastenc9b2e202013-02-26 11:32:32 -0800849 ALOGW("latency(): no playback thread found for output handle %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700850 return 0;
851 }
852 return thread->latency();
853}
854
855status_t AudioFlinger::setMasterVolume(float value)
856{
Eric Laurenta1884f92011-08-23 08:25:03 -0700857 status_t ret = initCheck();
858 if (ret != NO_ERROR) {
859 return ret;
860 }
861
Mathias Agopian65ab4712010-07-14 17:59:35 -0700862 // check calling permissions
863 if (!settingsAllowed()) {
864 return PERMISSION_DENIED;
865 }
866
Eric Laurenta4c5a552012-03-29 10:12:40 -0700867 Mutex::Autolock _l(mLock);
John Grossmanee578c02012-07-23 17:05:46 -0700868 mMasterVolume = value;
Eric Laurenta4c5a552012-03-29 10:12:40 -0700869
John Grossmanee578c02012-07-23 17:05:46 -0700870 // Set master volume in the HALs which support it.
871 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
872 AutoMutex lock(mHardwareLock);
873 AudioHwDevice *dev = mAudioHwDevs.valueAt(i);
John Grossman4ff14ba2012-02-08 16:37:41 -0800874
John Grossmanee578c02012-07-23 17:05:46 -0700875 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
876 if (dev->canSetMasterVolume()) {
Mikhail Naganove4f1f632016-08-31 11:35:10 -0700877 dev->hwDevice()->setMasterVolume(value);
Eric Laurent93575202011-01-18 18:39:02 -0800878 }
John Grossmanee578c02012-07-23 17:05:46 -0700879 mHardwareStatus = AUDIO_HW_IDLE;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700880 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700881
John Grossmanee578c02012-07-23 17:05:46 -0700882 // Now set the master volume in each playback thread. Playback threads
883 // assigned to HALs which do not have master volume support will apply
884 // master volume during the mix operation. Threads with HALs which do
885 // support master volume will simply ignore the setting.
Eric Laurentf6870ae2015-05-08 10:50:03 -0700886 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
887 if (mPlaybackThreads.valueAt(i)->isDuplicating()) {
888 continue;
889 }
John Grossmanee578c02012-07-23 17:05:46 -0700890 mPlaybackThreads.valueAt(i)->setMasterVolume(value);
Eric Laurentf6870ae2015-05-08 10:50:03 -0700891 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700892
893 return NO_ERROR;
894}
895
Glenn Kastenf78aee72012-01-04 11:00:47 -0800896status_t AudioFlinger::setMode(audio_mode_t mode)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700897{
Eric Laurenta1884f92011-08-23 08:25:03 -0700898 status_t ret = initCheck();
899 if (ret != NO_ERROR) {
900 return ret;
901 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700902
903 // check calling permissions
904 if (!settingsAllowed()) {
905 return PERMISSION_DENIED;
906 }
Glenn Kasten930f4ca2012-01-06 16:47:31 -0800907 if (uint32_t(mode) >= AUDIO_MODE_CNT) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000908 ALOGW("Illegal value: setMode(%d)", mode);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700909 return BAD_VALUE;
910 }
911
912 { // scope for the lock
913 AutoMutex lock(mHardwareLock);
Mikhail Naganove4f1f632016-08-31 11:35:10 -0700914 sp<DeviceHalInterface> dev = mPrimaryHardwareDev->hwDevice();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700915 mHardwareStatus = AUDIO_HW_SET_MODE;
Mikhail Naganove4f1f632016-08-31 11:35:10 -0700916 ret = dev->setMode(mode);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700917 mHardwareStatus = AUDIO_HW_IDLE;
918 }
919
920 if (NO_ERROR == ret) {
921 Mutex::Autolock _l(mLock);
922 mMode = mode;
Glenn Kasten8d6a2442012-02-08 14:04:28 -0800923 for (size_t i = 0; i < mPlaybackThreads.size(); i++)
Glenn Kastene53b9ea2012-03-12 16:29:55 -0700924 mPlaybackThreads.valueAt(i)->setMode(mode);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700925 }
926
927 return ret;
928}
929
930status_t AudioFlinger::setMicMute(bool state)
931{
Eric Laurenta1884f92011-08-23 08:25:03 -0700932 status_t ret = initCheck();
933 if (ret != NO_ERROR) {
934 return ret;
935 }
936
Mathias Agopian65ab4712010-07-14 17:59:35 -0700937 // check calling permissions
938 if (!settingsAllowed()) {
939 return PERMISSION_DENIED;
940 }
941
942 AutoMutex lock(mHardwareLock);
943 mHardwareStatus = AUDIO_HW_SET_MIC_MUTE;
Eric Laurent2f035f52014-09-14 12:11:52 -0700944 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
Mikhail Naganove4f1f632016-08-31 11:35:10 -0700945 sp<DeviceHalInterface> dev = mAudioHwDevs.valueAt(i)->hwDevice();
946 status_t result = dev->setMicMute(state);
Eric Laurent2f035f52014-09-14 12:11:52 -0700947 if (result != NO_ERROR) {
948 ret = result;
949 }
950 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700951 mHardwareStatus = AUDIO_HW_IDLE;
952 return ret;
953}
954
955bool AudioFlinger::getMicMute() const
956{
Eric Laurenta1884f92011-08-23 08:25:03 -0700957 status_t ret = initCheck();
958 if (ret != NO_ERROR) {
959 return false;
960 }
Ricardo Garcia3e91b5d2015-02-19 10:54:52 -0800961 bool mute = true;
Dima Zavinfce7a472011-04-19 22:30:36 -0700962 bool state = AUDIO_MODE_INVALID;
Glenn Kasten2b213bc2012-02-02 14:05:20 -0800963 AutoMutex lock(mHardwareLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700964 mHardwareStatus = AUDIO_HW_GET_MIC_MUTE;
Ricardo Garcia3e91b5d2015-02-19 10:54:52 -0800965 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
Mikhail Naganove4f1f632016-08-31 11:35:10 -0700966 sp<DeviceHalInterface> dev = mAudioHwDevs.valueAt(i)->hwDevice();
967 status_t result = dev->getMicMute(&state);
Ricardo Garcia3e91b5d2015-02-19 10:54:52 -0800968 if (result == NO_ERROR) {
969 mute = mute && state;
970 }
971 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700972 mHardwareStatus = AUDIO_HW_IDLE;
Ricardo Garcia3e91b5d2015-02-19 10:54:52 -0800973
974 return mute;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700975}
976
977status_t AudioFlinger::setMasterMute(bool muted)
978{
John Grossmand8f178d2012-07-20 14:51:35 -0700979 status_t ret = initCheck();
980 if (ret != NO_ERROR) {
981 return ret;
982 }
983
Mathias Agopian65ab4712010-07-14 17:59:35 -0700984 // check calling permissions
985 if (!settingsAllowed()) {
986 return PERMISSION_DENIED;
987 }
988
John Grossmanee578c02012-07-23 17:05:46 -0700989 Mutex::Autolock _l(mLock);
990 mMasterMute = muted;
John Grossmand8f178d2012-07-20 14:51:35 -0700991
John Grossmanee578c02012-07-23 17:05:46 -0700992 // Set master mute in the HALs which support it.
993 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
994 AutoMutex lock(mHardwareLock);
995 AudioHwDevice *dev = mAudioHwDevs.valueAt(i);
John Grossmand8f178d2012-07-20 14:51:35 -0700996
John Grossmanee578c02012-07-23 17:05:46 -0700997 mHardwareStatus = AUDIO_HW_SET_MASTER_MUTE;
998 if (dev->canSetMasterMute()) {
Mikhail Naganove4f1f632016-08-31 11:35:10 -0700999 dev->hwDevice()->setMasterMute(muted);
John Grossmand8f178d2012-07-20 14:51:35 -07001000 }
John Grossmanee578c02012-07-23 17:05:46 -07001001 mHardwareStatus = AUDIO_HW_IDLE;
John Grossmand8f178d2012-07-20 14:51:35 -07001002 }
1003
John Grossmanee578c02012-07-23 17:05:46 -07001004 // Now set the master mute in each playback thread. Playback threads
1005 // assigned to HALs which do not have master mute support will apply master
1006 // mute during the mix operation. Threads with HALs which do support master
1007 // mute will simply ignore the setting.
Eric Laurent6acd1d42017-01-04 14:23:29 -08001008 Vector<VolumeInterface *> volumeInterfaces = getAllVolumeInterfaces_l();
1009 for (size_t i = 0; i < volumeInterfaces.size(); i++) {
1010 volumeInterfaces[i]->setMasterMute(muted);
Eric Laurentf6870ae2015-05-08 10:50:03 -07001011 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001012
1013 return NO_ERROR;
1014}
1015
1016float AudioFlinger::masterVolume() const
1017{
Glenn Kasten98067102011-12-13 11:47:54 -08001018 Mutex::Autolock _l(mLock);
1019 return masterVolume_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001020}
1021
1022bool AudioFlinger::masterMute() const
1023{
Glenn Kasten98067102011-12-13 11:47:54 -08001024 Mutex::Autolock _l(mLock);
1025 return masterMute_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001026}
1027
John Grossman4ff14ba2012-02-08 16:37:41 -08001028float AudioFlinger::masterVolume_l() const
1029{
John Grossman4ff14ba2012-02-08 16:37:41 -08001030 return mMasterVolume;
1031}
1032
John Grossmand8f178d2012-07-20 14:51:35 -07001033bool AudioFlinger::masterMute_l() const
1034{
John Grossmanee578c02012-07-23 17:05:46 -07001035 return mMasterMute;
John Grossmand8f178d2012-07-20 14:51:35 -07001036}
1037
Eric Laurent223fd5c2014-11-11 13:43:36 -08001038status_t AudioFlinger::checkStreamType(audio_stream_type_t stream) const
1039{
1040 if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
Eric Laurent6acd1d42017-01-04 14:23:29 -08001041 ALOGW("checkStreamType() invalid stream %d", stream);
Eric Laurent223fd5c2014-11-11 13:43:36 -08001042 return BAD_VALUE;
1043 }
1044 pid_t caller = IPCThreadState::self()->getCallingPid();
1045 if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT && caller != getpid_cached) {
Eric Laurent6acd1d42017-01-04 14:23:29 -08001046 ALOGW("checkStreamType() pid %d cannot use internal stream type %d", caller, stream);
Eric Laurent223fd5c2014-11-11 13:43:36 -08001047 return PERMISSION_DENIED;
1048 }
1049
1050 return NO_ERROR;
1051}
1052
Glenn Kasten72ef00d2012-01-17 11:09:42 -08001053status_t AudioFlinger::setStreamVolume(audio_stream_type_t stream, float value,
1054 audio_io_handle_t output)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001055{
1056 // check calling permissions
1057 if (!settingsAllowed()) {
1058 return PERMISSION_DENIED;
1059 }
1060
Eric Laurent223fd5c2014-11-11 13:43:36 -08001061 status_t status = checkStreamType(stream);
1062 if (status != NO_ERROR) {
1063 return status;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001064 }
Eric Laurent223fd5c2014-11-11 13:43:36 -08001065 ALOG_ASSERT(stream != AUDIO_STREAM_PATCH, "attempt to change AUDIO_STREAM_PATCH volume");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001066
1067 AutoMutex lock(mLock);
Eric Laurent6acd1d42017-01-04 14:23:29 -08001068 Vector<VolumeInterface *> volumeInterfaces;
Glenn Kasten142f5192014-03-25 17:44:59 -07001069 if (output != AUDIO_IO_HANDLE_NONE) {
Eric Laurent6acd1d42017-01-04 14:23:29 -08001070 VolumeInterface *volumeInterface = getVolumeInterface_l(output);
1071 if (volumeInterface == NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001072 return BAD_VALUE;
1073 }
Eric Laurent6acd1d42017-01-04 14:23:29 -08001074 volumeInterfaces.add(volumeInterface);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001075 }
1076
1077 mStreamTypes[stream].volume = value;
1078
Eric Laurent6acd1d42017-01-04 14:23:29 -08001079 if (volumeInterfaces.size() == 0) {
1080 volumeInterfaces = getAllVolumeInterfaces_l();
1081 }
1082 for (size_t i = 0; i < volumeInterfaces.size(); i++) {
1083 volumeInterfaces[i]->setStreamVolume(stream, value);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001084 }
1085
1086 return NO_ERROR;
1087}
1088
Glenn Kastenfff6d712012-01-12 16:38:12 -08001089status_t AudioFlinger::setStreamMute(audio_stream_type_t stream, bool muted)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001090{
1091 // check calling permissions
1092 if (!settingsAllowed()) {
1093 return PERMISSION_DENIED;
1094 }
1095
Eric Laurent223fd5c2014-11-11 13:43:36 -08001096 status_t status = checkStreamType(stream);
1097 if (status != NO_ERROR) {
1098 return status;
1099 }
1100 ALOG_ASSERT(stream != AUDIO_STREAM_PATCH, "attempt to mute AUDIO_STREAM_PATCH");
1101
1102 if (uint32_t(stream) == AUDIO_STREAM_ENFORCED_AUDIBLE) {
Steve Block29357bc2012-01-06 19:20:56 +00001103 ALOGE("setStreamMute() invalid stream %d", stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001104 return BAD_VALUE;
1105 }
1106
Eric Laurent93575202011-01-18 18:39:02 -08001107 AutoMutex lock(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001108 mStreamTypes[stream].mute = muted;
Eric Laurent6acd1d42017-01-04 14:23:29 -08001109 Vector<VolumeInterface *> volumeInterfaces = getAllVolumeInterfaces_l();
1110 for (size_t i = 0; i < volumeInterfaces.size(); i++) {
1111 volumeInterfaces[i]->setStreamMute(stream, muted);
1112 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001113
1114 return NO_ERROR;
1115}
1116
Glenn Kasten72ef00d2012-01-17 11:09:42 -08001117float AudioFlinger::streamVolume(audio_stream_type_t stream, audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07001118{
Eric Laurent223fd5c2014-11-11 13:43:36 -08001119 status_t status = checkStreamType(stream);
1120 if (status != NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001121 return 0.0f;
1122 }
1123
1124 AutoMutex lock(mLock);
1125 float volume;
Glenn Kasten142f5192014-03-25 17:44:59 -07001126 if (output != AUDIO_IO_HANDLE_NONE) {
Eric Laurent6acd1d42017-01-04 14:23:29 -08001127 VolumeInterface *volumeInterface = getVolumeInterface_l(output);
1128 if (volumeInterface != NULL) {
1129 volume = volumeInterface->streamVolume(stream);
1130 } else {
1131 volume = 0.0f;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001132 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001133 } else {
Glenn Kasten6637baa2012-01-09 09:40:36 -08001134 volume = streamVolume_l(stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001135 }
1136
1137 return volume;
1138}
1139
Glenn Kastenfff6d712012-01-12 16:38:12 -08001140bool AudioFlinger::streamMute(audio_stream_type_t stream) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07001141{
Eric Laurent223fd5c2014-11-11 13:43:36 -08001142 status_t status = checkStreamType(stream);
1143 if (status != NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001144 return true;
1145 }
1146
Glenn Kasten6637baa2012-01-09 09:40:36 -08001147 AutoMutex lock(mLock);
1148 return streamMute_l(stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001149}
1150
Eric Laurent054d9d32015-04-24 08:48:48 -07001151
1152void AudioFlinger::broacastParametersToRecordThreads_l(const String8& keyValuePairs)
1153{
1154 for (size_t i = 0; i < mRecordThreads.size(); i++) {
1155 mRecordThreads.valueAt(i)->setParameters(keyValuePairs);
1156 }
1157}
1158
Glenn Kasten72ef00d2012-01-17 11:09:42 -08001159status_t AudioFlinger::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001160{
Glenn Kasten827e5f12012-11-02 10:00:06 -07001161 ALOGV("setParameters(): io %d, keyvalue %s, calling pid %d",
1162 ioHandle, keyValuePairs.string(), IPCThreadState::self()->getCallingPid());
Eric Laurent81784c32012-11-19 14:55:58 -08001163
Mathias Agopian65ab4712010-07-14 17:59:35 -07001164 // check calling permissions
1165 if (!settingsAllowed()) {
1166 return PERMISSION_DENIED;
1167 }
1168
Glenn Kasten142f5192014-03-25 17:44:59 -07001169 // AUDIO_IO_HANDLE_NONE means the parameters are global to the audio hardware interface
1170 if (ioHandle == AUDIO_IO_HANDLE_NONE) {
Eric Laurenta4c5a552012-03-29 10:12:40 -07001171 Mutex::Autolock _l(mLock);
Eric Laurentd21bcd22016-09-08 18:25:54 -07001172 // result will remain NO_INIT if no audio device is present
1173 status_t final_result = NO_INIT;
Glenn Kasten8abf44d2012-02-02 14:16:03 -08001174 {
Eric Laurenta4c5a552012-03-29 10:12:40 -07001175 AutoMutex lock(mHardwareLock);
1176 mHardwareStatus = AUDIO_HW_SET_PARAMETER;
1177 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001178 sp<DeviceHalInterface> dev = mAudioHwDevs.valueAt(i)->hwDevice();
1179 status_t result = dev->setParameters(keyValuePairs);
Eric Laurentd21bcd22016-09-08 18:25:54 -07001180 // return success if at least one audio device accepts the parameters as not all
1181 // HALs are requested to support all parameters. If no audio device supports the
1182 // requested parameters, the last error is reported.
1183 if (final_result != NO_ERROR) {
1184 final_result = result;
1185 }
Eric Laurenta4c5a552012-03-29 10:12:40 -07001186 }
1187 mHardwareStatus = AUDIO_HW_IDLE;
Glenn Kasten8abf44d2012-02-02 14:16:03 -08001188 }
Eric Laurent59bd0da2011-08-01 09:52:20 -07001189 // disable AEC and NS if the device is a BT SCO headset supporting those pre processings
1190 AudioParameter param = AudioParameter(keyValuePairs);
1191 String8 value;
Mikhail Naganov00260b52016-10-13 12:54:24 -07001192 if (param.get(String8(AudioParameter::keyBtNrec), value) == NO_ERROR) {
1193 bool btNrecIsOff = (value == AudioParameter::valueOff);
Eric Laurentbee53372011-08-29 12:42:48 -07001194 if (mBtNrecIsOff != btNrecIsOff) {
Eric Laurent59bd0da2011-08-01 09:52:20 -07001195 for (size_t i = 0; i < mRecordThreads.size(); i++) {
1196 sp<RecordThread> thread = mRecordThreads.valueAt(i);
Eric Laurentf1c04f92012-08-28 14:26:53 -07001197 audio_devices_t device = thread->inDevice();
Glenn Kasten510a3d62012-07-16 14:24:34 -07001198 bool suspend = audio_is_bluetooth_sco_device(device) && btNrecIsOff;
1199 // collect all of the thread's session IDs
Glenn Kastend848eb42016-03-08 13:42:11 -08001200 KeyedVector<audio_session_t, bool> ids = thread->sessionIds();
Glenn Kasten510a3d62012-07-16 14:24:34 -07001201 // suspend effects associated with those session IDs
1202 for (size_t j = 0; j < ids.size(); ++j) {
Glenn Kastend848eb42016-03-08 13:42:11 -08001203 audio_session_t sessionId = ids.keyAt(j);
Eric Laurent59bd0da2011-08-01 09:52:20 -07001204 thread->setEffectSuspended(FX_IID_AEC,
1205 suspend,
Glenn Kasten510a3d62012-07-16 14:24:34 -07001206 sessionId);
Eric Laurent59bd0da2011-08-01 09:52:20 -07001207 thread->setEffectSuspended(FX_IID_NS,
1208 suspend,
Glenn Kasten510a3d62012-07-16 14:24:34 -07001209 sessionId);
Eric Laurent59bd0da2011-08-01 09:52:20 -07001210 }
1211 }
Eric Laurentbee53372011-08-29 12:42:48 -07001212 mBtNrecIsOff = btNrecIsOff;
Eric Laurent59bd0da2011-08-01 09:52:20 -07001213 }
1214 }
Glenn Kasten28ed2f92012-06-07 10:17:54 -07001215 String8 screenState;
1216 if (param.get(String8(AudioParameter::keyScreenState), screenState) == NO_ERROR) {
Mikhail Naganov00260b52016-10-13 12:54:24 -07001217 bool isOff = (screenState == AudioParameter::valueOff);
Eric Laurent81784c32012-11-19 14:55:58 -08001218 if (isOff != (AudioFlinger::mScreenState & 1)) {
1219 AudioFlinger::mScreenState = ((AudioFlinger::mScreenState & ~1) + 2) | isOff;
Glenn Kasten28ed2f92012-06-07 10:17:54 -07001220 }
1221 }
Dima Zavin799a70e2011-04-18 16:57:27 -07001222 return final_result;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001223 }
1224
1225 // hold a strong ref on thread in case closeOutput() or closeInput() is called
1226 // and the thread is exited once the lock is released
1227 sp<ThreadBase> thread;
1228 {
1229 Mutex::Autolock _l(mLock);
1230 thread = checkPlaybackThread_l(ioHandle);
Glenn Kastend5903ec2012-03-18 10:33:27 -07001231 if (thread == 0) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001232 thread = checkRecordThread_l(ioHandle);
Eric Laurent6acd1d42017-01-04 14:23:29 -08001233 if (thread == 0) {
1234 thread = checkMmapThread_l(ioHandle);
1235 }
Glenn Kasten7fc9a6f2012-01-10 10:46:34 -08001236 } else if (thread == primaryPlaybackThread_l()) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07001237 // indicate output device change to all input threads for pre processing
1238 AudioParameter param = AudioParameter(keyValuePairs);
1239 int value;
Eric Laurent89d94e72012-03-16 20:37:59 -07001240 if ((param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) &&
1241 (value != 0)) {
Eric Laurent054d9d32015-04-24 08:48:48 -07001242 broacastParametersToRecordThreads_l(keyValuePairs);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07001243 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001244 }
1245 }
Glenn Kasten7378ca52012-01-20 13:44:40 -08001246 if (thread != 0) {
1247 return thread->setParameters(keyValuePairs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001248 }
1249 return BAD_VALUE;
1250}
1251
Glenn Kasten72ef00d2012-01-17 11:09:42 -08001252String8 AudioFlinger::getParameters(audio_io_handle_t ioHandle, const String8& keys) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07001253{
Glenn Kasten827e5f12012-11-02 10:00:06 -07001254 ALOGVV("getParameters() io %d, keys %s, calling pid %d",
1255 ioHandle, keys.string(), IPCThreadState::self()->getCallingPid());
Mathias Agopian65ab4712010-07-14 17:59:35 -07001256
Eric Laurenta4c5a552012-03-29 10:12:40 -07001257 Mutex::Autolock _l(mLock);
1258
Glenn Kasten142f5192014-03-25 17:44:59 -07001259 if (ioHandle == AUDIO_IO_HANDLE_NONE) {
Dima Zavinfce7a472011-04-19 22:30:36 -07001260 String8 out_s8;
1261
Dima Zavin799a70e2011-04-18 16:57:27 -07001262 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001263 String8 s;
1264 status_t result;
Glenn Kasten8abf44d2012-02-02 14:16:03 -08001265 {
1266 AutoMutex lock(mHardwareLock);
1267 mHardwareStatus = AUDIO_HW_GET_PARAMETER;
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001268 sp<DeviceHalInterface> dev = mAudioHwDevs.valueAt(i)->hwDevice();
1269 result = dev->getParameters(keys, &s);
Glenn Kasten8abf44d2012-02-02 14:16:03 -08001270 mHardwareStatus = AUDIO_HW_IDLE;
1271 }
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001272 if (result == OK) out_s8 += s;
Dima Zavin799a70e2011-04-18 16:57:27 -07001273 }
Dima Zavinfce7a472011-04-19 22:30:36 -07001274 return out_s8;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001275 }
1276
Eric Laurent6acd1d42017-01-04 14:23:29 -08001277 ThreadBase *thread = (ThreadBase *)checkPlaybackThread_l(ioHandle);
1278 if (thread == NULL) {
1279 thread = (ThreadBase *)checkRecordThread_l(ioHandle);
1280 if (thread == NULL) {
1281 thread = (ThreadBase *)checkMmapThread_l(ioHandle);
1282 if (thread == NULL) {
1283 String8("");
1284 }
1285 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001286 }
Eric Laurent6acd1d42017-01-04 14:23:29 -08001287 return thread->getParameters(keys);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001288}
1289
Glenn Kastendd8104c2012-07-02 12:42:44 -07001290size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, audio_format_t format,
1291 audio_channel_mask_t channelMask) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07001292{
Eric Laurenta1884f92011-08-23 08:25:03 -07001293 status_t ret = initCheck();
1294 if (ret != NO_ERROR) {
1295 return 0;
1296 }
Eric Laurentcdf924a2016-02-04 15:57:56 -08001297 if ((sampleRate == 0) ||
Phil Burkfdb3c072016-02-09 10:47:02 -08001298 !audio_is_valid_format(format) || !audio_has_proportional_frames(format) ||
Eric Laurentcdf924a2016-02-04 15:57:56 -08001299 !audio_is_input_channel(channelMask)) {
Andy Hung6770c6f2015-04-07 13:43:36 -07001300 return 0;
1301 }
Eric Laurenta1884f92011-08-23 08:25:03 -07001302
Glenn Kasten2b213bc2012-02-02 14:05:20 -08001303 AutoMutex lock(mHardwareLock);
1304 mHardwareStatus = AUDIO_HW_GET_INPUT_BUFFER_SIZE;
Andy Hung6770c6f2015-04-07 13:43:36 -07001305 audio_config_t config, proposed;
1306 memset(&proposed, 0, sizeof(proposed));
1307 proposed.sample_rate = sampleRate;
1308 proposed.channel_mask = channelMask;
1309 proposed.format = format;
Richard Fitzgeraldad3af332013-03-25 16:54:37 +00001310
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001311 sp<DeviceHalInterface> dev = mPrimaryHardwareDev->hwDevice();
Andy Hung6770c6f2015-04-07 13:43:36 -07001312 size_t frames;
1313 for (;;) {
1314 // Note: config is currently a const parameter for get_input_buffer_size()
1315 // but we use a copy from proposed in case config changes from the call.
1316 config = proposed;
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001317 status_t result = dev->getInputBufferSize(&config, &frames);
1318 if (result == OK && frames != 0) {
Andy Hung6770c6f2015-04-07 13:43:36 -07001319 break; // hal success, config is the result
1320 }
1321 // change one parameter of the configuration each iteration to a more "common" value
1322 // to see if the device will support it.
1323 if (proposed.format != AUDIO_FORMAT_PCM_16_BIT) {
1324 proposed.format = AUDIO_FORMAT_PCM_16_BIT;
1325 } else if (proposed.sample_rate != 44100) { // 44.1 is claimed as must in CDD as well as
1326 proposed.sample_rate = 44100; // legacy AudioRecord.java. TODO: Query hw?
1327 } else {
1328 ALOGW("getInputBufferSize failed with minimum buffer size sampleRate %u, "
1329 "format %#x, channelMask 0x%X",
1330 sampleRate, format, channelMask);
1331 break; // retries failed, break out of loop with frames == 0.
1332 }
1333 }
Glenn Kasten2b213bc2012-02-02 14:05:20 -08001334 mHardwareStatus = AUDIO_HW_IDLE;
Andy Hung6770c6f2015-04-07 13:43:36 -07001335 if (frames > 0 && config.sample_rate != sampleRate) {
1336 frames = destinationFramesPossible(frames, sampleRate, config.sample_rate);
1337 }
1338 return frames; // may be converted to bytes at the Java level.
Mathias Agopian65ab4712010-07-14 17:59:35 -07001339}
1340
Glenn Kasten5f972c02014-01-13 09:59:31 -08001341uint32_t AudioFlinger::getInputFramesLost(audio_io_handle_t ioHandle) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07001342{
Mathias Agopian65ab4712010-07-14 17:59:35 -07001343 Mutex::Autolock _l(mLock);
1344
1345 RecordThread *recordThread = checkRecordThread_l(ioHandle);
1346 if (recordThread != NULL) {
1347 return recordThread->getInputFramesLost();
1348 }
1349 return 0;
1350}
1351
1352status_t AudioFlinger::setVoiceVolume(float value)
1353{
Eric Laurenta1884f92011-08-23 08:25:03 -07001354 status_t ret = initCheck();
1355 if (ret != NO_ERROR) {
1356 return ret;
1357 }
1358
Mathias Agopian65ab4712010-07-14 17:59:35 -07001359 // check calling permissions
1360 if (!settingsAllowed()) {
1361 return PERMISSION_DENIED;
1362 }
1363
1364 AutoMutex lock(mHardwareLock);
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001365 sp<DeviceHalInterface> dev = mPrimaryHardwareDev->hwDevice();
Glenn Kasten8abf44d2012-02-02 14:16:03 -08001366 mHardwareStatus = AUDIO_HW_SET_VOICE_VOLUME;
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001367 ret = dev->setVoiceVolume(value);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001368 mHardwareStatus = AUDIO_HW_IDLE;
1369
1370 return ret;
1371}
1372
Kévin PETIT377b2ec2014-02-03 12:35:36 +00001373status_t AudioFlinger::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames,
Glenn Kasten72ef00d2012-01-17 11:09:42 -08001374 audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07001375{
Mathias Agopian65ab4712010-07-14 17:59:35 -07001376 Mutex::Autolock _l(mLock);
1377
1378 PlaybackThread *playbackThread = checkPlaybackThread_l(output);
1379 if (playbackThread != NULL) {
1380 return playbackThread->getRenderPosition(halFrames, dspFrames);
1381 }
1382
1383 return BAD_VALUE;
1384}
1385
1386void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
1387{
Mathias Agopian65ab4712010-07-14 17:59:35 -07001388 Mutex::Autolock _l(mLock);
Eric Laurent44622db2014-08-01 19:00:33 -07001389 if (client == 0) {
1390 return;
1391 }
Eric Laurent7c1ec5f2015-07-09 14:52:47 -07001392 pid_t pid = IPCThreadState::self()->getCallingPid();
Eric Laurent021cf962014-05-13 10:18:14 -07001393 {
1394 Mutex::Autolock _cl(mClientLock);
Eric Laurent021cf962014-05-13 10:18:14 -07001395 if (mNotificationClients.indexOfKey(pid) < 0) {
1396 sp<NotificationClient> notificationClient = new NotificationClient(this,
1397 client,
1398 pid);
1399 ALOGV("registerClient() client %p, pid %d", notificationClient.get(), pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001400
Eric Laurent021cf962014-05-13 10:18:14 -07001401 mNotificationClients.add(pid, notificationClient);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001402
Marco Nelissen06b46062014-11-14 07:58:25 -08001403 sp<IBinder> binder = IInterface::asBinder(client);
Eric Laurent021cf962014-05-13 10:18:14 -07001404 binder->linkToDeath(notificationClient);
Eric Laurent021cf962014-05-13 10:18:14 -07001405 }
1406 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001407
Eric Laurent021cf962014-05-13 10:18:14 -07001408 // mClientLock should not be held here because ThreadBase::sendIoConfigEvent() will lock the
Eric Laurentfe1a94e2014-05-26 16:03:08 -07001409 // ThreadBase mutex and the locking order is ThreadBase::mLock then AudioFlinger::mClientLock.
Eric Laurent7c1ec5f2015-07-09 14:52:47 -07001410 // the config change is always sent from playback or record threads to avoid deadlock
1411 // with AudioSystem::gLock
1412 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
1413 mPlaybackThreads.valueAt(i)->sendIoConfigEvent(AUDIO_OUTPUT_OPENED, pid);
1414 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001415
Eric Laurent7c1ec5f2015-07-09 14:52:47 -07001416 for (size_t i = 0; i < mRecordThreads.size(); i++) {
1417 mRecordThreads.valueAt(i)->sendIoConfigEvent(AUDIO_INPUT_OPENED, pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001418 }
1419}
1420
1421void AudioFlinger::removeNotificationClient(pid_t pid)
1422{
1423 Mutex::Autolock _l(mLock);
Eric Laurent021cf962014-05-13 10:18:14 -07001424 {
1425 Mutex::Autolock _cl(mClientLock);
1426 mNotificationClients.removeItem(pid);
1427 }
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001428
Steve Block3856b092011-10-20 11:56:00 +01001429 ALOGV("%d died, releasing its sessions", pid);
Glenn Kasten8d6a2442012-02-08 14:04:28 -08001430 size_t num = mAudioSessionRefs.size();
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001431 bool removed = false;
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001432 for (size_t i = 0; i < num; ) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001433 AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001434 ALOGV(" pid %d @ %zu", ref->mPid, i);
Glenn Kasten012ca6b2012-03-06 11:22:01 -08001435 if (ref->mPid == pid) {
1436 ALOGV(" removing entry for pid %d session %d", pid, ref->mSessionid);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001437 mAudioSessionRefs.removeAt(i);
1438 delete ref;
1439 removed = true;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001440 num--;
Glenn Kasten8d6a2442012-02-08 14:04:28 -08001441 } else {
1442 i++;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001443 }
1444 }
1445 if (removed) {
1446 purgeStaleEffects_l();
1447 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001448}
1449
Eric Laurent73e26b62015-04-27 16:55:58 -07001450void AudioFlinger::ioConfigChanged(audio_io_config_event event,
Eric Laurent7c1ec5f2015-07-09 14:52:47 -07001451 const sp<AudioIoDescriptor>& ioDesc,
1452 pid_t pid)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001453{
Eric Laurent021cf962014-05-13 10:18:14 -07001454 Mutex::Autolock _l(mClientLock);
1455 size_t size = mNotificationClients.size();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001456 for (size_t i = 0; i < size; i++) {
Eric Laurent7c1ec5f2015-07-09 14:52:47 -07001457 if ((pid == 0) || (mNotificationClients.keyAt(i) == pid)) {
1458 mNotificationClients.valueAt(i)->audioFlingerClient()->ioConfigChanged(event, ioDesc);
1459 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001460 }
1461}
1462
Eric Laurent021cf962014-05-13 10:18:14 -07001463// removeClient_l() must be called with AudioFlinger::mClientLock held
Mathias Agopian65ab4712010-07-14 17:59:35 -07001464void AudioFlinger::removeClient_l(pid_t pid)
1465{
Glenn Kasten827e5f12012-11-02 10:00:06 -07001466 ALOGV("removeClient_l() pid %d, calling pid %d", pid,
Glenn Kasten85ab62c2012-11-01 11:11:38 -07001467 IPCThreadState::self()->getCallingPid());
Mathias Agopian65ab4712010-07-14 17:59:35 -07001468 mClients.removeItem(pid);
1469}
1470
Eric Laurent717e1282012-06-29 16:36:52 -07001471// getEffectThread_l() must be called with AudioFlinger::mLock held
Glenn Kastend848eb42016-03-08 13:42:11 -08001472sp<AudioFlinger::PlaybackThread> AudioFlinger::getEffectThread_l(audio_session_t sessionId,
1473 int EffectId)
Eric Laurent717e1282012-06-29 16:36:52 -07001474{
1475 sp<PlaybackThread> thread;
1476
1477 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
1478 if (mPlaybackThreads.valueAt(i)->getEffect(sessionId, EffectId) != 0) {
1479 ALOG_ASSERT(thread == 0);
1480 thread = mPlaybackThreads.valueAt(i);
1481 }
1482 }
1483
1484 return thread;
1485}
Mathias Agopian65ab4712010-07-14 17:59:35 -07001486
Mathias Agopian65ab4712010-07-14 17:59:35 -07001487
Mathias Agopian65ab4712010-07-14 17:59:35 -07001488
1489// ----------------------------------------------------------------------------
1490
1491AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
1492 : RefBase(),
1493 mAudioFlinger(audioFlinger),
Glenn Kastend79072e2016-01-06 08:41:20 -08001494 mPid(pid)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001495{
Sumit Bhattacharyacd64e0e2016-02-11 01:37:20 +05301496 size_t heapSize = property_get_int32("ro.af.client_heap_size_kbyte", 0);
1497 heapSize *= 1024;
1498 if (!heapSize) {
1499 heapSize = kClientSharedHeapSizeBytes;
1500 // Increase heap size on non low ram devices to limit risk of reconnection failure for
1501 // invalidated tracks
1502 if (!audioFlinger->isLowRamDevice()) {
1503 heapSize *= kClientSharedHeapSizeMultiplier;
1504 }
Eric Laurentda73b6c2015-08-20 16:18:53 -07001505 }
1506 mMemoryDealer = new MemoryDealer(heapSize, "AudioFlinger::Client");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001507}
1508
Eric Laurent021cf962014-05-13 10:18:14 -07001509// Client destructor must be called with AudioFlinger::mClientLock held
Mathias Agopian65ab4712010-07-14 17:59:35 -07001510AudioFlinger::Client::~Client()
1511{
1512 mAudioFlinger->removeClient_l(mPid);
1513}
1514
Glenn Kasten435dbe62012-01-30 10:15:48 -08001515sp<MemoryDealer> AudioFlinger::Client::heap() const
Mathias Agopian65ab4712010-07-14 17:59:35 -07001516{
1517 return mMemoryDealer;
1518}
1519
1520// ----------------------------------------------------------------------------
1521
1522AudioFlinger::NotificationClient::NotificationClient(const sp<AudioFlinger>& audioFlinger,
1523 const sp<IAudioFlingerClient>& client,
1524 pid_t pid)
Glenn Kasten84afa3b2012-01-25 15:28:08 -08001525 : mAudioFlinger(audioFlinger), mPid(pid), mAudioFlingerClient(client)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001526{
1527}
1528
1529AudioFlinger::NotificationClient::~NotificationClient()
1530{
Mathias Agopian65ab4712010-07-14 17:59:35 -07001531}
1532
Glenn Kasten0f11b512014-01-31 16:18:54 -08001533void AudioFlinger::NotificationClient::binderDied(const wp<IBinder>& who __unused)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001534{
1535 sp<NotificationClient> keep(this);
Glenn Kastena1117922012-01-26 10:53:32 -08001536 mAudioFlinger->removeNotificationClient(mPid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001537}
1538
Nicolas Rouletdcdfaec2017-02-14 10:18:39 -08001539// ----------------------------------------------------------------------------
1540AudioFlinger::MediaLogNotifier::MediaLogNotifier()
1541 : mPendingRequests(false) {}
1542
1543
1544void AudioFlinger::MediaLogNotifier::requestMerge() {
1545 AutoMutex _l(mMutex);
1546 mPendingRequests = true;
1547 mCond.signal();
1548}
1549
1550bool AudioFlinger::MediaLogNotifier::threadLoop() {
Glenn Kasten04b96fc2017-04-10 14:58:47 -07001551 // Should already have been checked, but just in case
1552 if (sMediaLogService == 0) {
1553 return false;
1554 }
Nicolas Rouletdcdfaec2017-02-14 10:18:39 -08001555 // Wait until there are pending requests
1556 {
1557 AutoMutex _l(mMutex);
1558 mPendingRequests = false; // to ignore past requests
1559 while (!mPendingRequests) {
1560 mCond.wait(mMutex);
1561 // TODO may also need an exitPending check
1562 }
1563 mPendingRequests = false;
1564 }
1565 // Execute the actual MediaLogService binder call and ignore extra requests for a while
Glenn Kasten04b96fc2017-04-10 14:58:47 -07001566 sMediaLogService->requestMergeWakeup();
Nicolas Rouletdcdfaec2017-02-14 10:18:39 -08001567 usleep(kPostTriggerSleepPeriod);
1568 return true;
1569}
1570
1571void AudioFlinger::requestLogMerge() {
1572 mMediaLogNotifier->requestMerge();
1573}
Mathias Agopian65ab4712010-07-14 17:59:35 -07001574
1575// ----------------------------------------------------------------------------
1576
1577sp<IAudioRecord> AudioFlinger::openRecord(
Glenn Kasten72ef00d2012-01-17 11:09:42 -08001578 audio_io_handle_t input,
Mathias Agopian65ab4712010-07-14 17:59:35 -07001579 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08001580 audio_format_t format,
Glenn Kasten254af182012-07-03 14:59:05 -07001581 audio_channel_mask_t channelMask,
Svet Ganovbe71aa22015-04-28 12:06:02 -07001582 const String16& opPackageName,
Glenn Kasten74935e42013-12-19 08:56:45 -08001583 size_t *frameCount,
Eric Laurent05067782016-06-01 18:27:28 -07001584 audio_input_flags_t *flags,
Haynes Mathew George9ea77cd2016-04-06 17:07:48 -07001585 pid_t pid,
Glenn Kasten1879fff2012-07-11 15:36:59 -07001586 pid_t tid,
Jean-Michel Trivi4cb66832015-05-01 18:34:17 -07001587 int clientUid,
Glenn Kastend848eb42016-03-08 13:42:11 -08001588 audio_session_t *sessionId,
Glenn Kasten7df8c0b2014-07-03 12:23:29 -07001589 size_t *notificationFrames,
Glenn Kastend776ac62014-05-07 09:16:09 -07001590 sp<IMemory>& cblk,
1591 sp<IMemory>& buffers,
Eric Laurent20b9ef02016-12-05 11:03:16 -08001592 status_t *status,
1593 audio_port_handle_t portId)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001594{
1595 sp<RecordThread::RecordTrack> recordTrack;
1596 sp<RecordHandle> recordHandle;
1597 sp<Client> client;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001598 status_t lStatus;
Glenn Kastend848eb42016-03-08 13:42:11 -08001599 audio_session_t lSessionId;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001600
Glenn Kastend776ac62014-05-07 09:16:09 -07001601 cblk.clear();
1602 buffers.clear();
1603
Haynes Mathew George9ea77cd2016-04-06 17:07:48 -07001604 bool updatePid = (pid == -1);
Marco Nelissendcb346b2015-09-09 10:47:29 -07001605 const uid_t callingUid = IPCThreadState::self()->getCallingUid();
1606 if (!isTrustedCallingUid(callingUid)) {
Andy Hung879db192016-01-05 16:00:34 -08001607 ALOGW_IF((uid_t)clientUid != callingUid,
Marco Nelissendcb346b2015-09-09 10:47:29 -07001608 "%s uid %d tried to pass itself off as %d", __FUNCTION__, callingUid, clientUid);
1609 clientUid = callingUid;
Haynes Mathew George9ea77cd2016-04-06 17:07:48 -07001610 updatePid = true;
1611 }
1612
1613 if (updatePid) {
1614 const pid_t callingPid = IPCThreadState::self()->getCallingPid();
1615 ALOGW_IF(pid != -1 && pid != callingPid,
1616 "%s uid %d pid %d tried to pass itself off as pid %d",
1617 __func__, callingUid, callingPid, pid);
1618 pid = callingPid;
Marco Nelissendcb346b2015-09-09 10:47:29 -07001619 }
1620
Mathias Agopian65ab4712010-07-14 17:59:35 -07001621 // check calling permissions
Marco Nelissendcb346b2015-09-09 10:47:29 -07001622 if (!recordingAllowed(opPackageName, tid, clientUid)) {
Glenn Kastene93cf2c2013-09-24 11:52:37 -07001623 ALOGE("openRecord() permission denied: recording not allowed");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001624 lStatus = PERMISSION_DENIED;
1625 goto Exit;
1626 }
1627
Glenn Kasten53b5d092014-02-05 10:00:23 -08001628 // further sample rate checks are performed by createRecordTrack_l()
1629 if (sampleRate == 0) {
1630 ALOGE("openRecord() invalid sample rate %u", sampleRate);
1631 lStatus = BAD_VALUE;
1632 goto Exit;
1633 }
1634
Andy Hung6770c6f2015-04-07 13:43:36 -07001635 // we don't yet support anything other than linear PCM
1636 if (!audio_is_valid_format(format) || !audio_is_linear_pcm(format)) {
Glenn Kastencac3daa2014-02-07 09:47:14 -08001637 ALOGE("openRecord() invalid format %#x", format);
Glenn Kasten291bb6d2013-07-16 17:23:39 -07001638 lStatus = BAD_VALUE;
1639 goto Exit;
1640 }
1641
Glenn Kasten53b5d092014-02-05 10:00:23 -08001642 // further channel mask checks are performed by createRecordTrack_l()
1643 if (!audio_is_input_channel(channelMask)) {
1644 ALOGE("openRecord() invalid channel mask %#x", channelMask);
1645 lStatus = BAD_VALUE;
1646 goto Exit;
1647 }
1648
Glenn Kasten05997e22014-03-13 15:08:33 -07001649 {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001650 Mutex::Autolock _l(mLock);
Glenn Kastene848bd92014-03-13 15:00:32 -07001651 RecordThread *thread = checkRecordThread_l(input);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001652 if (thread == NULL) {
Glenn Kastene93cf2c2013-09-24 11:52:37 -07001653 ALOGE("openRecord() checkRecordThread_l failed");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001654 lStatus = BAD_VALUE;
1655 goto Exit;
1656 }
1657
Eric Laurent021cf962014-05-13 10:18:14 -07001658 client = registerPid(pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001659
Glenn Kastenaea7ea02013-06-26 09:25:47 -07001660 if (sessionId != NULL && *sessionId != AUDIO_SESSION_ALLOCATE) {
Glenn Kasteneeecb982016-02-26 10:44:04 -08001661 if (audio_unique_id_get_use(*sessionId) != AUDIO_UNIQUE_ID_USE_SESSION) {
1662 lStatus = BAD_VALUE;
1663 goto Exit;
1664 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001665 lSessionId = *sessionId;
1666 } else {
Glenn Kasten570f6332014-03-13 15:01:06 -07001667 // if no audio session id is provided, create one here
Glenn Kastend848eb42016-03-08 13:42:11 -08001668 lSessionId = (audio_session_t) nextUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001669 if (sessionId != NULL) {
1670 *sessionId = lSessionId;
1671 }
1672 }
Eric Laurentaaa44472014-09-12 17:41:50 -07001673 ALOGV("openRecord() lSessionId: %d input %d", lSessionId, input);
Glenn Kasten570f6332014-03-13 15:01:06 -07001674
Glenn Kasten1879fff2012-07-11 15:36:59 -07001675 recordTrack = thread->createRecordTrack_l(client, sampleRate, format, channelMask,
Glenn Kasten7df8c0b2014-07-03 12:23:29 -07001676 frameCount, lSessionId, notificationFrames,
Eric Laurent20b9ef02016-12-05 11:03:16 -08001677 clientUid, flags, tid, &lStatus, portId);
Haynes Mathew George03e9e832013-12-13 15:40:13 -08001678 LOG_ALWAYS_FATAL_IF((lStatus == NO_ERROR) && (recordTrack == 0));
Eric Laurent1b928682014-10-02 19:41:47 -07001679
1680 if (lStatus == NO_ERROR) {
1681 // Check if one effect chain was awaiting for an AudioRecord to be created on this
1682 // session and move it to this thread.
Glenn Kastend848eb42016-03-08 13:42:11 -08001683 sp<EffectChain> chain = getOrphanEffectChain_l(lSessionId);
Eric Laurent1b928682014-10-02 19:41:47 -07001684 if (chain != 0) {
1685 Mutex::Autolock _l(thread->mLock);
1686 thread->addEffectChain_l(chain);
1687 }
1688 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001689 }
Glenn Kastene198c362013-08-13 09:13:36 -07001690
Eric Laurent7c7f10b2011-06-17 21:29:58 -07001691 if (lStatus != NO_ERROR) {
Glenn Kasten85ab62c2012-11-01 11:11:38 -07001692 // remove local strong reference to Client before deleting the RecordTrack so that the
Eric Laurent021cf962014-05-13 10:18:14 -07001693 // Client destructor is called by the TrackBase destructor with mClientLock held
Eric Laurentfe1a94e2014-05-26 16:03:08 -07001694 // Don't hold mClientLock when releasing the reference on the track as the
1695 // destructor will acquire it.
1696 {
1697 Mutex::Autolock _cl(mClientLock);
1698 client.clear();
1699 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001700 recordTrack.clear();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001701 goto Exit;
1702 }
1703
Glenn Kastend776ac62014-05-07 09:16:09 -07001704 cblk = recordTrack->getCblk();
1705 buffers = recordTrack->getBuffers();
1706
Glenn Kasten2fc14732013-08-05 14:58:14 -07001707 // return handle to client
Mathias Agopian65ab4712010-07-14 17:59:35 -07001708 recordHandle = new RecordHandle(recordTrack);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001709
1710Exit:
Glenn Kasten9156ef32013-08-06 15:39:08 -07001711 *status = lStatus;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001712 return recordHandle;
1713}
1714
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001715
1716
Mathias Agopian65ab4712010-07-14 17:59:35 -07001717// ----------------------------------------------------------------------------
1718
Eric Laurenta4c5a552012-03-29 10:12:40 -07001719audio_module_handle_t AudioFlinger::loadHwModule(const char *name)
1720{
Eric Laurent44622db2014-08-01 19:00:33 -07001721 if (name == NULL) {
Glenn Kastena13cde92016-03-28 15:26:02 -07001722 return AUDIO_MODULE_HANDLE_NONE;
Eric Laurent44622db2014-08-01 19:00:33 -07001723 }
Eric Laurenta4c5a552012-03-29 10:12:40 -07001724 if (!settingsAllowed()) {
Glenn Kastena13cde92016-03-28 15:26:02 -07001725 return AUDIO_MODULE_HANDLE_NONE;
Eric Laurenta4c5a552012-03-29 10:12:40 -07001726 }
1727 Mutex::Autolock _l(mLock);
1728 return loadHwModule_l(name);
1729}
1730
1731// loadHwModule_l() must be called with AudioFlinger::mLock held
1732audio_module_handle_t AudioFlinger::loadHwModule_l(const char *name)
1733{
1734 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
1735 if (strncmp(mAudioHwDevs.valueAt(i)->moduleName(), name, strlen(name)) == 0) {
1736 ALOGW("loadHwModule() module %s already loaded", name);
1737 return mAudioHwDevs.keyAt(i);
1738 }
1739 }
1740
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001741 sp<DeviceHalInterface> dev;
Eric Laurenta4c5a552012-03-29 10:12:40 -07001742
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001743 int rc = mDevicesFactoryHal->openDevice(name, &dev);
Eric Laurenta4c5a552012-03-29 10:12:40 -07001744 if (rc) {
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001745 ALOGE("loadHwModule() error %d loading module %s", rc, name);
Glenn Kastena13cde92016-03-28 15:26:02 -07001746 return AUDIO_MODULE_HANDLE_NONE;
Eric Laurenta4c5a552012-03-29 10:12:40 -07001747 }
1748
1749 mHardwareStatus = AUDIO_HW_INIT;
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001750 rc = dev->initCheck();
Eric Laurenta4c5a552012-03-29 10:12:40 -07001751 mHardwareStatus = AUDIO_HW_IDLE;
1752 if (rc) {
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001753 ALOGE("loadHwModule() init check error %d for module %s", rc, name);
Glenn Kastena13cde92016-03-28 15:26:02 -07001754 return AUDIO_MODULE_HANDLE_NONE;
Eric Laurenta4c5a552012-03-29 10:12:40 -07001755 }
1756
John Grossmanee578c02012-07-23 17:05:46 -07001757 // Check and cache this HAL's level of support for master mute and master
1758 // volume. If this is the first HAL opened, and it supports the get
1759 // methods, use the initial values provided by the HAL as the current
1760 // master mute and volume settings.
1761
1762 AudioHwDevice::Flags flags = static_cast<AudioHwDevice::Flags>(0);
1763 { // scope for auto-lock pattern
Eric Laurenta4c5a552012-03-29 10:12:40 -07001764 AutoMutex lock(mHardwareLock);
John Grossmanee578c02012-07-23 17:05:46 -07001765
1766 if (0 == mAudioHwDevs.size()) {
1767 mHardwareStatus = AUDIO_HW_GET_MASTER_VOLUME;
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001768 float mv;
1769 if (OK == dev->getMasterVolume(&mv)) {
1770 mMasterVolume = mv;
John Grossmanee578c02012-07-23 17:05:46 -07001771 }
1772
1773 mHardwareStatus = AUDIO_HW_GET_MASTER_MUTE;
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001774 bool mm;
1775 if (OK == dev->getMasterMute(&mm)) {
1776 mMasterMute = mm;
John Grossmanee578c02012-07-23 17:05:46 -07001777 }
1778 }
1779
Eric Laurenta4c5a552012-03-29 10:12:40 -07001780 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001781 if (OK == dev->setMasterVolume(mMasterVolume)) {
John Grossmanee578c02012-07-23 17:05:46 -07001782 flags = static_cast<AudioHwDevice::Flags>(flags |
1783 AudioHwDevice::AHWD_CAN_SET_MASTER_VOLUME);
1784 }
1785
1786 mHardwareStatus = AUDIO_HW_SET_MASTER_MUTE;
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001787 if (OK == dev->setMasterMute(mMasterMute)) {
John Grossmanee578c02012-07-23 17:05:46 -07001788 flags = static_cast<AudioHwDevice::Flags>(flags |
1789 AudioHwDevice::AHWD_CAN_SET_MASTER_MUTE);
1790 }
1791
Eric Laurenta4c5a552012-03-29 10:12:40 -07001792 mHardwareStatus = AUDIO_HW_IDLE;
1793 }
1794
Glenn Kastena13cde92016-03-28 15:26:02 -07001795 audio_module_handle_t handle = (audio_module_handle_t) nextUniqueId(AUDIO_UNIQUE_ID_USE_MODULE);
Eric Laurent83b88082014-06-20 18:31:16 -07001796 mAudioHwDevs.add(handle, new AudioHwDevice(handle, name, dev, flags));
Eric Laurenta4c5a552012-03-29 10:12:40 -07001797
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001798 ALOGI("loadHwModule() Loaded %s audio interface, handle %d", name, handle);
Eric Laurenta4c5a552012-03-29 10:12:40 -07001799
1800 return handle;
1801
1802}
1803
Glenn Kastencc0f1cf2012-09-24 11:27:18 -07001804// ----------------------------------------------------------------------------
1805
Glenn Kasten3b16c762012-11-14 08:44:39 -08001806uint32_t AudioFlinger::getPrimaryOutputSamplingRate()
Glenn Kastencc0f1cf2012-09-24 11:27:18 -07001807{
1808 Mutex::Autolock _l(mLock);
Glenn Kastena7335632016-06-09 17:09:53 -07001809 PlaybackThread *thread = fastPlaybackThread_l();
Glenn Kastencc0f1cf2012-09-24 11:27:18 -07001810 return thread != NULL ? thread->sampleRate() : 0;
1811}
1812
Glenn Kastene33054e2012-11-14 12:54:39 -08001813size_t AudioFlinger::getPrimaryOutputFrameCount()
Glenn Kastencc0f1cf2012-09-24 11:27:18 -07001814{
1815 Mutex::Autolock _l(mLock);
Glenn Kastena7335632016-06-09 17:09:53 -07001816 PlaybackThread *thread = fastPlaybackThread_l();
Glenn Kastencc0f1cf2012-09-24 11:27:18 -07001817 return thread != NULL ? thread->frameCountHAL() : 0;
1818}
1819
1820// ----------------------------------------------------------------------------
1821
Glenn Kasten4182c4e2013-07-15 14:45:07 -07001822status_t AudioFlinger::setLowRamDevice(bool isLowRamDevice)
1823{
1824 uid_t uid = IPCThreadState::self()->getCallingUid();
1825 if (uid != AID_SYSTEM) {
1826 return PERMISSION_DENIED;
1827 }
1828 Mutex::Autolock _l(mLock);
1829 if (mIsDeviceTypeKnown) {
1830 return INVALID_OPERATION;
1831 }
1832 mIsLowRamDevice = isLowRamDevice;
1833 mIsDeviceTypeKnown = true;
1834 return NO_ERROR;
1835}
1836
Eric Laurent93c3d412014-08-01 14:48:35 -07001837audio_hw_sync_t AudioFlinger::getAudioHwSyncForSession(audio_session_t sessionId)
1838{
1839 Mutex::Autolock _l(mLock);
Eric Laurentfa90e842014-10-17 18:12:31 -07001840
1841 ssize_t index = mHwAvSyncIds.indexOfKey(sessionId);
1842 if (index >= 0) {
1843 ALOGV("getAudioHwSyncForSession found ID %d for session %d",
1844 mHwAvSyncIds.valueAt(index), sessionId);
1845 return mHwAvSyncIds.valueAt(index);
1846 }
1847
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001848 sp<DeviceHalInterface> dev = mPrimaryHardwareDev->hwDevice();
Eric Laurentfa90e842014-10-17 18:12:31 -07001849 if (dev == NULL) {
1850 return AUDIO_HW_SYNC_INVALID;
1851 }
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001852 String8 reply;
1853 AudioParameter param;
Mikhail Naganov00260b52016-10-13 12:54:24 -07001854 if (dev->getParameters(String8(AudioParameter::keyHwAvSync), &reply) == OK) {
Mikhail Naganove4f1f632016-08-31 11:35:10 -07001855 param = AudioParameter(reply);
1856 }
Eric Laurentfa90e842014-10-17 18:12:31 -07001857
1858 int value;
Mikhail Naganov00260b52016-10-13 12:54:24 -07001859 if (param.getInt(String8(AudioParameter::keyHwAvSync), value) != NO_ERROR) {
Eric Laurentfa90e842014-10-17 18:12:31 -07001860 ALOGW("getAudioHwSyncForSession error getting sync for session %d", sessionId);
1861 return AUDIO_HW_SYNC_INVALID;
1862 }
1863
1864 // allow only one session for a given HW A/V sync ID.
1865 for (size_t i = 0; i < mHwAvSyncIds.size(); i++) {
1866 if (mHwAvSyncIds.valueAt(i) == (audio_hw_sync_t)value) {
1867 ALOGV("getAudioHwSyncForSession removing ID %d for session %d",
1868 value, mHwAvSyncIds.keyAt(i));
1869 mHwAvSyncIds.removeItemsAt(i);
Eric Laurent93c3d412014-08-01 14:48:35 -07001870 break;
1871 }
1872 }
Eric Laurentfa90e842014-10-17 18:12:31 -07001873
1874 mHwAvSyncIds.add(sessionId, value);
1875
1876 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
1877 sp<PlaybackThread> thread = mPlaybackThreads.valueAt(i);
1878 uint32_t sessions = thread->hasAudioSession(sessionId);
Eric Laurent4c415062016-06-17 16:14:16 -07001879 if (sessions & ThreadBase::TRACK_SESSION) {
Eric Laurentfa90e842014-10-17 18:12:31 -07001880 AudioParameter param = AudioParameter();
Mikhail Naganov00260b52016-10-13 12:54:24 -07001881 param.addInt(String8(AudioParameter::keyStreamHwAvSync), value);
Eric Laurentfa90e842014-10-17 18:12:31 -07001882 thread->setParameters(param.toString());
1883 break;
1884 }
1885 }
1886
1887 ALOGV("getAudioHwSyncForSession adding ID %d for session %d", value, sessionId);
1888 return (audio_hw_sync_t)value;
Eric Laurent93c3d412014-08-01 14:48:35 -07001889}
1890
Eric Laurent72e3f392015-05-20 14:43:50 -07001891status_t AudioFlinger::systemReady()
1892{
1893 Mutex::Autolock _l(mLock);
1894 ALOGI("%s", __FUNCTION__);
1895 if (mSystemReady) {
1896 ALOGW("%s called twice", __FUNCTION__);
1897 return NO_ERROR;
1898 }
1899 mSystemReady = true;
1900 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
1901 ThreadBase *thread = (ThreadBase *)mPlaybackThreads.valueAt(i).get();
1902 thread->systemReady();
1903 }
1904 for (size_t i = 0; i < mRecordThreads.size(); i++) {
1905 ThreadBase *thread = (ThreadBase *)mRecordThreads.valueAt(i).get();
1906 thread->systemReady();
1907 }
1908 return NO_ERROR;
1909}
1910
Eric Laurentfa90e842014-10-17 18:12:31 -07001911// setAudioHwSyncForSession_l() must be called with AudioFlinger::mLock held
1912void AudioFlinger::setAudioHwSyncForSession_l(PlaybackThread *thread, audio_session_t sessionId)
1913{
1914 ssize_t index = mHwAvSyncIds.indexOfKey(sessionId);
1915 if (index >= 0) {
1916 audio_hw_sync_t syncId = mHwAvSyncIds.valueAt(index);
1917 ALOGV("setAudioHwSyncForSession_l found ID %d for session %d", syncId, sessionId);
1918 AudioParameter param = AudioParameter();
Mikhail Naganov00260b52016-10-13 12:54:24 -07001919 param.addInt(String8(AudioParameter::keyStreamHwAvSync), syncId);
Eric Laurentfa90e842014-10-17 18:12:31 -07001920 thread->setParameters(param.toString());
1921 }
1922}
1923
1924
Glenn Kasten4182c4e2013-07-15 14:45:07 -07001925// ----------------------------------------------------------------------------
1926
Eric Laurent83b88082014-06-20 18:31:16 -07001927
Eric Laurent6acd1d42017-01-04 14:23:29 -08001928sp<AudioFlinger::ThreadBase> AudioFlinger::openOutput_l(audio_module_handle_t module,
Eric Laurentcf2c0212014-07-25 16:20:43 -07001929 audio_io_handle_t *output,
1930 audio_config_t *config,
1931 audio_devices_t devices,
1932 const String8& address,
Eric Laurent83b88082014-06-20 18:31:16 -07001933 audio_output_flags_t flags)
1934{
Eric Laurentcf2c0212014-07-25 16:20:43 -07001935 AudioHwDevice *outHwDev = findSuitableHwDev_l(module, devices);
Eric Laurent83b88082014-06-20 18:31:16 -07001936 if (outHwDev == NULL) {
Eric Laurentcf2c0212014-07-25 16:20:43 -07001937 return 0;
Eric Laurent83b88082014-06-20 18:31:16 -07001938 }
1939
Eric Laurentcf2c0212014-07-25 16:20:43 -07001940 if (*output == AUDIO_IO_HANDLE_NONE) {
Glenn Kasteneeecb982016-02-26 10:44:04 -08001941 *output = nextUniqueId(AUDIO_UNIQUE_ID_USE_OUTPUT);
1942 } else {
1943 // Audio Policy does not currently request a specific output handle.
1944 // If this is ever needed, see openInput_l() for example code.
1945 ALOGE("openOutput_l requested output handle %d is not AUDIO_IO_HANDLE_NONE", *output);
1946 return 0;
Eric Laurentcf2c0212014-07-25 16:20:43 -07001947 }
Eric Laurent83b88082014-06-20 18:31:16 -07001948
1949 mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
1950
Eric Laurent83b88082014-06-20 18:31:16 -07001951 // FOR TESTING ONLY:
Andy Hung9a592762014-07-21 21:56:01 -07001952 // This if statement allows overriding the audio policy settings
1953 // and forcing a specific format or channel mask to the HAL/Sink device for testing.
1954 if (!(flags & (AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD | AUDIO_OUTPUT_FLAG_DIRECT))) {
1955 // Check only for Normal Mixing mode
1956 if (kEnableExtendedPrecision) {
1957 // Specify format (uncomment one below to choose)
1958 //config->format = AUDIO_FORMAT_PCM_FLOAT;
1959 //config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1960 //config->format = AUDIO_FORMAT_PCM_32_BIT;
1961 //config->format = AUDIO_FORMAT_PCM_8_24_BIT;
Eric Laurentcf2c0212014-07-25 16:20:43 -07001962 // ALOGV("openOutput_l() upgrading format to %#08x", config->format);
Andy Hung9a592762014-07-21 21:56:01 -07001963 }
1964 if (kEnableExtendedChannels) {
1965 // Specify channel mask (uncomment one below to choose)
1966 //config->channel_mask = audio_channel_out_mask_from_count(4); // for USB 4ch
1967 //config->channel_mask = audio_channel_mask_from_representation_and_bits(
1968 // AUDIO_CHANNEL_REPRESENTATION_INDEX, (1 << 4) - 1); // another 4ch example
1969 }
Eric Laurent83b88082014-06-20 18:31:16 -07001970 }
1971
Phil Burk062e67a2015-02-11 13:40:50 -08001972 AudioStreamOut *outputStream = NULL;
1973 status_t status = outHwDev->openOutputStream(
1974 &outputStream,
1975 *output,
1976 devices,
1977 flags,
1978 config,
1979 address.string());
Eric Laurent83b88082014-06-20 18:31:16 -07001980
1981 mHardwareStatus = AUDIO_HW_IDLE;
Eric Laurent83b88082014-06-20 18:31:16 -07001982
Phil Burk062e67a2015-02-11 13:40:50 -08001983 if (status == NO_ERROR) {
Eric Laurent6acd1d42017-01-04 14:23:29 -08001984 if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
1985 sp<MmapPlaybackThread> thread =
1986 new MmapPlaybackThread(this, *output, outHwDev, outputStream,
1987 devices, AUDIO_DEVICE_NONE, mSystemReady);
1988 mMmapThreads.add(*output, thread);
1989 ALOGV("openOutput_l() created mmap playback thread: ID %d thread %p",
1990 *output, thread.get());
1991 return thread;
Eric Laurent83b88082014-06-20 18:31:16 -07001992 } else {
Eric Laurent6acd1d42017-01-04 14:23:29 -08001993 sp<PlaybackThread> thread;
1994 if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
1995 thread = new OffloadThread(this, outputStream, *output, devices, mSystemReady);
1996 ALOGV("openOutput_l() created offload output: ID %d thread %p",
1997 *output, thread.get());
1998 } else if ((flags & AUDIO_OUTPUT_FLAG_DIRECT)
1999 || !isValidPcmSinkFormat(config->format)
2000 || !isValidPcmSinkChannelMask(config->channel_mask)) {
2001 thread = new DirectOutputThread(this, outputStream, *output, devices, mSystemReady);
2002 ALOGV("openOutput_l() created direct output: ID %d thread %p",
2003 *output, thread.get());
2004 } else {
2005 thread = new MixerThread(this, outputStream, *output, devices, mSystemReady);
2006 ALOGV("openOutput_l() created mixer output: ID %d thread %p",
2007 *output, thread.get());
2008 }
2009 mPlaybackThreads.add(*output, thread);
2010 return thread;
Eric Laurent83b88082014-06-20 18:31:16 -07002011 }
Eric Laurent83b88082014-06-20 18:31:16 -07002012 }
2013
2014 return 0;
2015}
2016
Eric Laurentcf2c0212014-07-25 16:20:43 -07002017status_t AudioFlinger::openOutput(audio_module_handle_t module,
2018 audio_io_handle_t *output,
2019 audio_config_t *config,
2020 audio_devices_t *devices,
2021 const String8& address,
2022 uint32_t *latencyMs,
2023 audio_output_flags_t flags)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002024{
Glenn Kastend3bb6452016-12-05 18:14:37 -08002025 ALOGI("openOutput() this %p, module %d Device %x, SamplingRate %d, Format %#08x, Channels %x, "
2026 "flags %x",
Eric Laurent6acd1d42017-01-04 14:23:29 -08002027 this, module,
Eric Laurentcf2c0212014-07-25 16:20:43 -07002028 (devices != NULL) ? *devices : 0,
2029 config->sample_rate,
2030 config->format,
2031 config->channel_mask,
Eric Laurenta4c5a552012-03-29 10:12:40 -07002032 flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002033
Yunlian Jiang32ba9862017-01-31 15:55:00 -08002034 if (devices == NULL || *devices == AUDIO_DEVICE_NONE) {
Eric Laurentcf2c0212014-07-25 16:20:43 -07002035 return BAD_VALUE;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002036 }
Dima Zavin799a70e2011-04-18 16:57:27 -07002037
Mathias Agopian65ab4712010-07-14 17:59:35 -07002038 Mutex::Autolock _l(mLock);
2039
Eric Laurent6acd1d42017-01-04 14:23:29 -08002040 sp<ThreadBase> thread = openOutput_l(module, output, config, *devices, address, flags);
Eric Laurent83b88082014-06-20 18:31:16 -07002041 if (thread != 0) {
Eric Laurent6acd1d42017-01-04 14:23:29 -08002042 if ((flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0) {
2043 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
2044 *latencyMs = playbackThread->latency();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002045
Eric Laurent6acd1d42017-01-04 14:23:29 -08002046 // notify client processes of the new output creation
2047 playbackThread->ioConfigChanged(AUDIO_OUTPUT_OPENED);
Eric Laurenta4c5a552012-03-29 10:12:40 -07002048
Eric Laurent6acd1d42017-01-04 14:23:29 -08002049 // the first primary output opened designates the primary hw device
2050 if ((mPrimaryHardwareDev == NULL) && (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
Glenn Kasten1bfe09a2017-02-21 13:05:56 -08002051 ALOGI("Using module %d as the primary audio interface", module);
Eric Laurent6acd1d42017-01-04 14:23:29 -08002052 mPrimaryHardwareDev = playbackThread->getOutput()->audioHwDev;
Eric Laurenta4c5a552012-03-29 10:12:40 -07002053
Eric Laurent6acd1d42017-01-04 14:23:29 -08002054 AutoMutex lock(mHardwareLock);
2055 mHardwareStatus = AUDIO_HW_SET_MODE;
2056 mPrimaryHardwareDev->hwDevice()->setMode(mMode);
2057 mHardwareStatus = AUDIO_HW_IDLE;
2058 }
2059 } else {
2060 MmapThread *mmapThread = (MmapThread *)thread.get();
2061 mmapThread->ioConfigChanged(AUDIO_OUTPUT_OPENED);
Eric Laurenta4c5a552012-03-29 10:12:40 -07002062 }
Eric Laurentcf2c0212014-07-25 16:20:43 -07002063 return NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002064 }
2065
Eric Laurentcf2c0212014-07-25 16:20:43 -07002066 return NO_INIT;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002067}
2068
Glenn Kasten72ef00d2012-01-17 11:09:42 -08002069audio_io_handle_t AudioFlinger::openDuplicateOutput(audio_io_handle_t output1,
2070 audio_io_handle_t output2)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002071{
2072 Mutex::Autolock _l(mLock);
2073 MixerThread *thread1 = checkMixerThread_l(output1);
2074 MixerThread *thread2 = checkMixerThread_l(output2);
2075
2076 if (thread1 == NULL || thread2 == NULL) {
Glenn Kasten85ab62c2012-11-01 11:11:38 -07002077 ALOGW("openDuplicateOutput() wrong output mixer type for output %d or %d", output1,
2078 output2);
Glenn Kasten142f5192014-03-25 17:44:59 -07002079 return AUDIO_IO_HANDLE_NONE;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002080 }
2081
Glenn Kasteneeecb982016-02-26 10:44:04 -08002082 audio_io_handle_t id = nextUniqueId(AUDIO_UNIQUE_ID_USE_OUTPUT);
Eric Laurent72e3f392015-05-20 14:43:50 -07002083 DuplicatingThread *thread = new DuplicatingThread(this, thread1, id, mSystemReady);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002084 thread->addOutputTrack(thread2);
2085 mPlaybackThreads.add(id, thread);
2086 // notify client processes of the new output creation
Eric Laurent73e26b62015-04-27 16:55:58 -07002087 thread->ioConfigChanged(AUDIO_OUTPUT_OPENED);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002088 return id;
2089}
2090
Glenn Kasten72ef00d2012-01-17 11:09:42 -08002091status_t AudioFlinger::closeOutput(audio_io_handle_t output)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002092{
Glenn Kastend96c5722012-04-25 13:44:49 -07002093 return closeOutput_nonvirtual(output);
2094}
2095
2096status_t AudioFlinger::closeOutput_nonvirtual(audio_io_handle_t output)
2097{
Mathias Agopian65ab4712010-07-14 17:59:35 -07002098 // keep strong reference on the playback thread so that
2099 // it is not destroyed while exit() is executed
Eric Laurent6acd1d42017-01-04 14:23:29 -08002100 sp<PlaybackThread> playbackThread;
2101 sp<MmapPlaybackThread> mmapThread;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002102 {
2103 Mutex::Autolock _l(mLock);
Eric Laurent6acd1d42017-01-04 14:23:29 -08002104 playbackThread = checkPlaybackThread_l(output);
2105 if (playbackThread != NULL) {
2106 ALOGV("closeOutput() %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002107
Eric Laurent6acd1d42017-01-04 14:23:29 -08002108 if (playbackThread->type() == ThreadBase::MIXER) {
2109 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
2110 if (mPlaybackThreads.valueAt(i)->isDuplicating()) {
2111 DuplicatingThread *dupThread =
2112 (DuplicatingThread *)mPlaybackThreads.valueAt(i).get();
2113 dupThread->removeOutputTrack((MixerThread *)playbackThread.get());
2114 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08002115 }
2116 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08002117
2118
Eric Laurent6acd1d42017-01-04 14:23:29 -08002119 mPlaybackThreads.removeItem(output);
2120 // save all effects to the default thread
2121 if (mPlaybackThreads.size()) {
2122 PlaybackThread *dstThread = checkPlaybackThread_l(mPlaybackThreads.keyAt(0));
2123 if (dstThread != NULL) {
Glenn Kastend3bb6452016-12-05 18:14:37 -08002124 // audioflinger lock is held so order of thread lock acquisition doesn't matter
Eric Laurent6acd1d42017-01-04 14:23:29 -08002125 Mutex::Autolock _dl(dstThread->mLock);
2126 Mutex::Autolock _sl(playbackThread->mLock);
2127 Vector< sp<EffectChain> > effectChains = playbackThread->getEffectChains_l();
2128 for (size_t i = 0; i < effectChains.size(); i ++) {
Glenn Kastend3bb6452016-12-05 18:14:37 -08002129 moveEffectChain_l(effectChains[i]->sessionId(), playbackThread.get(),
2130 dstThread, true);
Eric Laurent6acd1d42017-01-04 14:23:29 -08002131 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002132 }
2133 }
Eric Laurent6acd1d42017-01-04 14:23:29 -08002134 } else {
2135 mmapThread = (MmapPlaybackThread *)checkMmapThread_l(output);
2136 if (mmapThread == 0) {
2137 return BAD_VALUE;
2138 }
2139 mMmapThreads.removeItem(output);
Phil Burk7f6b40d2017-02-09 13:18:38 -08002140 ALOGD("closing mmapThread %p", mmapThread.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002141 }
Eric Laurent73e26b62015-04-27 16:55:58 -07002142 const sp<AudioIoDescriptor> ioDesc = new AudioIoDescriptor();
2143 ioDesc->mIoHandle = output;
2144 ioConfigChanged(AUDIO_OUTPUT_CLOSED, ioDesc);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002145 }
Glenn Kastenb28686f2012-01-06 08:39:38 -08002146 // The thread entity (active unit of execution) is no longer running here,
2147 // but the ThreadBase container still exists.
Mathias Agopian65ab4712010-07-14 17:59:35 -07002148
Eric Laurent6acd1d42017-01-04 14:23:29 -08002149 if (playbackThread != 0) {
2150 playbackThread->exit();
2151 if (!playbackThread->isDuplicating()) {
2152 closeOutputFinish(playbackThread);
2153 }
2154 } else if (mmapThread != 0) {
Phil Burk7f6b40d2017-02-09 13:18:38 -08002155 ALOGD("mmapThread exit()");
Eric Laurent6acd1d42017-01-04 14:23:29 -08002156 mmapThread->exit();
2157 AudioStreamOut *out = mmapThread->clearOutput();
2158 ALOG_ASSERT(out != NULL, "out shouldn't be NULL");
2159 // from now on thread->mOutput is NULL
2160 delete out;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002161 }
2162 return NO_ERROR;
2163}
2164
Chih-Hung Hsieh36d0ca12016-08-09 14:31:32 -07002165void AudioFlinger::closeOutputFinish(const sp<PlaybackThread>& thread)
Eric Laurent83b88082014-06-20 18:31:16 -07002166{
2167 AudioStreamOut *out = thread->clearOutput();
2168 ALOG_ASSERT(out != NULL, "out shouldn't be NULL");
2169 // from now on thread->mOutput is NULL
Eric Laurent83b88082014-06-20 18:31:16 -07002170 delete out;
2171}
2172
Chih-Hung Hsieh36d0ca12016-08-09 14:31:32 -07002173void AudioFlinger::closeOutputInternal_l(const sp<PlaybackThread>& thread)
Eric Laurent83b88082014-06-20 18:31:16 -07002174{
2175 mPlaybackThreads.removeItem(thread->mId);
2176 thread->exit();
2177 closeOutputFinish(thread);
2178}
2179
Glenn Kasten72ef00d2012-01-17 11:09:42 -08002180status_t AudioFlinger::suspendOutput(audio_io_handle_t output)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002181{
2182 Mutex::Autolock _l(mLock);
2183 PlaybackThread *thread = checkPlaybackThread_l(output);
2184
2185 if (thread == NULL) {
2186 return BAD_VALUE;
2187 }
2188
Steve Block3856b092011-10-20 11:56:00 +01002189 ALOGV("suspendOutput() %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002190 thread->suspend();
2191
2192 return NO_ERROR;
2193}
2194
Glenn Kasten72ef00d2012-01-17 11:09:42 -08002195status_t AudioFlinger::restoreOutput(audio_io_handle_t output)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002196{
2197 Mutex::Autolock _l(mLock);
2198 PlaybackThread *thread = checkPlaybackThread_l(output);
2199
2200 if (thread == NULL) {
2201 return BAD_VALUE;
2202 }
2203
Steve Block3856b092011-10-20 11:56:00 +01002204 ALOGV("restoreOutput() %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002205
2206 thread->restore();
2207
2208 return NO_ERROR;
2209}
2210
Eric Laurentcf2c0212014-07-25 16:20:43 -07002211status_t AudioFlinger::openInput(audio_module_handle_t module,
2212 audio_io_handle_t *input,
2213 audio_config_t *config,
Glenn Kastene7d66712015-03-05 13:46:52 -08002214 audio_devices_t *devices,
Eric Laurentcf2c0212014-07-25 16:20:43 -07002215 const String8& address,
2216 audio_source_t source,
Glenn Kastenec40d282014-07-15 15:31:26 -07002217 audio_input_flags_t flags)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002218{
Eric Laurent83b88082014-06-20 18:31:16 -07002219 Mutex::Autolock _l(mLock);
2220
Glenn Kastene7d66712015-03-05 13:46:52 -08002221 if (*devices == AUDIO_DEVICE_NONE) {
Eric Laurentcf2c0212014-07-25 16:20:43 -07002222 return BAD_VALUE;
Eric Laurent83b88082014-06-20 18:31:16 -07002223 }
2224
Eric Laurent6acd1d42017-01-04 14:23:29 -08002225 sp<ThreadBase> thread = openInput_l(module, input, config, *devices, address, source, flags);
Eric Laurent83b88082014-06-20 18:31:16 -07002226
2227 if (thread != 0) {
Eric Laurent83b88082014-06-20 18:31:16 -07002228 // notify client processes of the new input creation
Eric Laurent73e26b62015-04-27 16:55:58 -07002229 thread->ioConfigChanged(AUDIO_INPUT_OPENED);
Eric Laurentcf2c0212014-07-25 16:20:43 -07002230 return NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002231 }
Eric Laurentcf2c0212014-07-25 16:20:43 -07002232 return NO_INIT;
Eric Laurent83b88082014-06-20 18:31:16 -07002233}
Dima Zavin799a70e2011-04-18 16:57:27 -07002234
Eric Laurent6acd1d42017-01-04 14:23:29 -08002235sp<AudioFlinger::ThreadBase> AudioFlinger::openInput_l(audio_module_handle_t module,
Eric Laurentcf2c0212014-07-25 16:20:43 -07002236 audio_io_handle_t *input,
2237 audio_config_t *config,
Glenn Kastene7d66712015-03-05 13:46:52 -08002238 audio_devices_t devices,
Eric Laurentcf2c0212014-07-25 16:20:43 -07002239 const String8& address,
2240 audio_source_t source,
Eric Laurent83b88082014-06-20 18:31:16 -07002241 audio_input_flags_t flags)
2242{
Glenn Kastene7d66712015-03-05 13:46:52 -08002243 AudioHwDevice *inHwDev = findSuitableHwDev_l(module, devices);
Glenn Kasten6e2ebe92013-08-13 09:14:51 -07002244 if (inHwDev == NULL) {
Eric Laurentcf2c0212014-07-25 16:20:43 -07002245 *input = AUDIO_IO_HANDLE_NONE;
Dima Zavin799a70e2011-04-18 16:57:27 -07002246 return 0;
Glenn Kasten6e2ebe92013-08-13 09:14:51 -07002247 }
Dima Zavin799a70e2011-04-18 16:57:27 -07002248
Glenn Kasteneeecb982016-02-26 10:44:04 -08002249 // Audio Policy can request a specific handle for hardware hotword.
2250 // The goal here is not to re-open an already opened input.
2251 // It is to use a pre-assigned I/O handle.
Eric Laurentcf2c0212014-07-25 16:20:43 -07002252 if (*input == AUDIO_IO_HANDLE_NONE) {
Glenn Kasteneeecb982016-02-26 10:44:04 -08002253 *input = nextUniqueId(AUDIO_UNIQUE_ID_USE_INPUT);
2254 } else if (audio_unique_id_get_use(*input) != AUDIO_UNIQUE_ID_USE_INPUT) {
2255 ALOGE("openInput_l() requested input handle %d is invalid", *input);
2256 return 0;
2257 } else if (mRecordThreads.indexOfKey(*input) >= 0) {
2258 // This should not happen in a transient state with current design.
2259 ALOGE("openInput_l() requested input handle %d is already assigned", *input);
2260 return 0;
Eric Laurentcf2c0212014-07-25 16:20:43 -07002261 }
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07002262
Eric Laurentcf2c0212014-07-25 16:20:43 -07002263 audio_config_t halconfig = *config;
Mikhail Naganove4f1f632016-08-31 11:35:10 -07002264 sp<DeviceHalInterface> inHwHal = inHwDev->hwDevice();
Mikhail Naganov1dc98672016-08-18 17:50:29 -07002265 sp<StreamInHalInterface> inStream;
2266 status_t status = inHwHal->openInputStream(
Mikhail Naganove4f1f632016-08-31 11:35:10 -07002267 *input, devices, &halconfig, flags, address.string(), source, &inStream);
Mikhail Naganovf558e022016-11-14 17:45:17 -08002268 ALOGV("openInput_l() openInputStream returned input %p, devices %x, SamplingRate %d"
Jean-Michel Trivifd4c1482014-08-06 16:02:28 -07002269 ", Format %#x, Channels %x, flags %#x, status %d addr %s",
Mikhail Naganov1dc98672016-08-18 17:50:29 -07002270 inStream.get(),
Mikhail Naganovf558e022016-11-14 17:45:17 -08002271 devices,
Eric Laurentcf2c0212014-07-25 16:20:43 -07002272 halconfig.sample_rate,
2273 halconfig.format,
2274 halconfig.channel_mask,
Glenn Kastenec40d282014-07-15 15:31:26 -07002275 flags,
Jean-Michel Trivifd4c1482014-08-06 16:02:28 -07002276 status, address.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002277
Glenn Kasten85ab62c2012-11-01 11:11:38 -07002278 // If the input could not be opened with the requested parameters and we can handle the
Andy Hung6770c6f2015-04-07 13:43:36 -07002279 // conversion internally, try to open again with the proposed parameters.
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07002280 if (status == BAD_VALUE &&
Andy Hung6770c6f2015-04-07 13:43:36 -07002281 audio_is_linear_pcm(config->format) &&
2282 audio_is_linear_pcm(halconfig.format) &&
2283 (halconfig.sample_rate <= AUDIO_RESAMPLER_DOWN_RATIO_MAX * config->sample_rate) &&
vivek mehta75346662016-05-04 18:45:46 -07002284 (audio_channel_count_from_in_mask(halconfig.channel_mask) <= FCC_8) &&
2285 (audio_channel_count_from_in_mask(config->channel_mask) <= FCC_8)) {
Glenn Kasten85948432013-08-19 12:09:05 -07002286 // FIXME describe the change proposed by HAL (save old values so we can log them here)
Eric Laurentcf2c0212014-07-25 16:20:43 -07002287 ALOGV("openInput_l() reopening with proposed sampling rate and channel mask");
Mikhail Naganov1dc98672016-08-18 17:50:29 -07002288 inStream.clear();
2289 status = inHwHal->openInputStream(
Mikhail Naganove4f1f632016-08-31 11:35:10 -07002290 *input, devices, &halconfig, flags, address.string(), source, &inStream);
Glenn Kasten85948432013-08-19 12:09:05 -07002291 // FIXME log this new status; HAL should not propose any further changes
Mathias Agopian65ab4712010-07-14 17:59:35 -07002292 }
2293
Mikhail Naganov1dc98672016-08-18 17:50:29 -07002294 if (status == NO_ERROR && inStream != 0) {
Eric Laurent05067782016-06-01 18:27:28 -07002295 AudioStreamIn *inputStream = new AudioStreamIn(inHwDev, inStream, flags);
Eric Laurent6acd1d42017-01-04 14:23:29 -08002296 if ((flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0) {
2297 sp<MmapCaptureThread> thread =
2298 new MmapCaptureThread(this, *input,
2299 inHwDev, inputStream,
2300 primaryOutputDevice_l(), devices, mSystemReady);
2301 mMmapThreads.add(*input, thread);
Glenn Kastend3bb6452016-12-05 18:14:37 -08002302 ALOGV("openInput_l() created mmap capture thread: ID %d thread %p", *input,
2303 thread.get());
Eric Laurent6acd1d42017-01-04 14:23:29 -08002304 return thread;
2305 } else {
Glenn Kasten46909e72013-02-26 09:20:22 -08002306#ifdef TEE_SINK
Eric Laurent6acd1d42017-01-04 14:23:29 -08002307 // Try to re-use most recently used Pipe to archive a copy of input for dumpsys,
2308 // or (re-)create if current Pipe is idle and does not match the new format
2309 sp<NBAIO_Sink> teeSink;
2310 enum {
2311 TEE_SINK_NO, // don't copy input
2312 TEE_SINK_NEW, // copy input using a new pipe
2313 TEE_SINK_OLD, // copy input using an existing pipe
2314 } kind;
2315 NBAIO_Format format = Format_from_SR_C(halconfig.sample_rate,
2316 audio_channel_count_from_in_mask(halconfig.channel_mask), halconfig.format);
2317 if (!mTeeSinkInputEnabled) {
2318 kind = TEE_SINK_NO;
2319 } else if (!Format_isValid(format)) {
2320 kind = TEE_SINK_NO;
2321 } else if (mRecordTeeSink == 0) {
2322 kind = TEE_SINK_NEW;
2323 } else if (mRecordTeeSink->getStrongCount() != 1) {
2324 kind = TEE_SINK_NO;
2325 } else if (Format_isEqual(format, mRecordTeeSink->format())) {
2326 kind = TEE_SINK_OLD;
2327 } else {
2328 kind = TEE_SINK_NEW;
2329 }
2330 switch (kind) {
2331 case TEE_SINK_NEW: {
2332 Pipe *pipe = new Pipe(mTeeSinkInputFrames, format);
2333 size_t numCounterOffers = 0;
2334 const NBAIO_Format offers[1] = {format};
2335 ssize_t index = pipe->negotiate(offers, 1, NULL, numCounterOffers);
2336 ALOG_ASSERT(index == 0);
2337 PipeReader *pipeReader = new PipeReader(*pipe);
2338 numCounterOffers = 0;
2339 index = pipeReader->negotiate(offers, 1, NULL, numCounterOffers);
2340 ALOG_ASSERT(index == 0);
2341 mRecordTeeSink = pipe;
2342 mRecordTeeSource = pipeReader;
2343 teeSink = pipe;
2344 }
2345 break;
2346 case TEE_SINK_OLD:
2347 teeSink = mRecordTeeSink;
2348 break;
2349 case TEE_SINK_NO:
2350 default:
2351 break;
2352 }
Glenn Kasten46909e72013-02-26 09:20:22 -08002353#endif
Eric Laurent6acd1d42017-01-04 14:23:29 -08002354
2355 // Start record thread
2356 // RecordThread requires both input and output device indication to forward to audio
2357 // pre processing modules
2358 sp<RecordThread> thread = new RecordThread(this,
2359 inputStream,
2360 *input,
2361 primaryOutputDevice_l(),
2362 devices,
2363 mSystemReady
2364#ifdef TEE_SINK
2365 , teeSink
2366#endif
2367 );
2368 mRecordThreads.add(*input, thread);
2369 ALOGV("openInput_l() created record thread: ID %d thread %p", *input, thread.get());
2370 return thread;
2371 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002372 }
2373
Eric Laurentcf2c0212014-07-25 16:20:43 -07002374 *input = AUDIO_IO_HANDLE_NONE;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002375 return 0;
2376}
2377
Glenn Kasten72ef00d2012-01-17 11:09:42 -08002378status_t AudioFlinger::closeInput(audio_io_handle_t input)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002379{
Glenn Kastend96c5722012-04-25 13:44:49 -07002380 return closeInput_nonvirtual(input);
2381}
2382
2383status_t AudioFlinger::closeInput_nonvirtual(audio_io_handle_t input)
2384{
Mathias Agopian65ab4712010-07-14 17:59:35 -07002385 // keep strong reference on the record thread so that
2386 // it is not destroyed while exit() is executed
Eric Laurent6acd1d42017-01-04 14:23:29 -08002387 sp<RecordThread> recordThread;
2388 sp<MmapCaptureThread> mmapThread;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002389 {
2390 Mutex::Autolock _l(mLock);
Eric Laurent6acd1d42017-01-04 14:23:29 -08002391 recordThread = checkRecordThread_l(input);
2392 if (recordThread != 0) {
2393 ALOGV("closeInput() %d", input);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002394
Eric Laurent6acd1d42017-01-04 14:23:29 -08002395 // If we still have effect chains, it means that a client still holds a handle
2396 // on at least one effect. We must either move the chain to an existing thread with the
2397 // same session ID or put it aside in case a new record thread is opened for a
2398 // new capture on the same session
2399 sp<EffectChain> chain;
2400 {
2401 Mutex::Autolock _sl(recordThread->mLock);
2402 Vector< sp<EffectChain> > effectChains = recordThread->getEffectChains_l();
2403 // Note: maximum one chain per record thread
2404 if (effectChains.size() != 0) {
2405 chain = effectChains[0];
Eric Laurent1b928682014-10-02 19:41:47 -07002406 }
2407 }
Eric Laurent6acd1d42017-01-04 14:23:29 -08002408 if (chain != 0) {
Glenn Kastend3bb6452016-12-05 18:14:37 -08002409 // first check if a record thread is already opened with a client on same session.
Eric Laurent6acd1d42017-01-04 14:23:29 -08002410 // This should only happen in case of overlap between one thread tear down and the
2411 // creation of its replacement
2412 size_t i;
2413 for (i = 0; i < mRecordThreads.size(); i++) {
2414 sp<RecordThread> t = mRecordThreads.valueAt(i);
2415 if (t == recordThread) {
2416 continue;
2417 }
2418 if (t->hasAudioSession(chain->sessionId()) != 0) {
2419 Mutex::Autolock _l(t->mLock);
2420 ALOGV("closeInput() found thread %d for effect session %d",
2421 t->id(), chain->sessionId());
2422 t->addEffectChain_l(chain);
2423 break;
2424 }
2425 }
Glenn Kastend3bb6452016-12-05 18:14:37 -08002426 // put the chain aside if we could not find a record thread with the same session id
Eric Laurent6acd1d42017-01-04 14:23:29 -08002427 if (i == mRecordThreads.size()) {
2428 putOrphanEffectChain_l(chain);
2429 }
Eric Laurentaaa44472014-09-12 17:41:50 -07002430 }
Eric Laurent6acd1d42017-01-04 14:23:29 -08002431 mRecordThreads.removeItem(input);
2432 } else {
2433 mmapThread = (MmapCaptureThread *)checkMmapThread_l(input);
2434 if (mmapThread == 0) {
2435 return BAD_VALUE;
2436 }
2437 mMmapThreads.removeItem(input);
Eric Laurentaaa44472014-09-12 17:41:50 -07002438 }
Eric Laurent73e26b62015-04-27 16:55:58 -07002439 const sp<AudioIoDescriptor> ioDesc = new AudioIoDescriptor();
2440 ioDesc->mIoHandle = input;
2441 ioConfigChanged(AUDIO_INPUT_CLOSED, ioDesc);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002442 }
Eric Laurent83b88082014-06-20 18:31:16 -07002443 // FIXME: calling thread->exit() without mLock held should not be needed anymore now that
2444 // we have a different lock for notification client
Eric Laurent6acd1d42017-01-04 14:23:29 -08002445 if (recordThread != 0) {
2446 closeInputFinish(recordThread);
2447 } else if (mmapThread != 0) {
2448 mmapThread->exit();
2449 AudioStreamIn *in = mmapThread->clearInput();
2450 ALOG_ASSERT(in != NULL, "in shouldn't be NULL");
2451 // from now on thread->mInput is NULL
2452 delete in;
2453 }
Eric Laurent83b88082014-06-20 18:31:16 -07002454 return NO_ERROR;
2455}
Mathias Agopian65ab4712010-07-14 17:59:35 -07002456
Chih-Hung Hsieh36d0ca12016-08-09 14:31:32 -07002457void AudioFlinger::closeInputFinish(const sp<RecordThread>& thread)
Eric Laurent83b88082014-06-20 18:31:16 -07002458{
2459 thread->exit();
Eric Laurentb8ba0a92011-08-07 16:32:26 -07002460 AudioStreamIn *in = thread->clearInput();
Glenn Kasten5798d4e2012-03-08 12:18:35 -08002461 ALOG_ASSERT(in != NULL, "in shouldn't be NULL");
Eric Laurentb8ba0a92011-08-07 16:32:26 -07002462 // from now on thread->mInput is NULL
Dima Zavin799a70e2011-04-18 16:57:27 -07002463 delete in;
Eric Laurent83b88082014-06-20 18:31:16 -07002464}
Mathias Agopian65ab4712010-07-14 17:59:35 -07002465
Chih-Hung Hsieh36d0ca12016-08-09 14:31:32 -07002466void AudioFlinger::closeInputInternal_l(const sp<RecordThread>& thread)
Eric Laurent83b88082014-06-20 18:31:16 -07002467{
2468 mRecordThreads.removeItem(thread->mId);
2469 closeInputFinish(thread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002470}
2471
Glenn Kastend2304db2014-02-03 07:40:31 -08002472status_t AudioFlinger::invalidateStream(audio_stream_type_t stream)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002473{
2474 Mutex::Autolock _l(mLock);
Glenn Kastend2304db2014-02-03 07:40:31 -08002475 ALOGV("invalidateStream() stream %d", stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002476
2477 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
2478 PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
Eric Laurent22167852012-06-20 12:26:32 -07002479 thread->invalidateTracks(stream);
Eric Laurentde070132010-07-13 04:45:46 -07002480 }
Eric Laurent6acd1d42017-01-04 14:23:29 -08002481 for (size_t i = 0; i < mMmapThreads.size(); i++) {
2482 mMmapThreads[i]->invalidateTracks(stream);
2483 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002484 return NO_ERROR;
2485}
2486
2487
Glenn Kasteneeecb982016-02-26 10:44:04 -08002488audio_unique_id_t AudioFlinger::newAudioUniqueId(audio_unique_id_use_t use)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002489{
Glenn Kasten9d003132016-04-06 14:38:09 -07002490 // This is a binder API, so a malicious client could pass in a bad parameter.
2491 // Check for that before calling the internal API nextUniqueId().
2492 if ((unsigned) use >= (unsigned) AUDIO_UNIQUE_ID_USE_MAX) {
2493 ALOGE("newAudioUniqueId invalid use %d", use);
2494 return AUDIO_UNIQUE_ID_ALLOCATE;
2495 }
Glenn Kasteneeecb982016-02-26 10:44:04 -08002496 return nextUniqueId(use);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002497}
2498
Glenn Kastend848eb42016-03-08 13:42:11 -08002499void AudioFlinger::acquireAudioSessionId(audio_session_t audioSession, pid_t pid)
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002500{
2501 Mutex::Autolock _l(mLock);
Glenn Kastenbb001922012-02-03 11:10:26 -08002502 pid_t caller = IPCThreadState::self()->getCallingPid();
Marco Nelissend457c972014-02-11 08:47:07 -08002503 ALOGV("acquiring %d from %d, for %d", audioSession, caller, pid);
2504 if (pid != -1 && (caller == getpid_cached)) {
2505 caller = pid;
2506 }
Eric Laurentd1b28d42013-09-18 18:47:13 -07002507
Eric Laurent021cf962014-05-13 10:18:14 -07002508 {
2509 Mutex::Autolock _cl(mClientLock);
2510 // Ignore requests received from processes not known as notification client. The request
2511 // is likely proxied by mediaserver (e.g CameraService) and releaseAudioSessionId() can be
2512 // called from a different pid leaving a stale session reference. Also we don't know how
2513 // to clear this reference if the client process dies.
2514 if (mNotificationClients.indexOfKey(caller) < 0) {
2515 ALOGW("acquireAudioSessionId() unknown client %d for session %d", caller, audioSession);
2516 return;
2517 }
Eric Laurentd1b28d42013-09-18 18:47:13 -07002518 }
2519
Glenn Kasten8d6a2442012-02-08 14:04:28 -08002520 size_t num = mAudioSessionRefs.size();
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08002521 for (size_t i = 0; i < num; i++) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002522 AudioSessionRef *ref = mAudioSessionRefs.editItemAt(i);
Glenn Kasten012ca6b2012-03-06 11:22:01 -08002523 if (ref->mSessionid == audioSession && ref->mPid == caller) {
2524 ref->mCnt++;
2525 ALOGV(" incremented refcount to %d", ref->mCnt);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002526 return;
2527 }
2528 }
Glenn Kasten84afa3b2012-01-25 15:28:08 -08002529 mAudioSessionRefs.push(new AudioSessionRef(audioSession, caller));
2530 ALOGV(" added new entry for %d", audioSession);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002531}
2532
Glenn Kastend848eb42016-03-08 13:42:11 -08002533void AudioFlinger::releaseAudioSessionId(audio_session_t audioSession, pid_t pid)
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002534{
2535 Mutex::Autolock _l(mLock);
Glenn Kastenbb001922012-02-03 11:10:26 -08002536 pid_t caller = IPCThreadState::self()->getCallingPid();
Marco Nelissend457c972014-02-11 08:47:07 -08002537 ALOGV("releasing %d from %d for %d", audioSession, caller, pid);
2538 if (pid != -1 && (caller == getpid_cached)) {
2539 caller = pid;
2540 }
Glenn Kasten8d6a2442012-02-08 14:04:28 -08002541 size_t num = mAudioSessionRefs.size();
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08002542 for (size_t i = 0; i < num; i++) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002543 AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
Glenn Kasten012ca6b2012-03-06 11:22:01 -08002544 if (ref->mSessionid == audioSession && ref->mPid == caller) {
2545 ref->mCnt--;
2546 ALOGV(" decremented refcount to %d", ref->mCnt);
2547 if (ref->mCnt == 0) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002548 mAudioSessionRefs.removeAt(i);
2549 delete ref;
2550 purgeStaleEffects_l();
2551 }
2552 return;
2553 }
2554 }
Eric Laurentd1b28d42013-09-18 18:47:13 -07002555 // If the caller is mediaserver it is likely that the session being released was acquired
2556 // on behalf of a process not in notification clients and we ignore the warning.
2557 ALOGW_IF(caller != getpid_cached, "session id %d not found for pid %d", audioSession, caller);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002558}
2559
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08002560bool AudioFlinger::isSessionAcquired_l(audio_session_t audioSession)
2561{
2562 size_t num = mAudioSessionRefs.size();
2563 for (size_t i = 0; i < num; i++) {
2564 AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
2565 if (ref->mSessionid == audioSession) {
2566 return true;
2567 }
2568 }
2569 return false;
2570}
2571
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002572void AudioFlinger::purgeStaleEffects_l() {
2573
Steve Block3856b092011-10-20 11:56:00 +01002574 ALOGV("purging stale effects");
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002575
2576 Vector< sp<EffectChain> > chains;
2577
2578 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
2579 sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
2580 for (size_t j = 0; j < t->mEffectChains.size(); j++) {
2581 sp<EffectChain> ec = t->mEffectChains[j];
Marco Nelissen0270b182011-08-12 14:14:39 -07002582 if (ec->sessionId() > AUDIO_SESSION_OUTPUT_MIX) {
2583 chains.push(ec);
2584 }
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002585 }
2586 }
2587 for (size_t i = 0; i < mRecordThreads.size(); i++) {
2588 sp<RecordThread> t = mRecordThreads.valueAt(i);
2589 for (size_t j = 0; j < t->mEffectChains.size(); j++) {
2590 sp<EffectChain> ec = t->mEffectChains[j];
2591 chains.push(ec);
2592 }
2593 }
2594
2595 for (size_t i = 0; i < chains.size(); i++) {
2596 sp<EffectChain> ec = chains[i];
2597 int sessionid = ec->sessionId();
2598 sp<ThreadBase> t = ec->mThread.promote();
2599 if (t == 0) {
2600 continue;
2601 }
2602 size_t numsessionrefs = mAudioSessionRefs.size();
2603 bool found = false;
2604 for (size_t k = 0; k < numsessionrefs; k++) {
2605 AudioSessionRef *ref = mAudioSessionRefs.itemAt(k);
Glenn Kasten012ca6b2012-03-06 11:22:01 -08002606 if (ref->mSessionid == sessionid) {
Steve Block3856b092011-10-20 11:56:00 +01002607 ALOGV(" session %d still exists for %d with %d refs",
Glenn Kastene53b9ea2012-03-12 16:29:55 -07002608 sessionid, ref->mPid, ref->mCnt);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002609 found = true;
2610 break;
2611 }
2612 }
2613 if (!found) {
Glenn Kastene198c362013-08-13 09:13:36 -07002614 Mutex::Autolock _l(t->mLock);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002615 // remove all effects from the chain
2616 while (ec->mEffects.size()) {
2617 sp<EffectModule> effect = ec->mEffects[0];
2618 effect->unPin();
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002619 t->removeEffect_l(effect);
Eric Laurenta5f44eb2012-06-25 11:38:29 -07002620 if (effect->purgeHandles()) {
2621 t->checkSuspendOnEffectEnabled_l(effect, false, effect->sessionId());
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002622 }
2623 AudioSystem::unregisterEffect(effect->id());
2624 }
2625 }
2626 }
2627 return;
2628}
2629
Glenn Kasteneeecb982016-02-26 10:44:04 -08002630// checkThread_l() must be called with AudioFlinger::mLock held
2631AudioFlinger::ThreadBase *AudioFlinger::checkThread_l(audio_io_handle_t ioHandle) const
2632{
Eric Laurent6acd1d42017-01-04 14:23:29 -08002633 ThreadBase *thread = checkMmapThread_l(ioHandle);
2634 if (thread == 0) {
2635 switch (audio_unique_id_get_use(ioHandle)) {
2636 case AUDIO_UNIQUE_ID_USE_OUTPUT:
2637 thread = checkPlaybackThread_l(ioHandle);
2638 break;
2639 case AUDIO_UNIQUE_ID_USE_INPUT:
2640 thread = checkRecordThread_l(ioHandle);
2641 break;
2642 default:
2643 break;
2644 }
Glenn Kasteneeecb982016-02-26 10:44:04 -08002645 }
2646 return thread;
2647}
2648
Mathias Agopian65ab4712010-07-14 17:59:35 -07002649// checkPlaybackThread_l() must be called with AudioFlinger::mLock held
Glenn Kasten72ef00d2012-01-17 11:09:42 -08002650AudioFlinger::PlaybackThread *AudioFlinger::checkPlaybackThread_l(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07002651{
Glenn Kastena1117922012-01-26 10:53:32 -08002652 return mPlaybackThreads.valueFor(output).get();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002653}
2654
2655// checkMixerThread_l() must be called with AudioFlinger::mLock held
Glenn Kasten72ef00d2012-01-17 11:09:42 -08002656AudioFlinger::MixerThread *AudioFlinger::checkMixerThread_l(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07002657{
2658 PlaybackThread *thread = checkPlaybackThread_l(output);
Glenn Kastena1117922012-01-26 10:53:32 -08002659 return thread != NULL && thread->type() != ThreadBase::DIRECT ? (MixerThread *) thread : NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002660}
2661
2662// checkRecordThread_l() must be called with AudioFlinger::mLock held
Glenn Kasten72ef00d2012-01-17 11:09:42 -08002663AudioFlinger::RecordThread *AudioFlinger::checkRecordThread_l(audio_io_handle_t input) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07002664{
Glenn Kastena1117922012-01-26 10:53:32 -08002665 return mRecordThreads.valueFor(input).get();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002666}
2667
Eric Laurent6acd1d42017-01-04 14:23:29 -08002668// checkMmapThread_l() must be called with AudioFlinger::mLock held
2669AudioFlinger::MmapThread *AudioFlinger::checkMmapThread_l(audio_io_handle_t io) const
2670{
2671 return mMmapThreads.valueFor(io).get();
2672}
2673
2674
2675// checkPlaybackThread_l() must be called with AudioFlinger::mLock held
2676AudioFlinger::VolumeInterface *AudioFlinger::getVolumeInterface_l(audio_io_handle_t output) const
2677{
2678 VolumeInterface *volumeInterface = (VolumeInterface *)mPlaybackThreads.valueFor(output).get();
2679 if (volumeInterface == nullptr) {
2680 MmapThread *mmapThread = mMmapThreads.valueFor(output).get();
2681 if (mmapThread != nullptr) {
2682 if (mmapThread->isOutput()) {
2683 volumeInterface = (VolumeInterface *)mmapThread;
2684 }
2685 }
2686 }
2687 return volumeInterface;
2688}
2689
2690Vector <AudioFlinger::VolumeInterface *> AudioFlinger::getAllVolumeInterfaces_l() const
2691{
2692 Vector <VolumeInterface *> volumeInterfaces;
2693 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
2694 volumeInterfaces.add((VolumeInterface *)mPlaybackThreads.valueAt(i).get());
2695 }
2696 for (size_t i = 0; i < mMmapThreads.size(); i++) {
2697 if (mMmapThreads.valueAt(i)->isOutput()) {
2698 volumeInterfaces.add((VolumeInterface *)mMmapThreads.valueAt(i).get());
2699 }
2700 }
2701 return volumeInterfaces;
2702}
2703
Glenn Kasteneeecb982016-02-26 10:44:04 -08002704audio_unique_id_t AudioFlinger::nextUniqueId(audio_unique_id_use_t use)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002705{
Glenn Kasten9d003132016-04-06 14:38:09 -07002706 // This is the internal API, so it is OK to assert on bad parameter.
Glenn Kasteneeecb982016-02-26 10:44:04 -08002707 LOG_ALWAYS_FATAL_IF((unsigned) use >= (unsigned) AUDIO_UNIQUE_ID_USE_MAX);
Glenn Kastend2e67e12016-04-11 08:26:37 -07002708 const int maxRetries = use == AUDIO_UNIQUE_ID_USE_SESSION ? 3 : 1;
2709 for (int retry = 0; retry < maxRetries; retry++) {
2710 // The cast allows wraparound from max positive to min negative instead of abort
2711 uint32_t base = (uint32_t) atomic_fetch_add_explicit(&mNextUniqueIds[use],
2712 (uint_fast32_t) AUDIO_UNIQUE_ID_USE_MAX, memory_order_acq_rel);
2713 ALOG_ASSERT(audio_unique_id_get_use(base) == AUDIO_UNIQUE_ID_USE_UNSPECIFIED);
2714 // allow wrap by skipping 0 and -1 for session ids
2715 if (!(base == 0 || base == (~0u & ~AUDIO_UNIQUE_ID_USE_MASK))) {
2716 ALOGW_IF(retry != 0, "unique ID overflow for use %d", use);
2717 return (audio_unique_id_t) (base | use);
2718 }
2719 }
2720 // We have no way of recovering from wraparound
2721 LOG_ALWAYS_FATAL("unique ID overflow for use %d", use);
2722 // TODO Use a floor after wraparound. This may need a mutex.
Mathias Agopian65ab4712010-07-14 17:59:35 -07002723}
2724
Glenn Kasten02fe1bf2012-02-24 15:42:17 -08002725AudioFlinger::PlaybackThread *AudioFlinger::primaryPlaybackThread_l() const
Eric Laurent7c7f10b2011-06-17 21:29:58 -07002726{
2727 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
2728 PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
Eric Laurentf6870ae2015-05-08 10:50:03 -07002729 if(thread->isDuplicating()) {
2730 continue;
2731 }
Eric Laurentb8ba0a92011-08-07 16:32:26 -07002732 AudioStreamOut *output = thread->getOutput();
John Grossmanee578c02012-07-23 17:05:46 -07002733 if (output != NULL && output->audioHwDev == mPrimaryHardwareDev) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07002734 return thread;
2735 }
2736 }
2737 return NULL;
2738}
2739
Glenn Kastenbb4350d2012-07-03 15:56:38 -07002740audio_devices_t AudioFlinger::primaryOutputDevice_l() const
Eric Laurent7c7f10b2011-06-17 21:29:58 -07002741{
2742 PlaybackThread *thread = primaryPlaybackThread_l();
2743
2744 if (thread == NULL) {
2745 return 0;
2746 }
2747
Eric Laurentf1c04f92012-08-28 14:26:53 -07002748 return thread->outDevice();
Eric Laurent7c7f10b2011-06-17 21:29:58 -07002749}
2750
Glenn Kastena7335632016-06-09 17:09:53 -07002751AudioFlinger::PlaybackThread *AudioFlinger::fastPlaybackThread_l() const
2752{
2753 size_t minFrameCount = 0;
2754 PlaybackThread *minThread = NULL;
2755 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
2756 PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
2757 if (!thread->isDuplicating()) {
2758 size_t frameCount = thread->frameCountHAL();
2759 if (frameCount != 0 && (minFrameCount == 0 || frameCount < minFrameCount ||
2760 (frameCount == minFrameCount && thread->hasFastMixer() &&
2761 /*minThread != NULL &&*/ !minThread->hasFastMixer()))) {
2762 minFrameCount = frameCount;
2763 minThread = thread;
2764 }
2765 }
2766 }
2767 return minThread;
2768}
2769
Eric Laurenta011e352012-03-29 15:51:43 -07002770sp<AudioFlinger::SyncEvent> AudioFlinger::createSyncEvent(AudioSystem::sync_event_t type,
Glenn Kastend848eb42016-03-08 13:42:11 -08002771 audio_session_t triggerSession,
2772 audio_session_t listenerSession,
Eric Laurenta011e352012-03-29 15:51:43 -07002773 sync_event_callback_t callBack,
Chih-Hung Hsieh36d0ca12016-08-09 14:31:32 -07002774 const wp<RefBase>& cookie)
Eric Laurenta011e352012-03-29 15:51:43 -07002775{
2776 Mutex::Autolock _l(mLock);
2777
2778 sp<SyncEvent> event = new SyncEvent(type, triggerSession, listenerSession, callBack, cookie);
2779 status_t playStatus = NAME_NOT_FOUND;
2780 status_t recStatus = NAME_NOT_FOUND;
2781 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
2782 playStatus = mPlaybackThreads.valueAt(i)->setSyncEvent(event);
2783 if (playStatus == NO_ERROR) {
2784 return event;
2785 }
2786 }
2787 for (size_t i = 0; i < mRecordThreads.size(); i++) {
2788 recStatus = mRecordThreads.valueAt(i)->setSyncEvent(event);
2789 if (recStatus == NO_ERROR) {
2790 return event;
2791 }
2792 }
2793 if (playStatus == NAME_NOT_FOUND || recStatus == NAME_NOT_FOUND) {
2794 mPendingSyncEvents.add(event);
2795 } else {
2796 ALOGV("createSyncEvent() invalid event %d", event->type());
2797 event.clear();
2798 }
2799 return event;
2800}
Eric Laurent7c7f10b2011-06-17 21:29:58 -07002801
Mathias Agopian65ab4712010-07-14 17:59:35 -07002802// ----------------------------------------------------------------------------
2803// Effect management
2804// ----------------------------------------------------------------------------
2805
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -07002806sp<EffectsFactoryHalInterface> AudioFlinger::getEffectsFactory() {
2807 return mEffectsFactoryHal;
2808}
Mathias Agopian65ab4712010-07-14 17:59:35 -07002809
Glenn Kastenf587ba52012-01-26 16:25:10 -08002810status_t AudioFlinger::queryNumberEffects(uint32_t *numEffects) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07002811{
2812 Mutex::Autolock _l(mLock);
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -07002813 if (mEffectsFactoryHal.get()) {
2814 return mEffectsFactoryHal->queryNumberEffects(numEffects);
2815 } else {
2816 return -ENODEV;
2817 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002818}
2819
Glenn Kastenf587ba52012-01-26 16:25:10 -08002820status_t AudioFlinger::queryEffect(uint32_t index, effect_descriptor_t *descriptor) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07002821{
2822 Mutex::Autolock _l(mLock);
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -07002823 if (mEffectsFactoryHal.get()) {
2824 return mEffectsFactoryHal->getDescriptor(index, descriptor);
2825 } else {
2826 return -ENODEV;
2827 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002828}
2829
Glenn Kasten5e92a782012-01-30 07:40:52 -08002830status_t AudioFlinger::getEffectDescriptor(const effect_uuid_t *pUuid,
Glenn Kastenf587ba52012-01-26 16:25:10 -08002831 effect_descriptor_t *descriptor) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07002832{
2833 Mutex::Autolock _l(mLock);
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -07002834 if (mEffectsFactoryHal.get()) {
2835 return mEffectsFactoryHal->getDescriptor(pUuid, descriptor);
2836 } else {
2837 return -ENODEV;
2838 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002839}
2840
2841
Glenn Kasten8d6cc842012-02-03 11:06:53 -08002842sp<IEffect> AudioFlinger::createEffect(
Mathias Agopian65ab4712010-07-14 17:59:35 -07002843 effect_descriptor_t *pDesc,
2844 const sp<IEffectClient>& effectClient,
2845 int32_t priority,
Glenn Kasten72ef00d2012-01-17 11:09:42 -08002846 audio_io_handle_t io,
Glenn Kastend848eb42016-03-08 13:42:11 -08002847 audio_session_t sessionId,
Svet Ganovbe71aa22015-04-28 12:06:02 -07002848 const String16& opPackageName,
Eric Laurentb6436272016-12-07 19:24:50 -08002849 pid_t pid,
Mathias Agopian65ab4712010-07-14 17:59:35 -07002850 status_t *status,
2851 int *id,
2852 int *enabled)
2853{
2854 status_t lStatus = NO_ERROR;
2855 sp<EffectHandle> handle;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002856 effect_descriptor_t desc;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002857
Eric Laurentb6436272016-12-07 19:24:50 -08002858 const uid_t callingUid = IPCThreadState::self()->getCallingUid();
2859 if (pid == -1 || !isTrustedCallingUid(callingUid)) {
2860 const pid_t callingPid = IPCThreadState::self()->getCallingPid();
2861 ALOGW_IF(pid != -1 && pid != callingPid,
2862 "%s uid %d pid %d tried to pass itself off as pid %d",
2863 __func__, callingUid, callingPid, pid);
2864 pid = callingPid;
2865 }
2866
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -07002867 ALOGV("createEffect pid %d, effectClient %p, priority %d, sessionId %d, io %d, factory %p",
2868 pid, effectClient.get(), priority, sessionId, io, mEffectsFactoryHal.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002869
2870 if (pDesc == NULL) {
2871 lStatus = BAD_VALUE;
2872 goto Exit;
2873 }
2874
Eric Laurent84e9a102010-09-23 16:10:16 -07002875 // check audio settings permission for global effects
Dima Zavinfce7a472011-04-19 22:30:36 -07002876 if (sessionId == AUDIO_SESSION_OUTPUT_MIX && !settingsAllowed()) {
Eric Laurent84e9a102010-09-23 16:10:16 -07002877 lStatus = PERMISSION_DENIED;
2878 goto Exit;
2879 }
2880
Dima Zavinfce7a472011-04-19 22:30:36 -07002881 // Session AUDIO_SESSION_OUTPUT_STAGE is reserved for output stage effects
Eric Laurent84e9a102010-09-23 16:10:16 -07002882 // that can only be created by audio policy manager (running in same process)
Glenn Kasten44deb052012-02-05 18:09:08 -08002883 if (sessionId == AUDIO_SESSION_OUTPUT_STAGE && getpid_cached != pid) {
Eric Laurent84e9a102010-09-23 16:10:16 -07002884 lStatus = PERMISSION_DENIED;
2885 goto Exit;
2886 }
2887
Mikhail Naganov1dc98672016-08-18 17:50:29 -07002888 if (mEffectsFactoryHal == 0) {
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -07002889 lStatus = NO_INIT;
2890 goto Exit;
2891 }
2892
Mathias Agopian65ab4712010-07-14 17:59:35 -07002893 {
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -07002894 if (!EffectsFactoryHalInterface::isNullUuid(&pDesc->uuid)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002895 // if uuid is specified, request effect descriptor
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -07002896 lStatus = mEffectsFactoryHal->getDescriptor(&pDesc->uuid, &desc);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002897 if (lStatus < 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00002898 ALOGW("createEffect() error %d from EffectGetDescriptor", lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002899 goto Exit;
2900 }
2901 } else {
2902 // if uuid is not specified, look for an available implementation
2903 // of the required type in effect factory
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -07002904 if (EffectsFactoryHalInterface::isNullUuid(&pDesc->type)) {
Steve Block5ff1dd52012-01-05 23:22:43 +00002905 ALOGW("createEffect() no effect type");
Mathias Agopian65ab4712010-07-14 17:59:35 -07002906 lStatus = BAD_VALUE;
2907 goto Exit;
2908 }
2909 uint32_t numEffects = 0;
2910 effect_descriptor_t d;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07002911 d.flags = 0; // prevent compiler warning
Mathias Agopian65ab4712010-07-14 17:59:35 -07002912 bool found = false;
2913
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -07002914 lStatus = mEffectsFactoryHal->queryNumberEffects(&numEffects);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002915 if (lStatus < 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00002916 ALOGW("createEffect() error %d from EffectQueryNumberEffects", lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002917 goto Exit;
2918 }
2919 for (uint32_t i = 0; i < numEffects; i++) {
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -07002920 lStatus = mEffectsFactoryHal->getDescriptor(i, &desc);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002921 if (lStatus < 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00002922 ALOGW("createEffect() error %d from EffectQueryEffect", lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002923 continue;
2924 }
2925 if (memcmp(&desc.type, &pDesc->type, sizeof(effect_uuid_t)) == 0) {
2926 // If matching type found save effect descriptor. If the session is
2927 // 0 and the effect is not auxiliary, continue enumeration in case
2928 // an auxiliary version of this effect type is available
2929 found = true;
Glenn Kastena189a682012-02-20 12:16:30 -08002930 d = desc;
Dima Zavinfce7a472011-04-19 22:30:36 -07002931 if (sessionId != AUDIO_SESSION_OUTPUT_MIX ||
Mathias Agopian65ab4712010-07-14 17:59:35 -07002932 (desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
2933 break;
2934 }
2935 }
2936 }
2937 if (!found) {
2938 lStatus = BAD_VALUE;
Steve Block5ff1dd52012-01-05 23:22:43 +00002939 ALOGW("createEffect() effect not found");
Mathias Agopian65ab4712010-07-14 17:59:35 -07002940 goto Exit;
2941 }
2942 // For same effect type, chose auxiliary version over insert version if
2943 // connect to output mix (Compliance to OpenSL ES)
Dima Zavinfce7a472011-04-19 22:30:36 -07002944 if (sessionId == AUDIO_SESSION_OUTPUT_MIX &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07002945 (d.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_AUXILIARY) {
Glenn Kastena189a682012-02-20 12:16:30 -08002946 desc = d;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002947 }
2948 }
2949
2950 // Do not allow auxiliary effects on a session different from 0 (output mix)
Dima Zavinfce7a472011-04-19 22:30:36 -07002951 if (sessionId != AUDIO_SESSION_OUTPUT_MIX &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07002952 (desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
2953 lStatus = INVALID_OPERATION;
2954 goto Exit;
2955 }
2956
Eric Laurent59255e42011-07-27 19:49:51 -07002957 // check recording permission for visualizer
2958 if ((memcmp(&desc.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) &&
Marco Nelissendcb346b2015-09-09 10:47:29 -07002959 !recordingAllowed(opPackageName, pid, IPCThreadState::self()->getCallingUid())) {
Eric Laurent59255e42011-07-27 19:49:51 -07002960 lStatus = PERMISSION_DENIED;
2961 goto Exit;
2962 }
2963
Mathias Agopian65ab4712010-07-14 17:59:35 -07002964 // return effect descriptor
Glenn Kastena189a682012-02-20 12:16:30 -08002965 *pDesc = desc;
Glenn Kasten142f5192014-03-25 17:44:59 -07002966 if (io == AUDIO_IO_HANDLE_NONE && sessionId == AUDIO_SESSION_OUTPUT_MIX) {
Eric Laurenteb3c3372013-09-25 12:25:29 -07002967 // if the output returned by getOutputForEffect() is removed before we lock the
2968 // mutex below, the call to checkPlaybackThread_l(io) below will detect it
2969 // and we will exit safely
2970 io = AudioSystem::getOutputForEffect(&desc);
2971 ALOGV("createEffect got output %d", io);
2972 }
2973
2974 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002975
2976 // If output is not specified try to find a matching audio session ID in one of the
2977 // output threads.
Eric Laurent84e9a102010-09-23 16:10:16 -07002978 // If output is 0 here, sessionId is neither SESSION_OUTPUT_STAGE nor SESSION_OUTPUT_MIX
2979 // because of code checking output when entering the function.
Eric Laurent7c7f10b2011-06-17 21:29:58 -07002980 // Note: io is never 0 when creating an effect on an input
Glenn Kasten142f5192014-03-25 17:44:59 -07002981 if (io == AUDIO_IO_HANDLE_NONE) {
Eric Laurent5baf2af2013-09-12 17:37:00 -07002982 if (sessionId == AUDIO_SESSION_OUTPUT_STAGE) {
2983 // output must be specified by AudioPolicyManager when using session
2984 // AUDIO_SESSION_OUTPUT_STAGE
2985 lStatus = BAD_VALUE;
2986 goto Exit;
2987 }
Eric Laurenteb3c3372013-09-25 12:25:29 -07002988 // look for the thread where the specified audio session is present
2989 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
2990 if (mPlaybackThreads.valueAt(i)->hasAudioSession(sessionId) != 0) {
2991 io = mPlaybackThreads.keyAt(i);
2992 break;
2993 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002994 }
Eric Laurent6acd1d42017-01-04 14:23:29 -08002995 if (io == AUDIO_IO_HANDLE_NONE) {
Eric Laurenteb3c3372013-09-25 12:25:29 -07002996 for (size_t i = 0; i < mRecordThreads.size(); i++) {
2997 if (mRecordThreads.valueAt(i)->hasAudioSession(sessionId) != 0) {
2998 io = mRecordThreads.keyAt(i);
Glenn Kastene53b9ea2012-03-12 16:29:55 -07002999 break;
3000 }
3001 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07003002 }
Eric Laurent6acd1d42017-01-04 14:23:29 -08003003 if (io == AUDIO_IO_HANDLE_NONE) {
3004 for (size_t i = 0; i < mMmapThreads.size(); i++) {
3005 if (mMmapThreads.valueAt(i)->hasAudioSession(sessionId) != 0) {
3006 io = mMmapThreads.keyAt(i);
3007 break;
3008 }
3009 }
3010 }
Eric Laurent84e9a102010-09-23 16:10:16 -07003011 // If no output thread contains the requested session ID, default to
3012 // first output. The effect chain will be moved to the correct output
3013 // thread when a track with the same session ID is created
Glenn Kasten142f5192014-03-25 17:44:59 -07003014 if (io == AUDIO_IO_HANDLE_NONE && mPlaybackThreads.size() > 0) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07003015 io = mPlaybackThreads.keyAt(0);
3016 }
Steve Block3856b092011-10-20 11:56:00 +01003017 ALOGV("createEffect() got io %d for effect %s", io, desc.name);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07003018 }
3019 ThreadBase *thread = checkRecordThread_l(io);
3020 if (thread == NULL) {
3021 thread = checkPlaybackThread_l(io);
3022 if (thread == NULL) {
Eric Laurent6acd1d42017-01-04 14:23:29 -08003023 thread = checkMmapThread_l(io);
3024 if (thread == NULL) {
3025 ALOGE("createEffect() unknown output thread");
3026 lStatus = BAD_VALUE;
3027 goto Exit;
3028 }
Eric Laurent84e9a102010-09-23 16:10:16 -07003029 }
Eric Laurentaaa44472014-09-12 17:41:50 -07003030 } else {
3031 // Check if one effect chain was awaiting for an effect to be created on this
3032 // session and used it instead of creating a new one.
Glenn Kastend848eb42016-03-08 13:42:11 -08003033 sp<EffectChain> chain = getOrphanEffectChain_l(sessionId);
Eric Laurentaaa44472014-09-12 17:41:50 -07003034 if (chain != 0) {
Eric Laurent1b928682014-10-02 19:41:47 -07003035 Mutex::Autolock _l(thread->mLock);
Eric Laurentaaa44472014-09-12 17:41:50 -07003036 thread->addEffectChain_l(chain);
3037 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003038 }
Eric Laurent84e9a102010-09-23 16:10:16 -07003039
Eric Laurent021cf962014-05-13 10:18:14 -07003040 sp<Client> client = registerPid(pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003041
Marco Nelissen3a34bef2011-08-02 13:33:41 -07003042 // create effect on selected output thread
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08003043 bool pinned = (sessionId > AUDIO_SESSION_OUTPUT_MIX) && isSessionAcquired_l(sessionId);
Eric Laurentde070132010-07-13 04:45:46 -07003044 handle = thread->createEffect_l(client, effectClient, priority, sessionId,
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08003045 &desc, enabled, &lStatus, pinned);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003046 if (handle != 0 && id != NULL) {
3047 *id = handle->id();
3048 }
Eric Laurentfe1a94e2014-05-26 16:03:08 -07003049 if (handle == 0) {
3050 // remove local strong reference to Client with mClientLock held
3051 Mutex::Autolock _cl(mClientLock);
3052 client.clear();
3053 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003054 }
3055
3056Exit:
Glenn Kasten9156ef32013-08-06 15:39:08 -07003057 *status = lStatus;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003058 return handle;
3059}
3060
Glenn Kastend848eb42016-03-08 13:42:11 -08003061status_t AudioFlinger::moveEffects(audio_session_t sessionId, audio_io_handle_t srcOutput,
Glenn Kasten72ef00d2012-01-17 11:09:42 -08003062 audio_io_handle_t dstOutput)
Eric Laurentde070132010-07-13 04:45:46 -07003063{
Steve Block3856b092011-10-20 11:56:00 +01003064 ALOGV("moveEffects() session %d, srcOutput %d, dstOutput %d",
Eric Laurent59255e42011-07-27 19:49:51 -07003065 sessionId, srcOutput, dstOutput);
Eric Laurentde070132010-07-13 04:45:46 -07003066 Mutex::Autolock _l(mLock);
3067 if (srcOutput == dstOutput) {
Steve Block5ff1dd52012-01-05 23:22:43 +00003068 ALOGW("moveEffects() same dst and src outputs %d", dstOutput);
Eric Laurentde070132010-07-13 04:45:46 -07003069 return NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003070 }
Eric Laurentde070132010-07-13 04:45:46 -07003071 PlaybackThread *srcThread = checkPlaybackThread_l(srcOutput);
3072 if (srcThread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00003073 ALOGW("moveEffects() bad srcOutput %d", srcOutput);
Eric Laurentde070132010-07-13 04:45:46 -07003074 return BAD_VALUE;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003075 }
Eric Laurentde070132010-07-13 04:45:46 -07003076 PlaybackThread *dstThread = checkPlaybackThread_l(dstOutput);
3077 if (dstThread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00003078 ALOGW("moveEffects() bad dstOutput %d", dstOutput);
Eric Laurentde070132010-07-13 04:45:46 -07003079 return BAD_VALUE;
3080 }
3081
3082 Mutex::Autolock _dl(dstThread->mLock);
3083 Mutex::Autolock _sl(srcThread->mLock);
Eric Laurent5baf2af2013-09-12 17:37:00 -07003084 return moveEffectChain_l(sessionId, srcThread, dstThread, false);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003085}
3086
Marco Nelissen3a34bef2011-08-02 13:33:41 -07003087// moveEffectChain_l must be called with both srcThread and dstThread mLocks held
Glenn Kastend848eb42016-03-08 13:42:11 -08003088status_t AudioFlinger::moveEffectChain_l(audio_session_t sessionId,
Eric Laurentde070132010-07-13 04:45:46 -07003089 AudioFlinger::PlaybackThread *srcThread,
Eric Laurent39e94f82010-07-28 01:32:47 -07003090 AudioFlinger::PlaybackThread *dstThread,
3091 bool reRegister)
Eric Laurentde070132010-07-13 04:45:46 -07003092{
Steve Block3856b092011-10-20 11:56:00 +01003093 ALOGV("moveEffectChain_l() session %d from thread %p to thread %p",
Eric Laurent59255e42011-07-27 19:49:51 -07003094 sessionId, srcThread, dstThread);
Eric Laurentde070132010-07-13 04:45:46 -07003095
Eric Laurent59255e42011-07-27 19:49:51 -07003096 sp<EffectChain> chain = srcThread->getEffectChain_l(sessionId);
Eric Laurentde070132010-07-13 04:45:46 -07003097 if (chain == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00003098 ALOGW("moveEffectChain_l() effect chain for session %d not on source thread %p",
Eric Laurent59255e42011-07-27 19:49:51 -07003099 sessionId, srcThread);
Eric Laurentde070132010-07-13 04:45:46 -07003100 return INVALID_OPERATION;
3101 }
3102
Eric Laurent4c415062016-06-17 16:14:16 -07003103 // Check whether the destination thread and all effects in the chain are compatible
3104 if (!chain->isCompatibleWithThread_l(dstThread)) {
Andy Hung9a592762014-07-21 21:56:01 -07003105 ALOGW("moveEffectChain_l() effect chain failed because"
Eric Laurent4c415062016-06-17 16:14:16 -07003106 " destination thread %p is not compatible with effects in the chain",
3107 dstThread);
Andy Hung9a592762014-07-21 21:56:01 -07003108 return INVALID_OPERATION;
3109 }
3110
Eric Laurent39e94f82010-07-28 01:32:47 -07003111 // remove chain first. This is useful only if reconfiguring effect chain on same output thread,
Eric Laurentde070132010-07-13 04:45:46 -07003112 // so that a new chain is created with correct parameters when first effect is added. This is
Eric Laurentec35a142011-10-05 17:42:25 -07003113 // otherwise unnecessary as removeEffect_l() will remove the chain when last effect is
Eric Laurentde070132010-07-13 04:45:46 -07003114 // removed.
3115 srcThread->removeEffectChain_l(chain);
3116
3117 // transfer all effects one by one so that new effect chain is created on new thread with
3118 // correct buffer sizes and audio parameters and effect engines reconfigured accordingly
Eric Laurent39e94f82010-07-28 01:32:47 -07003119 sp<EffectChain> dstChain;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07003120 uint32_t strategy = 0; // prevent compiler warning
Eric Laurentde070132010-07-13 04:45:46 -07003121 sp<EffectModule> effect = chain->getEffectFromId_l(0);
Eric Laurent5baf2af2013-09-12 17:37:00 -07003122 Vector< sp<EffectModule> > removed;
3123 status_t status = NO_ERROR;
Eric Laurentde070132010-07-13 04:45:46 -07003124 while (effect != 0) {
3125 srcThread->removeEffect_l(effect);
Eric Laurent5baf2af2013-09-12 17:37:00 -07003126 removed.add(effect);
3127 status = dstThread->addEffect_l(effect);
3128 if (status != NO_ERROR) {
3129 break;
3130 }
Eric Laurentec35a142011-10-05 17:42:25 -07003131 // removeEffect_l() has stopped the effect if it was active so it must be restarted
3132 if (effect->state() == EffectModule::ACTIVE ||
3133 effect->state() == EffectModule::STOPPING) {
3134 effect->start();
3135 }
Eric Laurent39e94f82010-07-28 01:32:47 -07003136 // if the move request is not received from audio policy manager, the effect must be
3137 // re-registered with the new strategy and output
3138 if (dstChain == 0) {
3139 dstChain = effect->chain().promote();
3140 if (dstChain == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00003141 ALOGW("moveEffectChain_l() cannot get chain from effect %p", effect.get());
Eric Laurent5baf2af2013-09-12 17:37:00 -07003142 status = NO_INIT;
3143 break;
Eric Laurent39e94f82010-07-28 01:32:47 -07003144 }
3145 strategy = dstChain->strategy();
3146 }
3147 if (reRegister) {
3148 AudioSystem::unregisterEffect(effect->id());
3149 AudioSystem::registerEffect(&effect->desc(),
Eric Laurent5baf2af2013-09-12 17:37:00 -07003150 dstThread->id(),
Eric Laurent39e94f82010-07-28 01:32:47 -07003151 strategy,
Eric Laurent59255e42011-07-27 19:49:51 -07003152 sessionId,
Eric Laurent39e94f82010-07-28 01:32:47 -07003153 effect->id());
Eric Laurentd72b7c02013-10-12 16:17:46 -07003154 AudioSystem::setEffectEnabled(effect->id(), effect->isEnabled());
Eric Laurent39e94f82010-07-28 01:32:47 -07003155 }
Eric Laurentde070132010-07-13 04:45:46 -07003156 effect = chain->getEffectFromId_l(0);
3157 }
3158
Eric Laurent5baf2af2013-09-12 17:37:00 -07003159 if (status != NO_ERROR) {
3160 for (size_t i = 0; i < removed.size(); i++) {
3161 srcThread->addEffect_l(removed[i]);
3162 if (dstChain != 0 && reRegister) {
3163 AudioSystem::unregisterEffect(removed[i]->id());
3164 AudioSystem::registerEffect(&removed[i]->desc(),
3165 srcThread->id(),
3166 strategy,
3167 sessionId,
3168 removed[i]->id());
Eric Laurentd72b7c02013-10-12 16:17:46 -07003169 AudioSystem::setEffectEnabled(effect->id(), effect->isEnabled());
Eric Laurent5baf2af2013-09-12 17:37:00 -07003170 }
3171 }
3172 }
3173
3174 return status;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003175}
3176
Eric Laurent5baf2af2013-09-12 17:37:00 -07003177bool AudioFlinger::isNonOffloadableGlobalEffectEnabled_l()
Eric Laurent813e2a72013-08-31 12:59:48 -07003178{
3179 if (mGlobalEffectEnableTime != 0 &&
3180 ((systemTime() - mGlobalEffectEnableTime) < kMinGlobalEffectEnabletimeNs)) {
3181 return true;
3182 }
3183
3184 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
3185 sp<EffectChain> ec =
3186 mPlaybackThreads.valueAt(i)->getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
Eric Laurent5baf2af2013-09-12 17:37:00 -07003187 if (ec != 0 && ec->isNonOffloadableEnabled()) {
Eric Laurent813e2a72013-08-31 12:59:48 -07003188 return true;
3189 }
3190 }
3191 return false;
3192}
3193
Eric Laurent5baf2af2013-09-12 17:37:00 -07003194void AudioFlinger::onNonOffloadableGlobalEffectEnable()
Eric Laurent813e2a72013-08-31 12:59:48 -07003195{
3196 Mutex::Autolock _l(mLock);
3197
3198 mGlobalEffectEnableTime = systemTime();
3199
3200 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
3201 sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
3202 if (t->mType == ThreadBase::OFFLOAD) {
3203 t->invalidateTracks(AUDIO_STREAM_MUSIC);
3204 }
3205 }
3206
3207}
3208
Eric Laurentaaa44472014-09-12 17:41:50 -07003209status_t AudioFlinger::putOrphanEffectChain_l(const sp<AudioFlinger::EffectChain>& chain)
3210{
Glenn Kastend848eb42016-03-08 13:42:11 -08003211 audio_session_t session = chain->sessionId();
Eric Laurentaaa44472014-09-12 17:41:50 -07003212 ssize_t index = mOrphanEffectChains.indexOfKey(session);
Glenn Kastenc42e9b42016-03-21 11:35:03 -07003213 ALOGV("putOrphanEffectChain_l session %d index %zd", session, index);
Eric Laurentaaa44472014-09-12 17:41:50 -07003214 if (index >= 0) {
3215 ALOGW("putOrphanEffectChain_l chain for session %d already present", session);
3216 return ALREADY_EXISTS;
3217 }
3218 mOrphanEffectChains.add(session, chain);
3219 return NO_ERROR;
3220}
3221
3222sp<AudioFlinger::EffectChain> AudioFlinger::getOrphanEffectChain_l(audio_session_t session)
3223{
3224 sp<EffectChain> chain;
3225 ssize_t index = mOrphanEffectChains.indexOfKey(session);
Glenn Kastenc42e9b42016-03-21 11:35:03 -07003226 ALOGV("getOrphanEffectChain_l session %d index %zd", session, index);
Eric Laurentaaa44472014-09-12 17:41:50 -07003227 if (index >= 0) {
3228 chain = mOrphanEffectChains.valueAt(index);
3229 mOrphanEffectChains.removeItemsAt(index);
3230 }
3231 return chain;
3232}
3233
3234bool AudioFlinger::updateOrphanEffectChains(const sp<AudioFlinger::EffectModule>& effect)
3235{
3236 Mutex::Autolock _l(mLock);
Glenn Kastend848eb42016-03-08 13:42:11 -08003237 audio_session_t session = effect->sessionId();
Eric Laurentaaa44472014-09-12 17:41:50 -07003238 ssize_t index = mOrphanEffectChains.indexOfKey(session);
Glenn Kastenc42e9b42016-03-21 11:35:03 -07003239 ALOGV("updateOrphanEffectChains session %d index %zd", session, index);
Eric Laurentaaa44472014-09-12 17:41:50 -07003240 if (index >= 0) {
3241 sp<EffectChain> chain = mOrphanEffectChains.valueAt(index);
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08003242 if (chain->removeEffect_l(effect, true) == 0) {
Glenn Kastenc42e9b42016-03-21 11:35:03 -07003243 ALOGV("updateOrphanEffectChains removing effect chain at index %zd", index);
Eric Laurentaaa44472014-09-12 17:41:50 -07003244 mOrphanEffectChains.removeItemsAt(index);
3245 }
3246 return true;
3247 }
3248 return false;
3249}
3250
3251
Glenn Kastenda6ef132013-01-10 12:31:01 -08003252struct Entry {
Glenn Kasten2f55e762015-03-05 16:05:08 -08003253#define TEE_MAX_FILENAME 32 // %Y%m%d%H%M%S_%d.wav = 4+2+2+2+2+2+1+1+4+1 = 21
3254 char mFileName[TEE_MAX_FILENAME];
Glenn Kastenda6ef132013-01-10 12:31:01 -08003255};
3256
3257int comparEntry(const void *p1, const void *p2)
3258{
Glenn Kasten2f55e762015-03-05 16:05:08 -08003259 return strcmp(((const Entry *) p1)->mFileName, ((const Entry *) p2)->mFileName);
Glenn Kastenda6ef132013-01-10 12:31:01 -08003260}
3261
Glenn Kasten46909e72013-02-26 09:20:22 -08003262#ifdef TEE_SINK
Glenn Kasten5b2191a2016-08-19 11:44:47 -07003263void AudioFlinger::dumpTee(int fd, const sp<NBAIO_Source>& source, audio_io_handle_t id, char suffix)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003264{
Eric Laurent81784c32012-11-19 14:55:58 -08003265 NBAIO_Source *teeSource = source.get();
3266 if (teeSource != NULL) {
Glenn Kastenda6ef132013-01-10 12:31:01 -08003267 // .wav rotation
3268 // There is a benign race condition if 2 threads call this simultaneously.
3269 // They would both traverse the directory, but the result would simply be
3270 // failures at unlink() which are ignored. It's also unlikely since
3271 // normally dumpsys is only done by bugreport or from the command line.
3272 char teePath[32+256];
Glenn Kasten9a003992016-02-23 15:24:34 -08003273 strcpy(teePath, "/data/misc/audioserver");
Glenn Kastenda6ef132013-01-10 12:31:01 -08003274 size_t teePathLen = strlen(teePath);
3275 DIR *dir = opendir(teePath);
3276 teePath[teePathLen++] = '/';
3277 if (dir != NULL) {
Glenn Kasten2f55e762015-03-05 16:05:08 -08003278#define TEE_MAX_SORT 20 // number of entries to sort
3279#define TEE_MAX_KEEP 10 // number of entries to keep
3280 struct Entry entries[TEE_MAX_SORT];
Glenn Kastenda6ef132013-01-10 12:31:01 -08003281 size_t entryCount = 0;
Glenn Kasten2f55e762015-03-05 16:05:08 -08003282 while (entryCount < TEE_MAX_SORT) {
Glenn Kastenda6ef132013-01-10 12:31:01 -08003283 struct dirent de;
3284 struct dirent *result = NULL;
3285 int rc = readdir_r(dir, &de, &result);
3286 if (rc != 0) {
3287 ALOGW("readdir_r failed %d", rc);
3288 break;
3289 }
3290 if (result == NULL) {
3291 break;
3292 }
3293 if (result != &de) {
3294 ALOGW("readdir_r returned unexpected result %p != %p", result, &de);
3295 break;
3296 }
3297 // ignore non .wav file entries
3298 size_t nameLen = strlen(de.d_name);
Glenn Kasten2f55e762015-03-05 16:05:08 -08003299 if (nameLen <= 4 || nameLen >= TEE_MAX_FILENAME ||
Glenn Kastenda6ef132013-01-10 12:31:01 -08003300 strcmp(&de.d_name[nameLen - 4], ".wav")) {
3301 continue;
3302 }
Glenn Kasten2f55e762015-03-05 16:05:08 -08003303 strcpy(entries[entryCount++].mFileName, de.d_name);
Glenn Kastenda6ef132013-01-10 12:31:01 -08003304 }
3305 (void) closedir(dir);
Glenn Kasten2f55e762015-03-05 16:05:08 -08003306 if (entryCount > TEE_MAX_KEEP) {
Glenn Kastenda6ef132013-01-10 12:31:01 -08003307 qsort(entries, entryCount, sizeof(Entry), comparEntry);
Glenn Kasten2f55e762015-03-05 16:05:08 -08003308 for (size_t i = 0; i < entryCount - TEE_MAX_KEEP; ++i) {
3309 strcpy(&teePath[teePathLen], entries[i].mFileName);
Glenn Kastenda6ef132013-01-10 12:31:01 -08003310 (void) unlink(teePath);
3311 }
3312 }
3313 } else {
3314 if (fd >= 0) {
Glenn Kastenfbd87e82016-07-18 15:45:56 -07003315 dprintf(fd, "unable to rotate tees in %.*s: %s\n", (int) teePathLen, teePath,
Glenn Kasten9a003992016-02-23 15:24:34 -08003316 strerror(errno));
Glenn Kastenda6ef132013-01-10 12:31:01 -08003317 }
3318 }
Eric Laurent81784c32012-11-19 14:55:58 -08003319 char teeTime[16];
3320 struct timeval tv;
3321 gettimeofday(&tv, NULL);
3322 struct tm tm;
3323 localtime_r(&tv.tv_sec, &tm);
Glenn Kastenda6ef132013-01-10 12:31:01 -08003324 strftime(teeTime, sizeof(teeTime), "%Y%m%d%H%M%S", &tm);
Glenn Kasten5b2191a2016-08-19 11:44:47 -07003325 snprintf(&teePath[teePathLen], sizeof(teePath) - teePathLen, "%s_%d_%c.wav", teeTime, id,
3326 suffix);
Glenn Kastenda6ef132013-01-10 12:31:01 -08003327 // 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