blob: df5017b57f9181f25803a3820b9e49d3de2f91fe [file] [log] [blame]
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006-2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "AudioSystem"
18//#define LOG_NDEBUG 0
19
20#include <utils/Log.h>
Mathias Agopian75624082009-05-19 19:08:10 -070021#include <binder/IServiceManager.h>
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080022#include <media/AudioSystem.h>
Eric Laurentc2f1f072009-07-17 12:17:14 -070023#include <media/IAudioPolicyService.h>
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080024#include <math.h>
25
Dima Zavin64760242011-05-11 14:15:23 -070026#include <system/audio.h>
Dima Zavinfce7a472011-04-19 22:30:36 -070027
Eric Laurentc2f1f072009-07-17 12:17:14 -070028// ----------------------------------------------------------------------------
Eric Laurentc2f1f072009-07-17 12:17:14 -070029
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080030namespace android {
31
32// client singleton for AudioFlinger binder interface
33Mutex AudioSystem::gLock;
34sp<IAudioFlinger> AudioSystem::gAudioFlinger;
35sp<AudioSystem::AudioFlingerClient> AudioSystem::gAudioFlingerClient;
36audio_error_callback AudioSystem::gAudioErrorCallback = NULL;
37// Cached values
Glenn Kasten211eeaf2012-01-20 09:37:45 -080038
39DefaultKeyedVector<audio_stream_type_t, audio_io_handle_t> AudioSystem::gStreamOutputMap(0);
Eric Laurentc2f1f072009-07-17 12:17:14 -070040DefaultKeyedVector<audio_io_handle_t, AudioSystem::OutputDescriptor *> AudioSystem::gOutputs(0);
41
Glenn Kastenf8c1a6f2012-01-10 09:01:19 -080042// Cached values for recording queries, all protected by gLock
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080043uint32_t AudioSystem::gPrevInSamplingRate = 16000;
Glenn Kasten58f30212012-01-12 12:27:51 -080044audio_format_t AudioSystem::gPrevInFormat = AUDIO_FORMAT_PCM_16_BIT;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080045int AudioSystem::gPrevInChannelCount = 1;
46size_t AudioSystem::gInBuffSize = 0;
47
48
49// establish binder interface to AudioFlinger service
50const sp<IAudioFlinger>& AudioSystem::get_audio_flinger()
51{
52 Mutex::Autolock _l(gLock);
Glenn Kasten7fc9a6f2012-01-10 10:46:34 -080053 if (gAudioFlinger == 0) {
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080054 sp<IServiceManager> sm = defaultServiceManager();
55 sp<IBinder> binder;
56 do {
57 binder = sm->getService(String16("media.audio_flinger"));
58 if (binder != 0)
59 break;
Steve Block5ff1dd52012-01-05 23:22:43 +000060 ALOGW("AudioFlinger not published, waiting...");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080061 usleep(500000); // 0.5 s
62 } while(true);
63 if (gAudioFlingerClient == NULL) {
64 gAudioFlingerClient = new AudioFlingerClient();
65 } else {
66 if (gAudioErrorCallback) {
67 gAudioErrorCallback(NO_ERROR);
68 }
69 }
70 binder->linkToDeath(gAudioFlingerClient);
71 gAudioFlinger = interface_cast<IAudioFlinger>(binder);
72 gAudioFlinger->registerClient(gAudioFlingerClient);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080073 }
Steve Block29357bc2012-01-06 19:20:56 +000074 ALOGE_IF(gAudioFlinger==0, "no AudioFlinger!?");
Eric Laurentc2f1f072009-07-17 12:17:14 -070075
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080076 return gAudioFlinger;
77}
78
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080079status_t AudioSystem::muteMicrophone(bool state) {
80 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
81 if (af == 0) return PERMISSION_DENIED;
82 return af->setMicMute(state);
83}
84
85status_t AudioSystem::isMicrophoneMuted(bool* state) {
86 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
87 if (af == 0) return PERMISSION_DENIED;
88 *state = af->getMicMute();
89 return NO_ERROR;
90}
91
92status_t AudioSystem::setMasterVolume(float value)
93{
94 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
95 if (af == 0) return PERMISSION_DENIED;
96 af->setMasterVolume(value);
97 return NO_ERROR;
98}
99
100status_t AudioSystem::setMasterMute(bool mute)
101{
102 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
103 if (af == 0) return PERMISSION_DENIED;
104 af->setMasterMute(mute);
105 return NO_ERROR;
106}
107
108status_t AudioSystem::getMasterVolume(float* volume)
109{
110 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
111 if (af == 0) return PERMISSION_DENIED;
112 *volume = af->masterVolume();
113 return NO_ERROR;
114}
115
116status_t AudioSystem::getMasterMute(bool* mute)
117{
118 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
119 if (af == 0) return PERMISSION_DENIED;
120 *mute = af->masterMute();
121 return NO_ERROR;
122}
123
Glenn Kastenfff6d712012-01-12 16:38:12 -0800124status_t AudioSystem::setStreamVolume(audio_stream_type_t stream, float value, int output)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800125{
Dima Zavinfce7a472011-04-19 22:30:36 -0700126 if (uint32_t(stream) >= AUDIO_STREAM_CNT) return BAD_VALUE;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800127 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
128 if (af == 0) return PERMISSION_DENIED;
Eric Laurentc2f1f072009-07-17 12:17:14 -0700129 af->setStreamVolume(stream, value, output);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800130 return NO_ERROR;
131}
132
Glenn Kastenfff6d712012-01-12 16:38:12 -0800133status_t AudioSystem::setStreamMute(audio_stream_type_t stream, bool mute)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800134{
Dima Zavinfce7a472011-04-19 22:30:36 -0700135 if (uint32_t(stream) >= AUDIO_STREAM_CNT) return BAD_VALUE;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800136 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
137 if (af == 0) return PERMISSION_DENIED;
138 af->setStreamMute(stream, mute);
139 return NO_ERROR;
140}
141
Glenn Kastenfff6d712012-01-12 16:38:12 -0800142status_t AudioSystem::getStreamVolume(audio_stream_type_t stream, float* volume, int output)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800143{
Dima Zavinfce7a472011-04-19 22:30:36 -0700144 if (uint32_t(stream) >= AUDIO_STREAM_CNT) return BAD_VALUE;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800145 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
146 if (af == 0) return PERMISSION_DENIED;
Eric Laurentc2f1f072009-07-17 12:17:14 -0700147 *volume = af->streamVolume(stream, output);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800148 return NO_ERROR;
149}
150
Glenn Kastenfff6d712012-01-12 16:38:12 -0800151status_t AudioSystem::getStreamMute(audio_stream_type_t stream, bool* mute)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800152{
Dima Zavinfce7a472011-04-19 22:30:36 -0700153 if (uint32_t(stream) >= AUDIO_STREAM_CNT) return BAD_VALUE;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800154 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
155 if (af == 0) return PERMISSION_DENIED;
156 *mute = af->streamMute(stream);
157 return NO_ERROR;
158}
159
Glenn Kastenf78aee72012-01-04 11:00:47 -0800160status_t AudioSystem::setMode(audio_mode_t mode)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800161{
Glenn Kasten930f4ca2012-01-06 16:47:31 -0800162 if (uint32_t(mode) >= AUDIO_MODE_CNT) return BAD_VALUE;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800163 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
164 if (af == 0) return PERMISSION_DENIED;
165 return af->setMode(mode);
166}
167
Eric Laurentc2f1f072009-07-17 12:17:14 -0700168status_t AudioSystem::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs) {
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800169 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
170 if (af == 0) return PERMISSION_DENIED;
Eric Laurentc2f1f072009-07-17 12:17:14 -0700171 return af->setParameters(ioHandle, keyValuePairs);
172}
173
174String8 AudioSystem::getParameters(audio_io_handle_t ioHandle, const String8& keys) {
175 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
176 String8 result = String8("");
177 if (af == 0) return result;
178
179 result = af->getParameters(ioHandle, keys);
180 return result;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800181}
182
183// convert volume steps to natural log scale
184
185// change this value to change volume scaling
186static const float dBPerStep = 0.5f;
187// shouldn't need to touch these
188static const float dBConvert = -dBPerStep * 2.302585093f / 20.0f;
189static const float dBConvertInverse = 1.0f / dBConvert;
190
191float AudioSystem::linearToLog(int volume)
192{
193 // float v = volume ? exp(float(100 - volume) * dBConvert) : 0;
Steve Blockb8a80522011-12-20 16:23:08 +0000194 // ALOGD("linearToLog(%d)=%f", volume, v);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800195 // return v;
196 return volume ? exp(float(100 - volume) * dBConvert) : 0;
197}
198
199int AudioSystem::logToLinear(float volume)
200{
201 // int v = volume ? 100 - int(dBConvertInverse * log(volume) + 0.5) : 0;
Steve Blockb8a80522011-12-20 16:23:08 +0000202 // ALOGD("logTolinear(%d)=%f", v, volume);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800203 // return v;
204 return volume ? 100 - int(dBConvertInverse * log(volume) + 0.5) : 0;
205}
206
Andreas Huberc8139852012-01-18 10:51:55 -0800207// DEPRECATED
208status_t AudioSystem::getOutputSamplingRate(int* samplingRate, int streamType) {
209 return getOutputSamplingRate(samplingRate, (audio_stream_type_t)streamType);
210}
211
Glenn Kastenfff6d712012-01-12 16:38:12 -0800212status_t AudioSystem::getOutputSamplingRate(int* samplingRate, audio_stream_type_t streamType)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800213{
Eric Laurentc2f1f072009-07-17 12:17:14 -0700214 OutputDescriptor *outputDesc;
215 audio_io_handle_t output;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800216
Dima Zavinfce7a472011-04-19 22:30:36 -0700217 if (streamType == AUDIO_STREAM_DEFAULT) {
218 streamType = AUDIO_STREAM_MUSIC;
Eric Laurentc2f1f072009-07-17 12:17:14 -0700219 }
220
Glenn Kastenfff6d712012-01-12 16:38:12 -0800221 output = getOutput(streamType);
Eric Laurentc2f1f072009-07-17 12:17:14 -0700222 if (output == 0) {
223 return PERMISSION_DENIED;
224 }
225
226 gLock.lock();
227 outputDesc = AudioSystem::gOutputs.valueFor(output);
228 if (outputDesc == 0) {
Steve Block3856b092011-10-20 11:56:00 +0100229 ALOGV("getOutputSamplingRate() no output descriptor for output %d in gOutputs", output);
Eric Laurentc2f1f072009-07-17 12:17:14 -0700230 gLock.unlock();
231 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
232 if (af == 0) return PERMISSION_DENIED;
233 *samplingRate = af->sampleRate(output);
234 } else {
Steve Block3856b092011-10-20 11:56:00 +0100235 ALOGV("getOutputSamplingRate() reading from output desc");
Eric Laurentc2f1f072009-07-17 12:17:14 -0700236 *samplingRate = outputDesc->samplingRate;
237 gLock.unlock();
238 }
239
Steve Block3856b092011-10-20 11:56:00 +0100240 ALOGV("getOutputSamplingRate() streamType %d, output %d, sampling rate %d", streamType, output, *samplingRate);
Eric Laurentc2f1f072009-07-17 12:17:14 -0700241
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800242 return NO_ERROR;
243}
244
Andreas Huberc8139852012-01-18 10:51:55 -0800245// DEPRECATED
246status_t AudioSystem::getOutputFrameCount(int* frameCount, int streamType) {
247 return getOutputFrameCount(frameCount, (audio_stream_type_t)streamType);
248}
249
Glenn Kastenfff6d712012-01-12 16:38:12 -0800250status_t AudioSystem::getOutputFrameCount(int* frameCount, audio_stream_type_t streamType)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800251{
Eric Laurentc2f1f072009-07-17 12:17:14 -0700252 OutputDescriptor *outputDesc;
253 audio_io_handle_t output;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800254
Dima Zavinfce7a472011-04-19 22:30:36 -0700255 if (streamType == AUDIO_STREAM_DEFAULT) {
256 streamType = AUDIO_STREAM_MUSIC;
Eric Laurentc2f1f072009-07-17 12:17:14 -0700257 }
Eric Laurent48f7f5e2009-04-02 09:32:43 -0700258
Glenn Kastenfff6d712012-01-12 16:38:12 -0800259 output = getOutput(streamType);
Eric Laurentc2f1f072009-07-17 12:17:14 -0700260 if (output == 0) {
261 return PERMISSION_DENIED;
262 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800263
Eric Laurentc2f1f072009-07-17 12:17:14 -0700264 gLock.lock();
265 outputDesc = AudioSystem::gOutputs.valueFor(output);
266 if (outputDesc == 0) {
267 gLock.unlock();
268 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
269 if (af == 0) return PERMISSION_DENIED;
270 *frameCount = af->frameCount(output);
271 } else {
272 *frameCount = outputDesc->frameCount;
273 gLock.unlock();
274 }
275
Steve Block3856b092011-10-20 11:56:00 +0100276 ALOGV("getOutputFrameCount() streamType %d, output %d, frameCount %d", streamType, output, *frameCount);
Eric Laurentc2f1f072009-07-17 12:17:14 -0700277
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800278 return NO_ERROR;
279}
280
Glenn Kastenfff6d712012-01-12 16:38:12 -0800281status_t AudioSystem::getOutputLatency(uint32_t* latency, audio_stream_type_t streamType)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800282{
Eric Laurentc2f1f072009-07-17 12:17:14 -0700283 OutputDescriptor *outputDesc;
284 audio_io_handle_t output;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800285
Dima Zavinfce7a472011-04-19 22:30:36 -0700286 if (streamType == AUDIO_STREAM_DEFAULT) {
287 streamType = AUDIO_STREAM_MUSIC;
Eric Laurentc2f1f072009-07-17 12:17:14 -0700288 }
Eric Laurent48f7f5e2009-04-02 09:32:43 -0700289
Glenn Kastenfff6d712012-01-12 16:38:12 -0800290 output = getOutput(streamType);
Eric Laurentc2f1f072009-07-17 12:17:14 -0700291 if (output == 0) {
292 return PERMISSION_DENIED;
293 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800294
Eric Laurentc2f1f072009-07-17 12:17:14 -0700295 gLock.lock();
296 outputDesc = AudioSystem::gOutputs.valueFor(output);
297 if (outputDesc == 0) {
298 gLock.unlock();
299 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
300 if (af == 0) return PERMISSION_DENIED;
301 *latency = af->latency(output);
302 } else {
303 *latency = outputDesc->latency;
304 gLock.unlock();
305 }
306
Steve Block3856b092011-10-20 11:56:00 +0100307 ALOGV("getOutputLatency() streamType %d, output %d, latency %d", streamType, output, *latency);
Eric Laurentc2f1f072009-07-17 12:17:14 -0700308
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800309 return NO_ERROR;
310}
311
Glenn Kasten58f30212012-01-12 12:27:51 -0800312status_t AudioSystem::getInputBufferSize(uint32_t sampleRate, audio_format_t format, int channelCount,
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800313 size_t* buffSize)
314{
Glenn Kastenf8c1a6f2012-01-10 09:01:19 -0800315 gLock.lock();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800316 // Do we have a stale gInBufferSize or are we requesting the input buffer size for new values
Glenn Kastenf8c1a6f2012-01-10 09:01:19 -0800317 size_t inBuffSize = gInBuffSize;
318 if ((inBuffSize == 0) || (sampleRate != gPrevInSamplingRate) || (format != gPrevInFormat)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800319 || (channelCount != gPrevInChannelCount)) {
Glenn Kastenf8c1a6f2012-01-10 09:01:19 -0800320 gLock.unlock();
321 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
322 if (af == 0) {
323 return PERMISSION_DENIED;
324 }
325 inBuffSize = af->getInputBufferSize(sampleRate, format, channelCount);
326 gLock.lock();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800327 // save the request params
328 gPrevInSamplingRate = sampleRate;
Eric Laurentc2f1f072009-07-17 12:17:14 -0700329 gPrevInFormat = format;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800330 gPrevInChannelCount = channelCount;
331
Glenn Kastenf8c1a6f2012-01-10 09:01:19 -0800332 gInBuffSize = inBuffSize;
Eric Laurentc2f1f072009-07-17 12:17:14 -0700333 }
Glenn Kastenf8c1a6f2012-01-10 09:01:19 -0800334 gLock.unlock();
335 *buffSize = inBuffSize;
Eric Laurentc2f1f072009-07-17 12:17:14 -0700336
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800337 return NO_ERROR;
338}
339
Eric Laurentf0ee6f42009-10-21 08:14:22 -0700340status_t AudioSystem::setVoiceVolume(float value)
341{
342 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
343 if (af == 0) return PERMISSION_DENIED;
344 return af->setVoiceVolume(value);
345}
346
Glenn Kastenfff6d712012-01-12 16:38:12 -0800347status_t AudioSystem::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, audio_stream_type_t stream)
Eric Laurent342e9cf2010-01-19 17:37:09 -0800348{
349 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
350 if (af == 0) return PERMISSION_DENIED;
351
Dima Zavinfce7a472011-04-19 22:30:36 -0700352 if (stream == AUDIO_STREAM_DEFAULT) {
353 stream = AUDIO_STREAM_MUSIC;
Eric Laurent342e9cf2010-01-19 17:37:09 -0800354 }
355
Glenn Kastenfff6d712012-01-12 16:38:12 -0800356 return af->getRenderPosition(halFrames, dspFrames, getOutput(stream));
Eric Laurent342e9cf2010-01-19 17:37:09 -0800357}
358
Eric Laurent05bca2f2010-02-26 02:47:27 -0800359unsigned int AudioSystem::getInputFramesLost(audio_io_handle_t ioHandle) {
360 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
361 unsigned int result = 0;
362 if (af == 0) return result;
Eric Laurentbe55a2d2010-03-11 14:47:00 -0800363 if (ioHandle == 0) return result;
Eric Laurent05bca2f2010-02-26 02:47:27 -0800364
365 result = af->getInputFramesLost(ioHandle);
366 return result;
367}
368
Eric Laurentbe916aa2010-06-01 23:49:17 -0700369int AudioSystem::newAudioSessionId() {
370 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
371 if (af == 0) return 0;
372 return af->newAudioSessionId();
373}
374
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700375void AudioSystem::acquireAudioSessionId(int audioSession) {
376 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
377 if (af != 0) {
378 af->acquireAudioSessionId(audioSession);
379 }
380}
381
382void AudioSystem::releaseAudioSessionId(int audioSession) {
383 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
384 if (af != 0) {
385 af->releaseAudioSessionId(audioSession);
386 }
387}
388
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800389// ---------------------------------------------------------------------------
390
Eric Laurentc2f1f072009-07-17 12:17:14 -0700391void AudioSystem::AudioFlingerClient::binderDied(const wp<IBinder>& who) {
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800392 Mutex::Autolock _l(AudioSystem::gLock);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800393
Eric Laurentc2f1f072009-07-17 12:17:14 -0700394 AudioSystem::gAudioFlinger.clear();
Eric Laurent0ef583f2010-01-25 10:27:15 -0800395 // clear output handles and stream to output map caches
396 AudioSystem::gStreamOutputMap.clear();
397 AudioSystem::gOutputs.clear();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800398
399 if (gAudioErrorCallback) {
400 gAudioErrorCallback(DEAD_OBJECT);
401 }
Steve Block5ff1dd52012-01-05 23:22:43 +0000402 ALOGW("AudioFlinger server died!");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800403}
404
Eric Laurentfa2877b2009-07-28 08:44:33 -0700405void AudioSystem::AudioFlingerClient::ioConfigChanged(int event, int ioHandle, void *param2) {
Steve Block3856b092011-10-20 11:56:00 +0100406 ALOGV("ioConfigChanged() event %d", event);
Eric Laurentc2f1f072009-07-17 12:17:14 -0700407 OutputDescriptor *desc;
Glenn Kasten211eeaf2012-01-20 09:37:45 -0800408 audio_stream_type_t stream;
Eric Laurentc2f1f072009-07-17 12:17:14 -0700409
Eric Laurentfa2877b2009-07-28 08:44:33 -0700410 if (ioHandle == 0) return;
Eric Laurentc2f1f072009-07-17 12:17:14 -0700411
412 Mutex::Autolock _l(AudioSystem::gLock);
413
414 switch (event) {
415 case STREAM_CONFIG_CHANGED:
416 if (param2 == 0) break;
Glenn Kasten211eeaf2012-01-20 09:37:45 -0800417 stream = *(audio_stream_type_t *)param2;
Steve Block3856b092011-10-20 11:56:00 +0100418 ALOGV("ioConfigChanged() STREAM_CONFIG_CHANGED stream %d, output %d", stream, ioHandle);
Eric Laurentc2f1f072009-07-17 12:17:14 -0700419 if (gStreamOutputMap.indexOfKey(stream) >= 0) {
420 gStreamOutputMap.replaceValueFor(stream, ioHandle);
421 }
422 break;
423 case OUTPUT_OPENED: {
424 if (gOutputs.indexOfKey(ioHandle) >= 0) {
Steve Block3856b092011-10-20 11:56:00 +0100425 ALOGV("ioConfigChanged() opening already existing output! %d", ioHandle);
Eric Laurentc2f1f072009-07-17 12:17:14 -0700426 break;
427 }
428 if (param2 == 0) break;
429 desc = (OutputDescriptor *)param2;
430
431 OutputDescriptor *outputDesc = new OutputDescriptor(*desc);
432 gOutputs.add(ioHandle, outputDesc);
Steve Block3856b092011-10-20 11:56:00 +0100433 ALOGV("ioConfigChanged() new output samplingRate %d, format %d channels %d frameCount %d latency %d",
Eric Laurentc2f1f072009-07-17 12:17:14 -0700434 outputDesc->samplingRate, outputDesc->format, outputDesc->channels, outputDesc->frameCount, outputDesc->latency);
435 } break;
436 case OUTPUT_CLOSED: {
437 if (gOutputs.indexOfKey(ioHandle) < 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000438 ALOGW("ioConfigChanged() closing unknow output! %d", ioHandle);
Eric Laurentc2f1f072009-07-17 12:17:14 -0700439 break;
440 }
Steve Block3856b092011-10-20 11:56:00 +0100441 ALOGV("ioConfigChanged() output %d closed", ioHandle);
Eric Laurentc2f1f072009-07-17 12:17:14 -0700442
443 gOutputs.removeItem(ioHandle);
444 for (int i = gStreamOutputMap.size() - 1; i >= 0 ; i--) {
445 if (gStreamOutputMap.valueAt(i) == ioHandle) {
446 gStreamOutputMap.removeItemsAt(i);
447 }
448 }
449 } break;
450
451 case OUTPUT_CONFIG_CHANGED: {
452 int index = gOutputs.indexOfKey(ioHandle);
453 if (index < 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000454 ALOGW("ioConfigChanged() modifying unknow output! %d", ioHandle);
Eric Laurentc2f1f072009-07-17 12:17:14 -0700455 break;
456 }
457 if (param2 == 0) break;
458 desc = (OutputDescriptor *)param2;
459
Steve Block3856b092011-10-20 11:56:00 +0100460 ALOGV("ioConfigChanged() new config for output %d samplingRate %d, format %d channels %d frameCount %d latency %d",
Eric Laurentc2f1f072009-07-17 12:17:14 -0700461 ioHandle, desc->samplingRate, desc->format,
462 desc->channels, desc->frameCount, desc->latency);
463 OutputDescriptor *outputDesc = gOutputs.valueAt(index);
464 delete outputDesc;
465 outputDesc = new OutputDescriptor(*desc);
466 gOutputs.replaceValueFor(ioHandle, outputDesc);
467 } break;
468 case INPUT_OPENED:
469 case INPUT_CLOSED:
470 case INPUT_CONFIG_CHANGED:
471 break;
472
473 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800474}
475
476void AudioSystem::setErrorCallback(audio_error_callback cb) {
Eric Laurentc2f1f072009-07-17 12:17:14 -0700477 Mutex::Autolock _l(gLock);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800478 gAudioErrorCallback = cb;
479}
480
Glenn Kastenfff6d712012-01-12 16:38:12 -0800481bool AudioSystem::routedToA2dpOutput(audio_stream_type_t streamType) {
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800482 switch(streamType) {
Dima Zavinfce7a472011-04-19 22:30:36 -0700483 case AUDIO_STREAM_MUSIC:
484 case AUDIO_STREAM_VOICE_CALL:
485 case AUDIO_STREAM_BLUETOOTH_SCO:
486 case AUDIO_STREAM_SYSTEM:
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800487 return true;
488 default:
489 return false;
490 }
491}
492
493
Eric Laurentc2f1f072009-07-17 12:17:14 -0700494// client singleton for AudioPolicyService binder interface
495sp<IAudioPolicyService> AudioSystem::gAudioPolicyService;
496sp<AudioSystem::AudioPolicyServiceClient> AudioSystem::gAudioPolicyServiceClient;
497
498
499// establish binder interface to AudioFlinger service
500const sp<IAudioPolicyService>& AudioSystem::get_audio_policy_service()
501{
502 gLock.lock();
Glenn Kasten7fc9a6f2012-01-10 10:46:34 -0800503 if (gAudioPolicyService == 0) {
Eric Laurentc2f1f072009-07-17 12:17:14 -0700504 sp<IServiceManager> sm = defaultServiceManager();
505 sp<IBinder> binder;
506 do {
507 binder = sm->getService(String16("media.audio_policy"));
508 if (binder != 0)
509 break;
Steve Block5ff1dd52012-01-05 23:22:43 +0000510 ALOGW("AudioPolicyService not published, waiting...");
Eric Laurentc2f1f072009-07-17 12:17:14 -0700511 usleep(500000); // 0.5 s
512 } while(true);
513 if (gAudioPolicyServiceClient == NULL) {
514 gAudioPolicyServiceClient = new AudioPolicyServiceClient();
515 }
516 binder->linkToDeath(gAudioPolicyServiceClient);
517 gAudioPolicyService = interface_cast<IAudioPolicyService>(binder);
518 gLock.unlock();
519 } else {
520 gLock.unlock();
521 }
522 return gAudioPolicyService;
523}
524
Dima Zavinfce7a472011-04-19 22:30:36 -0700525status_t AudioSystem::setDeviceConnectionState(audio_devices_t device,
526 audio_policy_dev_state_t state,
527 const char *device_address)
Eric Laurentc2f1f072009-07-17 12:17:14 -0700528{
529 const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
Eric Laurent71b63e32011-09-02 14:20:56 -0700530 const char *address = "";
531
Eric Laurentc2f1f072009-07-17 12:17:14 -0700532 if (aps == 0) return PERMISSION_DENIED;
533
Eric Laurent71b63e32011-09-02 14:20:56 -0700534 if (device_address != NULL) {
535 address = device_address;
536 }
537
538 return aps->setDeviceConnectionState(device, state, address);
Eric Laurentc2f1f072009-07-17 12:17:14 -0700539}
540
Dima Zavinfce7a472011-04-19 22:30:36 -0700541audio_policy_dev_state_t AudioSystem::getDeviceConnectionState(audio_devices_t device,
Eric Laurentc2f1f072009-07-17 12:17:14 -0700542 const char *device_address)
543{
544 const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
Dima Zavinfce7a472011-04-19 22:30:36 -0700545 if (aps == 0) return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
Eric Laurentc2f1f072009-07-17 12:17:14 -0700546
547 return aps->getDeviceConnectionState(device, device_address);
548}
549
Glenn Kastenf78aee72012-01-04 11:00:47 -0800550status_t AudioSystem::setPhoneState(audio_mode_t state)
Eric Laurentc2f1f072009-07-17 12:17:14 -0700551{
Glenn Kasten347966c2012-01-18 14:58:32 -0800552 if (uint32_t(state) >= AUDIO_MODE_CNT) return BAD_VALUE;
Eric Laurentc2f1f072009-07-17 12:17:14 -0700553 const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
554 if (aps == 0) return PERMISSION_DENIED;
555
556 return aps->setPhoneState(state);
557}
558
Dima Zavinfce7a472011-04-19 22:30:36 -0700559status_t AudioSystem::setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config)
Eric Laurentc2f1f072009-07-17 12:17:14 -0700560{
561 const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
562 if (aps == 0) return PERMISSION_DENIED;
563 return aps->setForceUse(usage, config);
564}
565
Dima Zavinfce7a472011-04-19 22:30:36 -0700566audio_policy_forced_cfg_t AudioSystem::getForceUse(audio_policy_force_use_t usage)
Eric Laurentc2f1f072009-07-17 12:17:14 -0700567{
568 const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
Dima Zavinfce7a472011-04-19 22:30:36 -0700569 if (aps == 0) return AUDIO_POLICY_FORCE_NONE;
Eric Laurentc2f1f072009-07-17 12:17:14 -0700570 return aps->getForceUse(usage);
571}
572
573
Dima Zavinfce7a472011-04-19 22:30:36 -0700574audio_io_handle_t AudioSystem::getOutput(audio_stream_type_t stream,
Eric Laurentc2f1f072009-07-17 12:17:14 -0700575 uint32_t samplingRate,
Glenn Kasten58f30212012-01-12 12:27:51 -0800576 audio_format_t format,
Eric Laurentc2f1f072009-07-17 12:17:14 -0700577 uint32_t channels,
Dima Zavinfce7a472011-04-19 22:30:36 -0700578 audio_policy_output_flags_t flags)
Eric Laurentc2f1f072009-07-17 12:17:14 -0700579{
Eric Laurentfa2877b2009-07-28 08:44:33 -0700580 audio_io_handle_t output = 0;
Eric Laurentbe55a2d2010-03-11 14:47:00 -0800581 // Do not use stream to output map cache if the direct output
582 // flag is set or if we are likely to use a direct output
583 // (e.g voice call stream @ 8kHz could use BT SCO device and be routed to
584 // a direct output on some platforms).
585 // TODO: the output cache and stream to output mapping implementation needs to
586 // be reworked for proper operation with direct outputs. This code is too specific
587 // to the first use case we want to cover (Voice Recognition and Voice Dialer over
588 // Bluetooth SCO
Dima Zavinfce7a472011-04-19 22:30:36 -0700589 if ((flags & AUDIO_POLICY_OUTPUT_FLAG_DIRECT) == 0 &&
590 ((stream != AUDIO_STREAM_VOICE_CALL && stream != AUDIO_STREAM_BLUETOOTH_SCO) ||
591 channels != AUDIO_CHANNEL_OUT_MONO ||
Eric Laurentbe55a2d2010-03-11 14:47:00 -0800592 (samplingRate != 8000 && samplingRate != 16000))) {
Eric Laurentc2f1f072009-07-17 12:17:14 -0700593 Mutex::Autolock _l(gLock);
594 output = AudioSystem::gStreamOutputMap.valueFor(stream);
Steve Block3856b092011-10-20 11:56:00 +0100595 ALOGV_IF((output != 0), "getOutput() read %d from cache for stream %d", output, stream);
Eric Laurentc2f1f072009-07-17 12:17:14 -0700596 }
Eric Laurentfa2877b2009-07-28 08:44:33 -0700597 if (output == 0) {
Eric Laurentc2f1f072009-07-17 12:17:14 -0700598 const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
Eric Laurentfa2877b2009-07-28 08:44:33 -0700599 if (aps == 0) return 0;
Eric Laurentc2f1f072009-07-17 12:17:14 -0700600 output = aps->getOutput(stream, samplingRate, format, channels, flags);
Dima Zavinfce7a472011-04-19 22:30:36 -0700601 if ((flags & AUDIO_POLICY_OUTPUT_FLAG_DIRECT) == 0) {
Eric Laurentc2f1f072009-07-17 12:17:14 -0700602 Mutex::Autolock _l(gLock);
603 AudioSystem::gStreamOutputMap.add(stream, output);
604 }
605 }
606 return output;
607}
608
Eric Laurentde070132010-07-13 04:45:46 -0700609status_t AudioSystem::startOutput(audio_io_handle_t output,
Dima Zavinfce7a472011-04-19 22:30:36 -0700610 audio_stream_type_t stream,
Eric Laurentde070132010-07-13 04:45:46 -0700611 int session)
Eric Laurentc2f1f072009-07-17 12:17:14 -0700612{
613 const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
614 if (aps == 0) return PERMISSION_DENIED;
Eric Laurentde070132010-07-13 04:45:46 -0700615 return aps->startOutput(output, stream, session);
Eric Laurentc2f1f072009-07-17 12:17:14 -0700616}
617
Eric Laurentde070132010-07-13 04:45:46 -0700618status_t AudioSystem::stopOutput(audio_io_handle_t output,
Dima Zavinfce7a472011-04-19 22:30:36 -0700619 audio_stream_type_t stream,
Eric Laurentde070132010-07-13 04:45:46 -0700620 int session)
Eric Laurentc2f1f072009-07-17 12:17:14 -0700621{
622 const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
623 if (aps == 0) return PERMISSION_DENIED;
Eric Laurentde070132010-07-13 04:45:46 -0700624 return aps->stopOutput(output, stream, session);
Eric Laurentc2f1f072009-07-17 12:17:14 -0700625}
626
627void AudioSystem::releaseOutput(audio_io_handle_t output)
628{
629 const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
630 if (aps == 0) return;
631 aps->releaseOutput(output);
632}
633
Glenn Kasteneba51fb2012-01-23 13:58:49 -0800634audio_io_handle_t AudioSystem::getInput(audio_source_t inputSource,
Eric Laurentc2f1f072009-07-17 12:17:14 -0700635 uint32_t samplingRate,
Glenn Kasten58f30212012-01-12 12:27:51 -0800636 audio_format_t format,
Eric Laurentc2f1f072009-07-17 12:17:14 -0700637 uint32_t channels,
Eric Laurent7c7f10b2011-06-17 21:29:58 -0700638 audio_in_acoustics_t acoustics,
639 int sessionId)
Eric Laurentc2f1f072009-07-17 12:17:14 -0700640{
641 const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
Eric Laurentfa2877b2009-07-28 08:44:33 -0700642 if (aps == 0) return 0;
Eric Laurent7c7f10b2011-06-17 21:29:58 -0700643 return aps->getInput(inputSource, samplingRate, format, channels, acoustics, sessionId);
Eric Laurentc2f1f072009-07-17 12:17:14 -0700644}
645
646status_t AudioSystem::startInput(audio_io_handle_t input)
647{
648 const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
649 if (aps == 0) return PERMISSION_DENIED;
650 return aps->startInput(input);
651}
652
653status_t AudioSystem::stopInput(audio_io_handle_t input)
654{
655 const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
656 if (aps == 0) return PERMISSION_DENIED;
657 return aps->stopInput(input);
658}
659
660void AudioSystem::releaseInput(audio_io_handle_t input)
661{
662 const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
663 if (aps == 0) return;
664 aps->releaseInput(input);
665}
666
Dima Zavinfce7a472011-04-19 22:30:36 -0700667status_t AudioSystem::initStreamVolume(audio_stream_type_t stream,
Eric Laurentc2f1f072009-07-17 12:17:14 -0700668 int indexMin,
669 int indexMax)
670{
671 const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
672 if (aps == 0) return PERMISSION_DENIED;
673 return aps->initStreamVolume(stream, indexMin, indexMax);
674}
675
Eric Laurent83844cc2011-11-18 16:43:31 -0800676status_t AudioSystem::setStreamVolumeIndex(audio_stream_type_t stream,
677 int index,
678 audio_devices_t device)
Eric Laurentc2f1f072009-07-17 12:17:14 -0700679{
680 const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
681 if (aps == 0) return PERMISSION_DENIED;
Eric Laurent83844cc2011-11-18 16:43:31 -0800682 return aps->setStreamVolumeIndex(stream, index, device);
Eric Laurentc2f1f072009-07-17 12:17:14 -0700683}
684
Eric Laurent83844cc2011-11-18 16:43:31 -0800685status_t AudioSystem::getStreamVolumeIndex(audio_stream_type_t stream,
686 int *index,
687 audio_devices_t device)
Eric Laurentc2f1f072009-07-17 12:17:14 -0700688{
689 const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
690 if (aps == 0) return PERMISSION_DENIED;
Eric Laurent83844cc2011-11-18 16:43:31 -0800691 return aps->getStreamVolumeIndex(stream, index, device);
Eric Laurentc2f1f072009-07-17 12:17:14 -0700692}
693
Dima Zavinfce7a472011-04-19 22:30:36 -0700694uint32_t AudioSystem::getStrategyForStream(audio_stream_type_t stream)
Eric Laurentde070132010-07-13 04:45:46 -0700695{
696 const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
697 if (aps == 0) return 0;
698 return aps->getStrategyForStream(stream);
699}
700
Dima Zavinfce7a472011-04-19 22:30:36 -0700701uint32_t AudioSystem::getDevicesForStream(audio_stream_type_t stream)
Glenn Kasten6b2718c2011-02-04 13:54:26 -0800702{
703 const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
704 if (aps == 0) return 0;
705 return aps->getDevicesForStream(stream);
706}
707
Eric Laurentde070132010-07-13 04:45:46 -0700708audio_io_handle_t AudioSystem::getOutputForEffect(effect_descriptor_t *desc)
709{
710 const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
711 if (aps == 0) return PERMISSION_DENIED;
712 return aps->getOutputForEffect(desc);
713}
714
715status_t AudioSystem::registerEffect(effect_descriptor_t *desc,
Eric Laurent7c7f10b2011-06-17 21:29:58 -0700716 audio_io_handle_t io,
Eric Laurentde070132010-07-13 04:45:46 -0700717 uint32_t strategy,
718 int session,
719 int id)
720{
721 const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
722 if (aps == 0) return PERMISSION_DENIED;
Eric Laurent7c7f10b2011-06-17 21:29:58 -0700723 return aps->registerEffect(desc, io, strategy, session, id);
Eric Laurentde070132010-07-13 04:45:46 -0700724}
725
726status_t AudioSystem::unregisterEffect(int id)
727{
728 const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
729 if (aps == 0) return PERMISSION_DENIED;
730 return aps->unregisterEffect(id);
731}
732
Eric Laurentdb7c0792011-08-10 10:37:50 -0700733status_t AudioSystem::setEffectEnabled(int id, bool enabled)
734{
735 const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
736 if (aps == 0) return PERMISSION_DENIED;
737 return aps->setEffectEnabled(id, enabled);
738}
739
Glenn Kastenfff6d712012-01-12 16:38:12 -0800740status_t AudioSystem::isStreamActive(audio_stream_type_t stream, bool* state, uint32_t inPastMs)
Eric Laurent7c7f10b2011-06-17 21:29:58 -0700741{
Eric Laurenteda6c362011-02-02 09:33:30 -0800742 const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
743 if (aps == 0) return PERMISSION_DENIED;
Eric Laurent7c7f10b2011-06-17 21:29:58 -0700744 if (state == NULL) return BAD_VALUE;
Eric Laurenteda6c362011-02-02 09:33:30 -0800745 *state = aps->isStreamActive(stream, inPastMs);
746 return NO_ERROR;
747}
748
749
Eric Laurent9f6530f2011-08-30 10:18:54 -0700750void AudioSystem::clearAudioConfigCache()
751{
752 Mutex::Autolock _l(gLock);
Steve Block3856b092011-10-20 11:56:00 +0100753 ALOGV("clearAudioConfigCache()");
Eric Laurent9f6530f2011-08-30 10:18:54 -0700754 gStreamOutputMap.clear();
755 gOutputs.clear();
756}
757
Eric Laurentc2f1f072009-07-17 12:17:14 -0700758// ---------------------------------------------------------------------------
759
760void AudioSystem::AudioPolicyServiceClient::binderDied(const wp<IBinder>& who) {
761 Mutex::Autolock _l(AudioSystem::gLock);
762 AudioSystem::gAudioPolicyService.clear();
763
Steve Block5ff1dd52012-01-05 23:22:43 +0000764 ALOGW("AudioPolicyService server died!");
Eric Laurentc2f1f072009-07-17 12:17:14 -0700765}
766
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800767}; // namespace android
768