blob: edea2c59110370d4dc1668a7c7d3e001938dcdf5 [file] [log] [blame]
Mathias Agopian65ab4712010-07-14 17:59:35 -07001/*
2 * Copyright (C) 2009 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 "AudioPolicyManagerBase"
18//#define LOG_NDEBUG 0
19#include <utils/Log.h>
20#include <hardware_legacy/AudioPolicyManagerBase.h>
21#include <media/mediarecorder.h>
22
23namespace android {
24
25
26// ----------------------------------------------------------------------------
27// AudioPolicyInterface implementation
28// ----------------------------------------------------------------------------
29
30
31status_t AudioPolicyManagerBase::setDeviceConnectionState(AudioSystem::audio_devices device,
32 AudioSystem::device_connection_state state,
33 const char *device_address)
34{
35
36 LOGV("setDeviceConnectionState() device: %x, state %d, address %s", device, state, device_address);
37
38 // connect/disconnect only 1 device at a time
39 if (AudioSystem::popCount(device) != 1) return BAD_VALUE;
40
41 if (strlen(device_address) >= MAX_DEVICE_ADDRESS_LEN) {
42 LOGE("setDeviceConnectionState() invalid address: %s", device_address);
43 return BAD_VALUE;
44 }
45
46 // handle output devices
47 if (AudioSystem::isOutputDevice(device)) {
48
49#ifndef WITH_A2DP
50 if (AudioSystem::isA2dpDevice(device)) {
51 LOGE("setDeviceConnectionState() invalid device: %x", device);
52 return BAD_VALUE;
53 }
54#endif
55
56 switch (state)
57 {
58 // handle output device connection
59 case AudioSystem::DEVICE_STATE_AVAILABLE:
60 if (mAvailableOutputDevices & device) {
61 LOGW("setDeviceConnectionState() device already connected: %x", device);
62 return INVALID_OPERATION;
63 }
64 LOGV("setDeviceConnectionState() connecting device %x", device);
65
66 // register new device as available
67 mAvailableOutputDevices |= device;
68
69#ifdef WITH_A2DP
70 // handle A2DP device connection
71 if (AudioSystem::isA2dpDevice(device)) {
72 status_t status = handleA2dpConnection(device, device_address);
73 if (status != NO_ERROR) {
74 mAvailableOutputDevices &= ~device;
75 return status;
76 }
77 } else
78#endif
79 {
80 if (AudioSystem::isBluetoothScoDevice(device)) {
81 LOGV("setDeviceConnectionState() BT SCO device, address %s", device_address);
82 // keep track of SCO device address
83 mScoDeviceAddress = String8(device_address, MAX_DEVICE_ADDRESS_LEN);
84#ifdef WITH_A2DP
85 if (mA2dpOutput != 0 &&
86 mPhoneState != AudioSystem::MODE_NORMAL) {
87 mpClientInterface->suspendOutput(mA2dpOutput);
88 }
89#endif
90 }
91 }
92 break;
93 // handle output device disconnection
94 case AudioSystem::DEVICE_STATE_UNAVAILABLE: {
95 if (!(mAvailableOutputDevices & device)) {
96 LOGW("setDeviceConnectionState() device not connected: %x", device);
97 return INVALID_OPERATION;
98 }
99
100
101 LOGV("setDeviceConnectionState() disconnecting device %x", device);
102 // remove device from available output devices
103 mAvailableOutputDevices &= ~device;
104
105#ifdef WITH_A2DP
106 // handle A2DP device disconnection
107 if (AudioSystem::isA2dpDevice(device)) {
108 status_t status = handleA2dpDisconnection(device, device_address);
109 if (status != NO_ERROR) {
110 mAvailableOutputDevices |= device;
111 return status;
112 }
113 } else
114#endif
115 {
116 if (AudioSystem::isBluetoothScoDevice(device)) {
117 mScoDeviceAddress = "";
118#ifdef WITH_A2DP
119 if (mA2dpOutput != 0 &&
120 mPhoneState != AudioSystem::MODE_NORMAL) {
121 mpClientInterface->restoreOutput(mA2dpOutput);
122 }
123#endif
124 }
125 }
126 } break;
127
128 default:
129 LOGE("setDeviceConnectionState() invalid state: %x", state);
130 return BAD_VALUE;
131 }
132
133 // request routing change if necessary
134 uint32_t newDevice = getNewDevice(mHardwareOutput, false);
135#ifdef WITH_A2DP
Eric Laurentc1c88e22010-08-27 17:10:36 -0700136 checkOutputForAllStrategies();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700137 // A2DP outputs must be closed after checkOutputForAllStrategies() is executed
138 if (state == AudioSystem::DEVICE_STATE_UNAVAILABLE && AudioSystem::isA2dpDevice(device)) {
139 closeA2dpOutputs();
140 }
141#endif
142 updateDeviceForStrategy();
143 setOutputDevice(mHardwareOutput, newDevice);
144
145 if (device == AudioSystem::DEVICE_OUT_WIRED_HEADSET) {
146 device = AudioSystem::DEVICE_IN_WIRED_HEADSET;
147 } else if (device == AudioSystem::DEVICE_OUT_BLUETOOTH_SCO ||
148 device == AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET ||
149 device == AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT) {
150 device = AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET;
151 } else {
152 return NO_ERROR;
153 }
154 }
155 // handle input devices
156 if (AudioSystem::isInputDevice(device)) {
157
158 switch (state)
159 {
160 // handle input device connection
161 case AudioSystem::DEVICE_STATE_AVAILABLE: {
162 if (mAvailableInputDevices & device) {
163 LOGW("setDeviceConnectionState() device already connected: %d", device);
164 return INVALID_OPERATION;
165 }
166 mAvailableInputDevices |= device;
167 }
168 break;
169
170 // handle input device disconnection
171 case AudioSystem::DEVICE_STATE_UNAVAILABLE: {
172 if (!(mAvailableInputDevices & device)) {
173 LOGW("setDeviceConnectionState() device not connected: %d", device);
174 return INVALID_OPERATION;
175 }
176 mAvailableInputDevices &= ~device;
177 } break;
178
179 default:
180 LOGE("setDeviceConnectionState() invalid state: %x", state);
181 return BAD_VALUE;
182 }
183
184 audio_io_handle_t activeInput = getActiveInput();
185 if (activeInput != 0) {
186 AudioInputDescriptor *inputDesc = mInputs.valueFor(activeInput);
187 uint32_t newDevice = getDeviceForInputSource(inputDesc->mInputSource);
188 if (newDevice != inputDesc->mDevice) {
189 LOGV("setDeviceConnectionState() changing device from %x to %x for input %d",
190 inputDesc->mDevice, newDevice, activeInput);
191 inputDesc->mDevice = newDevice;
192 AudioParameter param = AudioParameter();
193 param.addInt(String8(AudioParameter::keyRouting), (int)newDevice);
194 mpClientInterface->setParameters(activeInput, param.toString());
195 }
196 }
197
198 return NO_ERROR;
199 }
200
201 LOGW("setDeviceConnectionState() invalid device: %x", device);
202 return BAD_VALUE;
203}
204
205AudioSystem::device_connection_state AudioPolicyManagerBase::getDeviceConnectionState(AudioSystem::audio_devices device,
206 const char *device_address)
207{
208 AudioSystem::device_connection_state state = AudioSystem::DEVICE_STATE_UNAVAILABLE;
209 String8 address = String8(device_address);
210 if (AudioSystem::isOutputDevice(device)) {
211 if (device & mAvailableOutputDevices) {
212#ifdef WITH_A2DP
213 if (AudioSystem::isA2dpDevice(device) &&
214 address != "" && mA2dpDeviceAddress != address) {
215 return state;
216 }
217#endif
218 if (AudioSystem::isBluetoothScoDevice(device) &&
219 address != "" && mScoDeviceAddress != address) {
220 return state;
221 }
222 state = AudioSystem::DEVICE_STATE_AVAILABLE;
223 }
224 } else if (AudioSystem::isInputDevice(device)) {
225 if (device & mAvailableInputDevices) {
226 state = AudioSystem::DEVICE_STATE_AVAILABLE;
227 }
228 }
229
230 return state;
231}
232
233void AudioPolicyManagerBase::setPhoneState(int state)
234{
235 LOGV("setPhoneState() state %d", state);
236 uint32_t newDevice = 0;
237 if (state < 0 || state >= AudioSystem::NUM_MODES) {
238 LOGW("setPhoneState() invalid state %d", state);
239 return;
240 }
241
242 if (state == mPhoneState ) {
243 LOGW("setPhoneState() setting same state %d", state);
244 return;
245 }
246
247 // if leaving call state, handle special case of active streams
248 // pertaining to sonification strategy see handleIncallSonification()
249 if (mPhoneState == AudioSystem::MODE_IN_CALL) {
250 LOGV("setPhoneState() in call state management: new state is %d", state);
251 for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
252 handleIncallSonification(stream, false, true);
253 }
254 }
255
256 // store previous phone state for management of sonification strategy below
257 int oldState = mPhoneState;
258 mPhoneState = state;
259 bool force = false;
260
261 // are we entering or starting a call
262 if ((oldState != AudioSystem::MODE_IN_CALL) && (state == AudioSystem::MODE_IN_CALL)) {
263 LOGV(" Entering call in setPhoneState()");
264 // force routing command to audio hardware when starting a call
265 // even if no device change is needed
266 force = true;
267 } else if ((oldState == AudioSystem::MODE_IN_CALL) && (state != AudioSystem::MODE_IN_CALL)) {
268 LOGV(" Exiting call in setPhoneState()");
269 // force routing command to audio hardware when exiting a call
270 // even if no device change is needed
271 force = true;
272 }
273
274 // check for device and output changes triggered by new phone state
275 newDevice = getNewDevice(mHardwareOutput, false);
276#ifdef WITH_A2DP
Eric Laurentc1c88e22010-08-27 17:10:36 -0700277 checkOutputForAllStrategies();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700278 // suspend A2DP output if a SCO device is present.
279 if (mA2dpOutput != 0 && mScoDeviceAddress != "") {
280 if (oldState == AudioSystem::MODE_NORMAL) {
281 mpClientInterface->suspendOutput(mA2dpOutput);
282 } else if (state == AudioSystem::MODE_NORMAL) {
283 mpClientInterface->restoreOutput(mA2dpOutput);
284 }
285 }
286#endif
287 updateDeviceForStrategy();
288
289 AudioOutputDescriptor *hwOutputDesc = mOutputs.valueFor(mHardwareOutput);
290
291 // force routing command to audio hardware when ending call
292 // even if no device change is needed
293 if (oldState == AudioSystem::MODE_IN_CALL && newDevice == 0) {
294 newDevice = hwOutputDesc->device();
295 }
296
297 // when changing from ring tone to in call mode, mute the ringing tone
298 // immediately and delay the route change to avoid sending the ring tone
299 // tail into the earpiece or headset.
300 int delayMs = 0;
301 if (state == AudioSystem::MODE_IN_CALL && oldState == AudioSystem::MODE_RINGTONE) {
302 // delay the device change command by twice the output latency to have some margin
303 // and be sure that audio buffers not yet affected by the mute are out when
304 // we actually apply the route change
305 delayMs = hwOutputDesc->mLatency*2;
306 setStreamMute(AudioSystem::RING, true, mHardwareOutput);
307 }
308
309 // change routing is necessary
310 setOutputDevice(mHardwareOutput, newDevice, force, delayMs);
311
312 // if entering in call state, handle special case of active streams
313 // pertaining to sonification strategy see handleIncallSonification()
314 if (state == AudioSystem::MODE_IN_CALL) {
315 LOGV("setPhoneState() in call state management: new state is %d", state);
316 // unmute the ringing tone after a sufficient delay if it was muted before
317 // setting output device above
318 if (oldState == AudioSystem::MODE_RINGTONE) {
319 setStreamMute(AudioSystem::RING, false, mHardwareOutput, MUTE_TIME_MS);
320 }
321 for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
322 handleIncallSonification(stream, true, true);
323 }
324 }
325
326 // Flag that ringtone volume must be limited to music volume until we exit MODE_RINGTONE
327 if (state == AudioSystem::MODE_RINGTONE &&
328 (hwOutputDesc->mRefCount[AudioSystem::MUSIC] ||
329 (systemTime() - mMusicStopTime) < seconds(SONIFICATION_HEADSET_MUSIC_DELAY))) {
330 mLimitRingtoneVolume = true;
331 } else {
332 mLimitRingtoneVolume = false;
333 }
334}
335
336void AudioPolicyManagerBase::setRingerMode(uint32_t mode, uint32_t mask)
337{
338 LOGV("setRingerMode() mode %x, mask %x", mode, mask);
339
340 mRingerMode = mode;
341}
342
343void AudioPolicyManagerBase::setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config)
344{
345 LOGV("setForceUse() usage %d, config %d, mPhoneState %d", usage, config, mPhoneState);
346
347 bool forceVolumeReeval = false;
348 switch(usage) {
349 case AudioSystem::FOR_COMMUNICATION:
350 if (config != AudioSystem::FORCE_SPEAKER && config != AudioSystem::FORCE_BT_SCO &&
351 config != AudioSystem::FORCE_NONE) {
352 LOGW("setForceUse() invalid config %d for FOR_COMMUNICATION", config);
353 return;
354 }
355 mForceUse[usage] = config;
356 break;
357 case AudioSystem::FOR_MEDIA:
358 if (config != AudioSystem::FORCE_HEADPHONES && config != AudioSystem::FORCE_BT_A2DP &&
Praveen Bharathib235dee2010-10-06 15:23:14 -0500359 config != AudioSystem::FORCE_WIRED_ACCESSORY &&
360 config != AudioSystem::FORCE_ANALOG_DOCK &&
361 config != AudioSystem::FORCE_DIGITAL_DOCK && config != AudioSystem::FORCE_NONE) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700362 LOGW("setForceUse() invalid config %d for FOR_MEDIA", config);
363 return;
364 }
365 mForceUse[usage] = config;
366 break;
367 case AudioSystem::FOR_RECORD:
368 if (config != AudioSystem::FORCE_BT_SCO && config != AudioSystem::FORCE_WIRED_ACCESSORY &&
369 config != AudioSystem::FORCE_NONE) {
370 LOGW("setForceUse() invalid config %d for FOR_RECORD", config);
371 return;
372 }
373 mForceUse[usage] = config;
374 break;
375 case AudioSystem::FOR_DOCK:
376 if (config != AudioSystem::FORCE_NONE && config != AudioSystem::FORCE_BT_CAR_DOCK &&
Praveen Bharathib235dee2010-10-06 15:23:14 -0500377 config != AudioSystem::FORCE_BT_DESK_DOCK &&
378 config != AudioSystem::FORCE_WIRED_ACCESSORY &&
379 config != AudioSystem::FORCE_ANALOG_DOCK &&
380 config != AudioSystem::FORCE_DIGITAL_DOCK) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700381 LOGW("setForceUse() invalid config %d for FOR_DOCK", config);
382 }
383 forceVolumeReeval = true;
384 mForceUse[usage] = config;
385 break;
386 default:
387 LOGW("setForceUse() invalid usage %d", usage);
388 break;
389 }
390
391 // check for device and output changes triggered by new phone state
392 uint32_t newDevice = getNewDevice(mHardwareOutput, false);
393#ifdef WITH_A2DP
Eric Laurentc1c88e22010-08-27 17:10:36 -0700394 checkOutputForAllStrategies();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700395#endif
396 updateDeviceForStrategy();
397 setOutputDevice(mHardwareOutput, newDevice);
398 if (forceVolumeReeval) {
399 applyStreamVolumes(mHardwareOutput, newDevice);
400 }
Eric Laurentc1c88e22010-08-27 17:10:36 -0700401
402 audio_io_handle_t activeInput = getActiveInput();
403 if (activeInput != 0) {
404 AudioInputDescriptor *inputDesc = mInputs.valueFor(activeInput);
405 newDevice = getDeviceForInputSource(inputDesc->mInputSource);
406 if (newDevice != inputDesc->mDevice) {
407 LOGV("setForceUse() changing device from %x to %x for input %d",
408 inputDesc->mDevice, newDevice, activeInput);
409 inputDesc->mDevice = newDevice;
410 AudioParameter param = AudioParameter();
411 param.addInt(String8(AudioParameter::keyRouting), (int)newDevice);
412 mpClientInterface->setParameters(activeInput, param.toString());
413 }
414 }
415
Mathias Agopian65ab4712010-07-14 17:59:35 -0700416}
417
418AudioSystem::forced_config AudioPolicyManagerBase::getForceUse(AudioSystem::force_use usage)
419{
420 return mForceUse[usage];
421}
422
423void AudioPolicyManagerBase::setSystemProperty(const char* property, const char* value)
424{
425 LOGV("setSystemProperty() property %s, value %s", property, value);
426 if (strcmp(property, "ro.camera.sound.forced") == 0) {
427 if (atoi(value)) {
428 LOGV("ENFORCED_AUDIBLE cannot be muted");
429 mStreams[AudioSystem::ENFORCED_AUDIBLE].mCanBeMuted = false;
430 } else {
431 LOGV("ENFORCED_AUDIBLE can be muted");
432 mStreams[AudioSystem::ENFORCED_AUDIBLE].mCanBeMuted = true;
433 }
434 }
435}
436
437audio_io_handle_t AudioPolicyManagerBase::getOutput(AudioSystem::stream_type stream,
438 uint32_t samplingRate,
439 uint32_t format,
440 uint32_t channels,
441 AudioSystem::output_flags flags)
442{
443 audio_io_handle_t output = 0;
444 uint32_t latency = 0;
445 routing_strategy strategy = getStrategy((AudioSystem::stream_type)stream);
446 uint32_t device = getDeviceForStrategy(strategy);
447 LOGV("getOutput() stream %d, samplingRate %d, format %d, channels %x, flags %x", stream, samplingRate, format, channels, flags);
448
449#ifdef AUDIO_POLICY_TEST
450 if (mCurOutput != 0) {
451 LOGV("getOutput() test output mCurOutput %d, samplingRate %d, format %d, channels %x, mDirectOutput %d",
452 mCurOutput, mTestSamplingRate, mTestFormat, mTestChannels, mDirectOutput);
453
454 if (mTestOutputs[mCurOutput] == 0) {
455 LOGV("getOutput() opening test output");
456 AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();
457 outputDesc->mDevice = mTestDevice;
458 outputDesc->mSamplingRate = mTestSamplingRate;
459 outputDesc->mFormat = mTestFormat;
460 outputDesc->mChannels = mTestChannels;
461 outputDesc->mLatency = mTestLatencyMs;
462 outputDesc->mFlags = (AudioSystem::output_flags)(mDirectOutput ? AudioSystem::OUTPUT_FLAG_DIRECT : 0);
463 outputDesc->mRefCount[stream] = 0;
464 mTestOutputs[mCurOutput] = mpClientInterface->openOutput(&outputDesc->mDevice,
465 &outputDesc->mSamplingRate,
466 &outputDesc->mFormat,
467 &outputDesc->mChannels,
468 &outputDesc->mLatency,
469 outputDesc->mFlags);
470 if (mTestOutputs[mCurOutput]) {
471 AudioParameter outputCmd = AudioParameter();
472 outputCmd.addInt(String8("set_id"),mCurOutput);
473 mpClientInterface->setParameters(mTestOutputs[mCurOutput],outputCmd.toString());
474 addOutput(mTestOutputs[mCurOutput], outputDesc);
475 }
476 }
477 return mTestOutputs[mCurOutput];
478 }
479#endif //AUDIO_POLICY_TEST
480
481 // open a direct output if required by specified parameters
482 if (needsDirectOuput(stream, samplingRate, format, channels, flags, device)) {
483
484 LOGV("getOutput() opening direct output device %x", device);
485 AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();
486 outputDesc->mDevice = device;
487 outputDesc->mSamplingRate = samplingRate;
488 outputDesc->mFormat = format;
489 outputDesc->mChannels = channels;
490 outputDesc->mLatency = 0;
491 outputDesc->mFlags = (AudioSystem::output_flags)(flags | AudioSystem::OUTPUT_FLAG_DIRECT);
492 outputDesc->mRefCount[stream] = 0;
493 output = mpClientInterface->openOutput(&outputDesc->mDevice,
494 &outputDesc->mSamplingRate,
495 &outputDesc->mFormat,
496 &outputDesc->mChannels,
497 &outputDesc->mLatency,
498 outputDesc->mFlags);
499
500 // only accept an output with the requeted parameters
501 if (output == 0 ||
502 (samplingRate != 0 && samplingRate != outputDesc->mSamplingRate) ||
503 (format != 0 && format != outputDesc->mFormat) ||
504 (channels != 0 && channels != outputDesc->mChannels)) {
505 LOGV("getOutput() failed opening direct output: samplingRate %d, format %d, channels %d",
506 samplingRate, format, channels);
507 if (output != 0) {
508 mpClientInterface->closeOutput(output);
509 }
510 delete outputDesc;
511 return 0;
512 }
513 addOutput(output, outputDesc);
514 return output;
515 }
516
517 if (channels != 0 && channels != AudioSystem::CHANNEL_OUT_MONO &&
518 channels != AudioSystem::CHANNEL_OUT_STEREO) {
519 return 0;
520 }
521 // open a non direct output
522
523 // get which output is suitable for the specified stream. The actual routing change will happen
524 // when startOutput() will be called
525 uint32_t a2dpDevice = device & AudioSystem::DEVICE_OUT_ALL_A2DP;
526 if (AudioSystem::popCount((AudioSystem::audio_devices)device) == 2) {
527#ifdef WITH_A2DP
528 if (a2dpUsedForSonification() && a2dpDevice != 0) {
529 // if playing on 2 devices among which one is A2DP, use duplicated output
530 LOGV("getOutput() using duplicated output");
531 LOGW_IF((mA2dpOutput == 0), "getOutput() A2DP device in multiple %x selected but A2DP output not opened", device);
532 output = mDuplicatedOutput;
533 } else
534#endif
535 {
536 // if playing on 2 devices among which none is A2DP, use hardware output
537 output = mHardwareOutput;
538 }
539 LOGV("getOutput() using output %d for 2 devices %x", output, device);
540 } else {
541#ifdef WITH_A2DP
542 if (a2dpDevice != 0) {
543 // if playing on A2DP device, use a2dp output
544 LOGW_IF((mA2dpOutput == 0), "getOutput() A2DP device %x selected but A2DP output not opened", device);
545 output = mA2dpOutput;
546 } else
547#endif
548 {
549 // if playing on not A2DP device, use hardware output
550 output = mHardwareOutput;
551 }
552 }
553
554
555 LOGW_IF((output ==0), "getOutput() could not find output for stream %d, samplingRate %d, format %d, channels %x, flags %x",
556 stream, samplingRate, format, channels, flags);
557
558 return output;
559}
560
Eric Laurentde070132010-07-13 04:45:46 -0700561status_t AudioPolicyManagerBase::startOutput(audio_io_handle_t output,
562 AudioSystem::stream_type stream,
563 int session)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700564{
Eric Laurentde070132010-07-13 04:45:46 -0700565 LOGV("startOutput() output %d, stream %d, session %d", output, stream, session);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700566 ssize_t index = mOutputs.indexOfKey(output);
567 if (index < 0) {
568 LOGW("startOutput() unknow output %d", output);
569 return BAD_VALUE;
570 }
571
572 AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index);
573 routing_strategy strategy = getStrategy((AudioSystem::stream_type)stream);
574
575#ifdef WITH_A2DP
576 if (mA2dpOutput != 0 && !a2dpUsedForSonification() && strategy == STRATEGY_SONIFICATION) {
577 setStrategyMute(STRATEGY_MEDIA, true, mA2dpOutput);
578 }
579#endif
580
581 // incremenent usage count for this stream on the requested output:
582 // NOTE that the usage count is the same for duplicated output and hardware output which is
583 // necassary for a correct control of hardware output routing by startOutput() and stopOutput()
584 outputDesc->changeRefCount(stream, 1);
585
586 setOutputDevice(output, getNewDevice(output));
587
588 // handle special case for sonification while in call
589 if (mPhoneState == AudioSystem::MODE_IN_CALL) {
590 handleIncallSonification(stream, true, false);
591 }
592
593 // apply volume rules for current stream and device if necessary
594 checkAndSetVolume(stream, mStreams[stream].mIndexCur, output, outputDesc->device());
595
596 return NO_ERROR;
597}
598
Eric Laurentde070132010-07-13 04:45:46 -0700599status_t AudioPolicyManagerBase::stopOutput(audio_io_handle_t output,
600 AudioSystem::stream_type stream,
601 int session)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700602{
Eric Laurentde070132010-07-13 04:45:46 -0700603 LOGV("stopOutput() output %d, stream %d, session %d", output, stream, session);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700604 ssize_t index = mOutputs.indexOfKey(output);
605 if (index < 0) {
606 LOGW("stopOutput() unknow output %d", output);
607 return BAD_VALUE;
608 }
609
610 AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index);
611 routing_strategy strategy = getStrategy((AudioSystem::stream_type)stream);
612
613 // handle special case for sonification while in call
614 if (mPhoneState == AudioSystem::MODE_IN_CALL) {
615 handleIncallSonification(stream, false, false);
616 }
617
618 if (outputDesc->mRefCount[stream] > 0) {
619 // decrement usage count of this stream on the output
620 outputDesc->changeRefCount(stream, -1);
621 // store time at which the last music track was stopped - see computeVolume()
622 if (stream == AudioSystem::MUSIC) {
623 mMusicStopTime = systemTime();
624 }
625
626 setOutputDevice(output, getNewDevice(output));
627
628#ifdef WITH_A2DP
Eric Laurentde070132010-07-13 04:45:46 -0700629 if (mA2dpOutput != 0 && !a2dpUsedForSonification() &&
630 strategy == STRATEGY_SONIFICATION) {
631 setStrategyMute(STRATEGY_MEDIA,
632 false,
633 mA2dpOutput,
634 mOutputs.valueFor(mHardwareOutput)->mLatency*2);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700635 }
636#endif
637 if (output != mHardwareOutput) {
638 setOutputDevice(mHardwareOutput, getNewDevice(mHardwareOutput), true);
639 }
640 return NO_ERROR;
641 } else {
642 LOGW("stopOutput() refcount is already 0 for output %d", output);
643 return INVALID_OPERATION;
644 }
645}
646
647void AudioPolicyManagerBase::releaseOutput(audio_io_handle_t output)
648{
649 LOGV("releaseOutput() %d", output);
650 ssize_t index = mOutputs.indexOfKey(output);
651 if (index < 0) {
652 LOGW("releaseOutput() releasing unknown output %d", output);
653 return;
654 }
655
656#ifdef AUDIO_POLICY_TEST
657 int testIndex = testOutputIndex(output);
658 if (testIndex != 0) {
659 AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index);
660 if (outputDesc->refCount() == 0) {
661 mpClientInterface->closeOutput(output);
662 delete mOutputs.valueAt(index);
663 mOutputs.removeItem(output);
664 mTestOutputs[testIndex] = 0;
665 }
666 return;
667 }
668#endif //AUDIO_POLICY_TEST
669
670 if (mOutputs.valueAt(index)->mFlags & AudioSystem::OUTPUT_FLAG_DIRECT) {
671 mpClientInterface->closeOutput(output);
672 delete mOutputs.valueAt(index);
673 mOutputs.removeItem(output);
674 }
675}
676
677audio_io_handle_t AudioPolicyManagerBase::getInput(int inputSource,
678 uint32_t samplingRate,
679 uint32_t format,
680 uint32_t channels,
681 AudioSystem::audio_in_acoustics acoustics)
682{
683 audio_io_handle_t input = 0;
684 uint32_t device = getDeviceForInputSource(inputSource);
685
686 LOGV("getInput() inputSource %d, samplingRate %d, format %d, channels %x, acoustics %x", inputSource, samplingRate, format, channels, acoustics);
687
688 if (device == 0) {
689 return 0;
690 }
691
692 // adapt channel selection to input source
693 switch(inputSource) {
694 case AUDIO_SOURCE_VOICE_UPLINK:
695 channels = AudioSystem::CHANNEL_IN_VOICE_UPLINK;
696 break;
697 case AUDIO_SOURCE_VOICE_DOWNLINK:
698 channels = AudioSystem::CHANNEL_IN_VOICE_DNLINK;
699 break;
700 case AUDIO_SOURCE_VOICE_CALL:
701 channels = (AudioSystem::CHANNEL_IN_VOICE_UPLINK | AudioSystem::CHANNEL_IN_VOICE_DNLINK);
702 break;
703 default:
704 break;
705 }
706
707 AudioInputDescriptor *inputDesc = new AudioInputDescriptor();
708
709 inputDesc->mInputSource = inputSource;
710 inputDesc->mDevice = device;
711 inputDesc->mSamplingRate = samplingRate;
712 inputDesc->mFormat = format;
713 inputDesc->mChannels = channels;
714 inputDesc->mAcoustics = acoustics;
715 inputDesc->mRefCount = 0;
716 input = mpClientInterface->openInput(&inputDesc->mDevice,
717 &inputDesc->mSamplingRate,
718 &inputDesc->mFormat,
719 &inputDesc->mChannels,
720 inputDesc->mAcoustics);
721
722 // only accept input with the exact requested set of parameters
723 if (input == 0 ||
724 (samplingRate != inputDesc->mSamplingRate) ||
725 (format != inputDesc->mFormat) ||
726 (channels != inputDesc->mChannels)) {
727 LOGV("getInput() failed opening input: samplingRate %d, format %d, channels %d",
728 samplingRate, format, channels);
729 if (input != 0) {
730 mpClientInterface->closeInput(input);
731 }
732 delete inputDesc;
733 return 0;
734 }
735 mInputs.add(input, inputDesc);
736 return input;
737}
738
739status_t AudioPolicyManagerBase::startInput(audio_io_handle_t input)
740{
741 LOGV("startInput() input %d", input);
742 ssize_t index = mInputs.indexOfKey(input);
743 if (index < 0) {
744 LOGW("startInput() unknow input %d", input);
745 return BAD_VALUE;
746 }
747 AudioInputDescriptor *inputDesc = mInputs.valueAt(index);
748
749#ifdef AUDIO_POLICY_TEST
750 if (mTestInput == 0)
751#endif //AUDIO_POLICY_TEST
752 {
753 // refuse 2 active AudioRecord clients at the same time
754 if (getActiveInput() != 0) {
755 LOGW("startInput() input %d failed: other input already started", input);
756 return INVALID_OPERATION;
757 }
758 }
759
760 AudioParameter param = AudioParameter();
761 param.addInt(String8(AudioParameter::keyRouting), (int)inputDesc->mDevice);
762
763 // use Voice Recognition mode or not for this input based on input source
764 int vr_enabled = inputDesc->mInputSource == AUDIO_SOURCE_VOICE_RECOGNITION ? 1 : 0;
765 param.addInt(String8("vr_mode"), vr_enabled);
766 LOGV("AudioPolicyManager::startInput(%d), setting vr_mode to %d", inputDesc->mInputSource, vr_enabled);
767
768 mpClientInterface->setParameters(input, param.toString());
769
770 inputDesc->mRefCount = 1;
771 return NO_ERROR;
772}
773
774status_t AudioPolicyManagerBase::stopInput(audio_io_handle_t input)
775{
776 LOGV("stopInput() input %d", input);
777 ssize_t index = mInputs.indexOfKey(input);
778 if (index < 0) {
779 LOGW("stopInput() unknow input %d", input);
780 return BAD_VALUE;
781 }
782 AudioInputDescriptor *inputDesc = mInputs.valueAt(index);
783
784 if (inputDesc->mRefCount == 0) {
785 LOGW("stopInput() input %d already stopped", input);
786 return INVALID_OPERATION;
787 } else {
788 AudioParameter param = AudioParameter();
789 param.addInt(String8(AudioParameter::keyRouting), 0);
790 mpClientInterface->setParameters(input, param.toString());
791 inputDesc->mRefCount = 0;
792 return NO_ERROR;
793 }
794}
795
796void AudioPolicyManagerBase::releaseInput(audio_io_handle_t input)
797{
798 LOGV("releaseInput() %d", input);
799 ssize_t index = mInputs.indexOfKey(input);
800 if (index < 0) {
801 LOGW("releaseInput() releasing unknown input %d", input);
802 return;
803 }
804 mpClientInterface->closeInput(input);
805 delete mInputs.valueAt(index);
806 mInputs.removeItem(input);
807 LOGV("releaseInput() exit");
808}
809
810void AudioPolicyManagerBase::initStreamVolume(AudioSystem::stream_type stream,
811 int indexMin,
812 int indexMax)
813{
814 LOGV("initStreamVolume() stream %d, min %d, max %d", stream , indexMin, indexMax);
815 if (indexMin < 0 || indexMin >= indexMax) {
816 LOGW("initStreamVolume() invalid index limits for stream %d, min %d, max %d", stream , indexMin, indexMax);
817 return;
818 }
819 mStreams[stream].mIndexMin = indexMin;
820 mStreams[stream].mIndexMax = indexMax;
821}
822
823status_t AudioPolicyManagerBase::setStreamVolumeIndex(AudioSystem::stream_type stream, int index)
824{
825
826 if ((index < mStreams[stream].mIndexMin) || (index > mStreams[stream].mIndexMax)) {
827 return BAD_VALUE;
828 }
829
830 // Force max volume if stream cannot be muted
831 if (!mStreams[stream].mCanBeMuted) index = mStreams[stream].mIndexMax;
832
833 LOGV("setStreamVolumeIndex() stream %d, index %d", stream, index);
834 mStreams[stream].mIndexCur = index;
835
836 // compute and apply stream volume on all outputs according to connected device
837 status_t status = NO_ERROR;
838 for (size_t i = 0; i < mOutputs.size(); i++) {
839 status_t volStatus = checkAndSetVolume(stream, index, mOutputs.keyAt(i), mOutputs.valueAt(i)->device());
840 if (volStatus != NO_ERROR) {
841 status = volStatus;
842 }
843 }
844 return status;
845}
846
847status_t AudioPolicyManagerBase::getStreamVolumeIndex(AudioSystem::stream_type stream, int *index)
848{
849 if (index == 0) {
850 return BAD_VALUE;
851 }
852 LOGV("getStreamVolumeIndex() stream %d", stream);
853 *index = mStreams[stream].mIndexCur;
854 return NO_ERROR;
855}
856
Eric Laurentde070132010-07-13 04:45:46 -0700857audio_io_handle_t AudioPolicyManagerBase::getOutputForEffect(effect_descriptor_t *desc)
858{
859 LOGV("getOutputForEffect()");
860 // apply simple rule where global effects are attached to the same output as MUSIC streams
861 return getOutput(AudioSystem::MUSIC);
862}
863
864status_t AudioPolicyManagerBase::registerEffect(effect_descriptor_t *desc,
865 audio_io_handle_t output,
866 uint32_t strategy,
867 int session,
868 int id)
869{
870 ssize_t index = mOutputs.indexOfKey(output);
871 if (index < 0) {
872 LOGW("registerEffect() unknown output %d", output);
873 return INVALID_OPERATION;
874 }
875
876 if (mTotalEffectsCpuLoad + desc->cpuLoad > getMaxEffectsCpuLoad()) {
877 LOGW("registerEffect() CPU Load limit exceeded for Fx %s, CPU %f MIPS",
878 desc->name, (float)desc->cpuLoad/10);
879 return INVALID_OPERATION;
880 }
881 if (mTotalEffectsMemory + desc->memoryUsage > getMaxEffectsMemory()) {
882 LOGW("registerEffect() memory limit exceeded for Fx %s, Memory %d KB",
883 desc->name, desc->memoryUsage);
884 return INVALID_OPERATION;
885 }
886 mTotalEffectsCpuLoad += desc->cpuLoad;
887 mTotalEffectsMemory += desc->memoryUsage;
888 LOGV("registerEffect() effect %s, output %d, strategy %d session %d id %d",
889 desc->name, output, strategy, session, id);
890
891 LOGV("registerEffect() CPU %d, memory %d", desc->cpuLoad, desc->memoryUsage);
892 LOGV(" total CPU %d, total memory %d", mTotalEffectsCpuLoad, mTotalEffectsMemory);
893
894 EffectDescriptor *pDesc = new EffectDescriptor();
895 memcpy (&pDesc->mDesc, desc, sizeof(effect_descriptor_t));
896 pDesc->mOutput = output;
897 pDesc->mStrategy = (routing_strategy)strategy;
898 pDesc->mSession = session;
899 mEffects.add(id, pDesc);
900
901 return NO_ERROR;
902}
903
904status_t AudioPolicyManagerBase::unregisterEffect(int id)
905{
906 ssize_t index = mEffects.indexOfKey(id);
907 if (index < 0) {
908 LOGW("unregisterEffect() unknown effect ID %d", id);
909 return INVALID_OPERATION;
910 }
911
912 EffectDescriptor *pDesc = mEffects.valueAt(index);
913
914 if (mTotalEffectsCpuLoad < pDesc->mDesc.cpuLoad) {
915 LOGW("unregisterEffect() CPU load %d too high for total %d",
916 pDesc->mDesc.cpuLoad, mTotalEffectsCpuLoad);
917 pDesc->mDesc.cpuLoad = mTotalEffectsCpuLoad;
918 }
919 mTotalEffectsCpuLoad -= pDesc->mDesc.cpuLoad;
920 if (mTotalEffectsMemory < pDesc->mDesc.memoryUsage) {
921 LOGW("unregisterEffect() memory %d too big for total %d",
922 pDesc->mDesc.memoryUsage, mTotalEffectsMemory);
923 pDesc->mDesc.memoryUsage = mTotalEffectsMemory;
924 }
925 mTotalEffectsMemory -= pDesc->mDesc.memoryUsage;
926 LOGV("unregisterEffect() effect %s, ID %d, CPU %d, memory %d",
927 pDesc->mDesc.name, id, pDesc->mDesc.cpuLoad, pDesc->mDesc.memoryUsage);
928 LOGV(" total CPU %d, total memory %d", mTotalEffectsCpuLoad, mTotalEffectsMemory);
929
930 mEffects.removeItem(id);
931 delete pDesc;
932
933 return NO_ERROR;
934}
935
Mathias Agopian65ab4712010-07-14 17:59:35 -0700936status_t AudioPolicyManagerBase::dump(int fd)
937{
938 const size_t SIZE = 256;
939 char buffer[SIZE];
940 String8 result;
941
942 snprintf(buffer, SIZE, "\nAudioPolicyManager Dump: %p\n", this);
943 result.append(buffer);
944 snprintf(buffer, SIZE, " Hardware Output: %d\n", mHardwareOutput);
945 result.append(buffer);
946#ifdef WITH_A2DP
947 snprintf(buffer, SIZE, " A2DP Output: %d\n", mA2dpOutput);
948 result.append(buffer);
949 snprintf(buffer, SIZE, " Duplicated Output: %d\n", mDuplicatedOutput);
950 result.append(buffer);
951 snprintf(buffer, SIZE, " A2DP device address: %s\n", mA2dpDeviceAddress.string());
952 result.append(buffer);
953#endif
954 snprintf(buffer, SIZE, " SCO device address: %s\n", mScoDeviceAddress.string());
955 result.append(buffer);
956 snprintf(buffer, SIZE, " Output devices: %08x\n", mAvailableOutputDevices);
957 result.append(buffer);
958 snprintf(buffer, SIZE, " Input devices: %08x\n", mAvailableInputDevices);
959 result.append(buffer);
960 snprintf(buffer, SIZE, " Phone state: %d\n", mPhoneState);
961 result.append(buffer);
962 snprintf(buffer, SIZE, " Ringer mode: %d\n", mRingerMode);
963 result.append(buffer);
964 snprintf(buffer, SIZE, " Force use for communications %d\n", mForceUse[AudioSystem::FOR_COMMUNICATION]);
965 result.append(buffer);
966 snprintf(buffer, SIZE, " Force use for media %d\n", mForceUse[AudioSystem::FOR_MEDIA]);
967 result.append(buffer);
968 snprintf(buffer, SIZE, " Force use for record %d\n", mForceUse[AudioSystem::FOR_RECORD]);
969 result.append(buffer);
970 snprintf(buffer, SIZE, " Force use for dock %d\n", mForceUse[AudioSystem::FOR_DOCK]);
971 result.append(buffer);
972 write(fd, result.string(), result.size());
973
974 snprintf(buffer, SIZE, "\nOutputs dump:\n");
975 write(fd, buffer, strlen(buffer));
976 for (size_t i = 0; i < mOutputs.size(); i++) {
977 snprintf(buffer, SIZE, "- Output %d dump:\n", mOutputs.keyAt(i));
978 write(fd, buffer, strlen(buffer));
979 mOutputs.valueAt(i)->dump(fd);
980 }
981
982 snprintf(buffer, SIZE, "\nInputs dump:\n");
983 write(fd, buffer, strlen(buffer));
984 for (size_t i = 0; i < mInputs.size(); i++) {
985 snprintf(buffer, SIZE, "- Input %d dump:\n", mInputs.keyAt(i));
986 write(fd, buffer, strlen(buffer));
987 mInputs.valueAt(i)->dump(fd);
988 }
989
990 snprintf(buffer, SIZE, "\nStreams dump:\n");
991 write(fd, buffer, strlen(buffer));
992 snprintf(buffer, SIZE, " Stream Index Min Index Max Index Cur Can be muted\n");
993 write(fd, buffer, strlen(buffer));
994 for (size_t i = 0; i < AudioSystem::NUM_STREAM_TYPES; i++) {
995 snprintf(buffer, SIZE, " %02d", i);
996 mStreams[i].dump(buffer + 3, SIZE);
997 write(fd, buffer, strlen(buffer));
998 }
999
Eric Laurentde070132010-07-13 04:45:46 -07001000 snprintf(buffer, SIZE, "\nTotal Effects CPU: %f MIPS, Total Effects memory: %d KB\n",
1001 (float)mTotalEffectsCpuLoad/10, mTotalEffectsMemory);
1002 write(fd, buffer, strlen(buffer));
1003
1004 snprintf(buffer, SIZE, "Registered effects:\n");
1005 write(fd, buffer, strlen(buffer));
1006 for (size_t i = 0; i < mEffects.size(); i++) {
1007 snprintf(buffer, SIZE, "- Effect %d dump:\n", mEffects.keyAt(i));
1008 write(fd, buffer, strlen(buffer));
1009 mEffects.valueAt(i)->dump(fd);
1010 }
1011
1012
Mathias Agopian65ab4712010-07-14 17:59:35 -07001013 return NO_ERROR;
1014}
1015
1016// ----------------------------------------------------------------------------
1017// AudioPolicyManagerBase
1018// ----------------------------------------------------------------------------
1019
1020AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clientInterface)
1021 :
1022#ifdef AUDIO_POLICY_TEST
1023 Thread(false),
1024#endif //AUDIO_POLICY_TEST
Mathias Agopian094c96d2010-07-14 18:48:58 -07001025 mPhoneState(AudioSystem::MODE_NORMAL), mRingerMode(0), mMusicStopTime(0), mLimitRingtoneVolume(false),
Eric Laurent8184a572010-07-20 13:37:19 -07001026 mLastVoiceVolume(-1.0f), mTotalEffectsCpuLoad(0), mTotalEffectsMemory(0)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001027{
1028 mpClientInterface = clientInterface;
1029
1030 for (int i = 0; i < AudioSystem::NUM_FORCE_USE; i++) {
1031 mForceUse[i] = AudioSystem::FORCE_NONE;
1032 }
1033
1034 // devices available by default are speaker, ear piece and microphone
1035 mAvailableOutputDevices = AudioSystem::DEVICE_OUT_EARPIECE |
1036 AudioSystem::DEVICE_OUT_SPEAKER;
1037 mAvailableInputDevices = AudioSystem::DEVICE_IN_BUILTIN_MIC;
1038
1039#ifdef WITH_A2DP
1040 mA2dpOutput = 0;
1041 mDuplicatedOutput = 0;
1042 mA2dpDeviceAddress = String8("");
1043#endif
1044 mScoDeviceAddress = String8("");
1045
1046 // open hardware output
1047 AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();
1048 outputDesc->mDevice = (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER;
1049 mHardwareOutput = mpClientInterface->openOutput(&outputDesc->mDevice,
1050 &outputDesc->mSamplingRate,
1051 &outputDesc->mFormat,
1052 &outputDesc->mChannels,
1053 &outputDesc->mLatency,
1054 outputDesc->mFlags);
1055
1056 if (mHardwareOutput == 0) {
1057 LOGE("Failed to initialize hardware output stream, samplingRate: %d, format %d, channels %d",
1058 outputDesc->mSamplingRate, outputDesc->mFormat, outputDesc->mChannels);
1059 } else {
1060 addOutput(mHardwareOutput, outputDesc);
1061 setOutputDevice(mHardwareOutput, (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER, true);
Eric Laurentde070132010-07-13 04:45:46 -07001062 //TODO: configure audio effect output stage here
Mathias Agopian65ab4712010-07-14 17:59:35 -07001063 }
1064
1065 updateDeviceForStrategy();
1066#ifdef AUDIO_POLICY_TEST
1067 AudioParameter outputCmd = AudioParameter();
1068 outputCmd.addInt(String8("set_id"), 0);
1069 mpClientInterface->setParameters(mHardwareOutput, outputCmd.toString());
1070
1071 mTestDevice = AudioSystem::DEVICE_OUT_SPEAKER;
1072 mTestSamplingRate = 44100;
1073 mTestFormat = AudioSystem::PCM_16_BIT;
1074 mTestChannels = AudioSystem::CHANNEL_OUT_STEREO;
1075 mTestLatencyMs = 0;
1076 mCurOutput = 0;
1077 mDirectOutput = false;
1078 for (int i = 0; i < NUM_TEST_OUTPUTS; i++) {
1079 mTestOutputs[i] = 0;
1080 }
1081
1082 const size_t SIZE = 256;
1083 char buffer[SIZE];
1084 snprintf(buffer, SIZE, "AudioPolicyManagerTest");
1085 run(buffer, ANDROID_PRIORITY_AUDIO);
1086#endif //AUDIO_POLICY_TEST
1087}
1088
1089AudioPolicyManagerBase::~AudioPolicyManagerBase()
1090{
1091#ifdef AUDIO_POLICY_TEST
1092 exit();
1093#endif //AUDIO_POLICY_TEST
1094 for (size_t i = 0; i < mOutputs.size(); i++) {
1095 mpClientInterface->closeOutput(mOutputs.keyAt(i));
1096 delete mOutputs.valueAt(i);
1097 }
1098 mOutputs.clear();
1099 for (size_t i = 0; i < mInputs.size(); i++) {
1100 mpClientInterface->closeInput(mInputs.keyAt(i));
1101 delete mInputs.valueAt(i);
1102 }
1103 mInputs.clear();
1104}
1105
1106#ifdef AUDIO_POLICY_TEST
1107bool AudioPolicyManagerBase::threadLoop()
1108{
1109 LOGV("entering threadLoop()");
1110 while (!exitPending())
1111 {
1112 String8 command;
1113 int valueInt;
1114 String8 value;
1115
1116 Mutex::Autolock _l(mLock);
1117 mWaitWorkCV.waitRelative(mLock, milliseconds(50));
1118
1119 command = mpClientInterface->getParameters(0, String8("test_cmd_policy"));
1120 AudioParameter param = AudioParameter(command);
1121
1122 if (param.getInt(String8("test_cmd_policy"), valueInt) == NO_ERROR &&
1123 valueInt != 0) {
1124 LOGV("Test command %s received", command.string());
1125 String8 target;
1126 if (param.get(String8("target"), target) != NO_ERROR) {
1127 target = "Manager";
1128 }
1129 if (param.getInt(String8("test_cmd_policy_output"), valueInt) == NO_ERROR) {
1130 param.remove(String8("test_cmd_policy_output"));
1131 mCurOutput = valueInt;
1132 }
1133 if (param.get(String8("test_cmd_policy_direct"), value) == NO_ERROR) {
1134 param.remove(String8("test_cmd_policy_direct"));
1135 if (value == "false") {
1136 mDirectOutput = false;
1137 } else if (value == "true") {
1138 mDirectOutput = true;
1139 }
1140 }
1141 if (param.getInt(String8("test_cmd_policy_input"), valueInt) == NO_ERROR) {
1142 param.remove(String8("test_cmd_policy_input"));
1143 mTestInput = valueInt;
1144 }
1145
1146 if (param.get(String8("test_cmd_policy_format"), value) == NO_ERROR) {
1147 param.remove(String8("test_cmd_policy_format"));
1148 int format = AudioSystem::INVALID_FORMAT;
1149 if (value == "PCM 16 bits") {
1150 format = AudioSystem::PCM_16_BIT;
1151 } else if (value == "PCM 8 bits") {
1152 format = AudioSystem::PCM_8_BIT;
1153 } else if (value == "Compressed MP3") {
1154 format = AudioSystem::MP3;
1155 }
1156 if (format != AudioSystem::INVALID_FORMAT) {
1157 if (target == "Manager") {
1158 mTestFormat = format;
1159 } else if (mTestOutputs[mCurOutput] != 0) {
1160 AudioParameter outputParam = AudioParameter();
1161 outputParam.addInt(String8("format"), format);
1162 mpClientInterface->setParameters(mTestOutputs[mCurOutput], outputParam.toString());
1163 }
1164 }
1165 }
1166 if (param.get(String8("test_cmd_policy_channels"), value) == NO_ERROR) {
1167 param.remove(String8("test_cmd_policy_channels"));
1168 int channels = 0;
1169
1170 if (value == "Channels Stereo") {
1171 channels = AudioSystem::CHANNEL_OUT_STEREO;
1172 } else if (value == "Channels Mono") {
1173 channels = AudioSystem::CHANNEL_OUT_MONO;
1174 }
1175 if (channels != 0) {
1176 if (target == "Manager") {
1177 mTestChannels = channels;
1178 } else if (mTestOutputs[mCurOutput] != 0) {
1179 AudioParameter outputParam = AudioParameter();
1180 outputParam.addInt(String8("channels"), channels);
1181 mpClientInterface->setParameters(mTestOutputs[mCurOutput], outputParam.toString());
1182 }
1183 }
1184 }
1185 if (param.getInt(String8("test_cmd_policy_sampleRate"), valueInt) == NO_ERROR) {
1186 param.remove(String8("test_cmd_policy_sampleRate"));
1187 if (valueInt >= 0 && valueInt <= 96000) {
1188 int samplingRate = valueInt;
1189 if (target == "Manager") {
1190 mTestSamplingRate = samplingRate;
1191 } else if (mTestOutputs[mCurOutput] != 0) {
1192 AudioParameter outputParam = AudioParameter();
1193 outputParam.addInt(String8("sampling_rate"), samplingRate);
1194 mpClientInterface->setParameters(mTestOutputs[mCurOutput], outputParam.toString());
1195 }
1196 }
1197 }
1198
1199 if (param.get(String8("test_cmd_policy_reopen"), value) == NO_ERROR) {
1200 param.remove(String8("test_cmd_policy_reopen"));
1201
1202 mpClientInterface->closeOutput(mHardwareOutput);
1203 delete mOutputs.valueFor(mHardwareOutput);
1204 mOutputs.removeItem(mHardwareOutput);
1205
1206 AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();
1207 outputDesc->mDevice = (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER;
1208 mHardwareOutput = mpClientInterface->openOutput(&outputDesc->mDevice,
1209 &outputDesc->mSamplingRate,
1210 &outputDesc->mFormat,
1211 &outputDesc->mChannels,
1212 &outputDesc->mLatency,
1213 outputDesc->mFlags);
1214 if (mHardwareOutput == 0) {
1215 LOGE("Failed to reopen hardware output stream, samplingRate: %d, format %d, channels %d",
1216 outputDesc->mSamplingRate, outputDesc->mFormat, outputDesc->mChannels);
1217 } else {
1218 AudioParameter outputCmd = AudioParameter();
1219 outputCmd.addInt(String8("set_id"), 0);
1220 mpClientInterface->setParameters(mHardwareOutput, outputCmd.toString());
1221 addOutput(mHardwareOutput, outputDesc);
1222 }
1223 }
1224
1225
1226 mpClientInterface->setParameters(0, String8("test_cmd_policy="));
1227 }
1228 }
1229 return false;
1230}
1231
1232void AudioPolicyManagerBase::exit()
1233{
1234 {
1235 AutoMutex _l(mLock);
1236 requestExit();
1237 mWaitWorkCV.signal();
1238 }
1239 requestExitAndWait();
1240}
1241
1242int AudioPolicyManagerBase::testOutputIndex(audio_io_handle_t output)
1243{
1244 for (int i = 0; i < NUM_TEST_OUTPUTS; i++) {
1245 if (output == mTestOutputs[i]) return i;
1246 }
1247 return 0;
1248}
1249#endif //AUDIO_POLICY_TEST
1250
1251// ---
1252
1253void AudioPolicyManagerBase::addOutput(audio_io_handle_t id, AudioOutputDescriptor *outputDesc)
1254{
1255 outputDesc->mId = id;
1256 mOutputs.add(id, outputDesc);
1257}
1258
1259
1260#ifdef WITH_A2DP
1261status_t AudioPolicyManagerBase::handleA2dpConnection(AudioSystem::audio_devices device,
1262 const char *device_address)
1263{
1264 // when an A2DP device is connected, open an A2DP and a duplicated output
1265 LOGV("opening A2DP output for device %s", device_address);
1266 AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();
1267 outputDesc->mDevice = device;
1268 mA2dpOutput = mpClientInterface->openOutput(&outputDesc->mDevice,
1269 &outputDesc->mSamplingRate,
1270 &outputDesc->mFormat,
1271 &outputDesc->mChannels,
1272 &outputDesc->mLatency,
1273 outputDesc->mFlags);
1274 if (mA2dpOutput) {
1275 // add A2DP output descriptor
1276 addOutput(mA2dpOutput, outputDesc);
Eric Laurentde070132010-07-13 04:45:46 -07001277
1278 //TODO: configure audio effect output stage here
1279
Mathias Agopian65ab4712010-07-14 17:59:35 -07001280 // set initial stream volume for A2DP device
1281 applyStreamVolumes(mA2dpOutput, device);
1282 if (a2dpUsedForSonification()) {
1283 mDuplicatedOutput = mpClientInterface->openDuplicateOutput(mA2dpOutput, mHardwareOutput);
1284 }
1285 if (mDuplicatedOutput != 0 ||
1286 !a2dpUsedForSonification()) {
1287 // If both A2DP and duplicated outputs are open, send device address to A2DP hardware
1288 // interface
1289 AudioParameter param;
1290 param.add(String8("a2dp_sink_address"), String8(device_address));
1291 mpClientInterface->setParameters(mA2dpOutput, param.toString());
1292 mA2dpDeviceAddress = String8(device_address, MAX_DEVICE_ADDRESS_LEN);
1293
1294 if (a2dpUsedForSonification()) {
1295 // add duplicated output descriptor
1296 AudioOutputDescriptor *dupOutputDesc = new AudioOutputDescriptor();
1297 dupOutputDesc->mOutput1 = mOutputs.valueFor(mHardwareOutput);
1298 dupOutputDesc->mOutput2 = mOutputs.valueFor(mA2dpOutput);
1299 dupOutputDesc->mSamplingRate = outputDesc->mSamplingRate;
1300 dupOutputDesc->mFormat = outputDesc->mFormat;
1301 dupOutputDesc->mChannels = outputDesc->mChannels;
1302 dupOutputDesc->mLatency = outputDesc->mLatency;
1303 addOutput(mDuplicatedOutput, dupOutputDesc);
1304 applyStreamVolumes(mDuplicatedOutput, device);
1305 }
1306 } else {
1307 LOGW("getOutput() could not open duplicated output for %d and %d",
1308 mHardwareOutput, mA2dpOutput);
1309 mpClientInterface->closeOutput(mA2dpOutput);
1310 mOutputs.removeItem(mA2dpOutput);
1311 mA2dpOutput = 0;
1312 delete outputDesc;
1313 return NO_INIT;
1314 }
1315 } else {
1316 LOGW("setDeviceConnectionState() could not open A2DP output for device %x", device);
1317 delete outputDesc;
1318 return NO_INIT;
1319 }
1320 AudioOutputDescriptor *hwOutputDesc = mOutputs.valueFor(mHardwareOutput);
1321
1322 if (mScoDeviceAddress != "") {
1323 // It is normal to suspend twice if we are both in call,
1324 // and have the hardware audio output routed to BT SCO
1325 if (mPhoneState != AudioSystem::MODE_NORMAL) {
1326 mpClientInterface->suspendOutput(mA2dpOutput);
1327 }
1328 if (AudioSystem::isBluetoothScoDevice((AudioSystem::audio_devices)hwOutputDesc->device())) {
1329 mpClientInterface->suspendOutput(mA2dpOutput);
1330 }
1331 }
1332
1333 if (!a2dpUsedForSonification()) {
1334 // mute music on A2DP output if a notification or ringtone is playing
1335 uint32_t refCount = hwOutputDesc->strategyRefCount(STRATEGY_SONIFICATION);
1336 for (uint32_t i = 0; i < refCount; i++) {
1337 setStrategyMute(STRATEGY_MEDIA, true, mA2dpOutput);
1338 }
1339 }
1340 return NO_ERROR;
1341}
1342
1343status_t AudioPolicyManagerBase::handleA2dpDisconnection(AudioSystem::audio_devices device,
1344 const char *device_address)
1345{
1346 if (mA2dpOutput == 0) {
1347 LOGW("setDeviceConnectionState() disconnecting A2DP and no A2DP output!");
1348 return INVALID_OPERATION;
1349 }
1350
1351 if (mA2dpDeviceAddress != device_address) {
1352 LOGW("setDeviceConnectionState() disconnecting unknow A2DP sink address %s", device_address);
1353 return INVALID_OPERATION;
1354 }
1355
1356 // mute media strategy to avoid outputting sound on hardware output while music stream
1357 // is switched from A2DP output and before music is paused by music application
1358 setStrategyMute(STRATEGY_MEDIA, true, mHardwareOutput);
1359 setStrategyMute(STRATEGY_MEDIA, false, mHardwareOutput, MUTE_TIME_MS);
1360
1361 if (!a2dpUsedForSonification()) {
1362 // unmute music on A2DP output if a notification or ringtone is playing
1363 uint32_t refCount = mOutputs.valueFor(mHardwareOutput)->strategyRefCount(STRATEGY_SONIFICATION);
1364 for (uint32_t i = 0; i < refCount; i++) {
1365 setStrategyMute(STRATEGY_MEDIA, false, mA2dpOutput);
1366 }
1367 }
1368 mA2dpDeviceAddress = "";
1369 return NO_ERROR;
1370}
1371
1372void AudioPolicyManagerBase::closeA2dpOutputs()
1373{
Praveen Bharathib235dee2010-10-06 15:23:14 -05001374
Mathias Agopian65ab4712010-07-14 17:59:35 -07001375 LOGV("setDeviceConnectionState() closing A2DP and duplicated output!");
1376
1377 if (mDuplicatedOutput != 0) {
1378 AudioOutputDescriptor *dupOutputDesc = mOutputs.valueFor(mDuplicatedOutput);
1379 AudioOutputDescriptor *hwOutputDesc = mOutputs.valueFor(mHardwareOutput);
1380 // As all active tracks on duplicated output will be deleted,
1381 // and as they were also referenced on hardware output, the reference
1382 // count for their stream type must be adjusted accordingly on
1383 // hardware output.
1384 for (int i = 0; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) {
1385 int refCount = dupOutputDesc->mRefCount[i];
1386 hwOutputDesc->changeRefCount((AudioSystem::stream_type)i,-refCount);
1387 }
1388
1389 mpClientInterface->closeOutput(mDuplicatedOutput);
1390 delete mOutputs.valueFor(mDuplicatedOutput);
1391 mOutputs.removeItem(mDuplicatedOutput);
1392 mDuplicatedOutput = 0;
1393 }
1394 if (mA2dpOutput != 0) {
1395 AudioParameter param;
1396 param.add(String8("closing"), String8("true"));
1397 mpClientInterface->setParameters(mA2dpOutput, param.toString());
Eric Laurentde070132010-07-13 04:45:46 -07001398
Mathias Agopian65ab4712010-07-14 17:59:35 -07001399 mpClientInterface->closeOutput(mA2dpOutput);
1400 delete mOutputs.valueFor(mA2dpOutput);
1401 mOutputs.removeItem(mA2dpOutput);
1402 mA2dpOutput = 0;
1403 }
1404}
1405
Eric Laurentc1c88e22010-08-27 17:10:36 -07001406void AudioPolicyManagerBase::checkOutputForStrategy(routing_strategy strategy)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001407{
1408 uint32_t prevDevice = getDeviceForStrategy(strategy);
1409 uint32_t curDevice = getDeviceForStrategy(strategy, false);
1410 bool a2dpWasUsed = AudioSystem::isA2dpDevice((AudioSystem::audio_devices)(prevDevice & ~AudioSystem::DEVICE_OUT_SPEAKER));
1411 bool a2dpIsUsed = AudioSystem::isA2dpDevice((AudioSystem::audio_devices)(curDevice & ~AudioSystem::DEVICE_OUT_SPEAKER));
Eric Laurentde070132010-07-13 04:45:46 -07001412 audio_io_handle_t srcOutput = 0;
1413 audio_io_handle_t dstOutput = 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001414
1415 if (a2dpWasUsed && !a2dpIsUsed) {
1416 bool dupUsed = a2dpUsedForSonification() && a2dpWasUsed && (AudioSystem::popCount(prevDevice) == 2);
Eric Laurentde070132010-07-13 04:45:46 -07001417 dstOutput = mHardwareOutput;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001418 if (dupUsed) {
Eric Laurentde070132010-07-13 04:45:46 -07001419 LOGV("checkOutputForStrategy() moving strategy %d from duplicated", strategy);
1420 srcOutput = mDuplicatedOutput;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001421 } else {
Eric Laurentde070132010-07-13 04:45:46 -07001422 LOGV("checkOutputForStrategy() moving strategy %d from a2dp", strategy);
1423 srcOutput = mA2dpOutput;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001424 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001425 }
1426 if (a2dpIsUsed && !a2dpWasUsed) {
1427 bool dupUsed = a2dpUsedForSonification() && a2dpIsUsed && (AudioSystem::popCount(curDevice) == 2);
Eric Laurentde070132010-07-13 04:45:46 -07001428 srcOutput = mHardwareOutput;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001429 if (dupUsed) {
Eric Laurentde070132010-07-13 04:45:46 -07001430 LOGV("checkOutputForStrategy() moving strategy %d to duplicated", strategy);
1431 dstOutput = mDuplicatedOutput;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001432 } else {
Eric Laurentde070132010-07-13 04:45:46 -07001433 LOGV("checkOutputForStrategy() moving strategy %d to a2dp", strategy);
1434 dstOutput = mA2dpOutput;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001435 }
Eric Laurentde070132010-07-13 04:45:46 -07001436 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001437
Eric Laurentde070132010-07-13 04:45:46 -07001438 if (srcOutput != 0 && dstOutput != 0) {
1439 // Move effects associated to this strategy from previous output to new output
1440 for (size_t i = 0; i < mEffects.size(); i++) {
1441 EffectDescriptor *desc = mEffects.valueAt(i);
1442 if (desc->mSession != AudioSystem::SESSION_OUTPUT_STAGE &&
1443 desc->mStrategy == strategy &&
1444 desc->mOutput == srcOutput) {
1445 LOGV("checkOutputForStrategy() moving effect %d to output %d", mEffects.keyAt(i), dstOutput);
1446 mpClientInterface->moveEffects(desc->mSession, srcOutput, dstOutput);
1447 desc->mOutput = dstOutput;
1448 }
1449 }
1450 // Move tracks associated to this strategy from previous output to new output
Mathias Agopian65ab4712010-07-14 17:59:35 -07001451 for (int i = 0; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) {
1452 if (getStrategy((AudioSystem::stream_type)i) == strategy) {
Eric Laurentde070132010-07-13 04:45:46 -07001453 mpClientInterface->setStreamOutput((AudioSystem::stream_type)i, dstOutput);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001454 }
1455 }
1456 }
1457}
1458
Eric Laurentc1c88e22010-08-27 17:10:36 -07001459void AudioPolicyManagerBase::checkOutputForAllStrategies()
Mathias Agopian65ab4712010-07-14 17:59:35 -07001460{
Eric Laurentc1c88e22010-08-27 17:10:36 -07001461 checkOutputForStrategy(STRATEGY_PHONE);
1462 checkOutputForStrategy(STRATEGY_SONIFICATION);
1463 checkOutputForStrategy(STRATEGY_MEDIA);
1464 checkOutputForStrategy(STRATEGY_DTMF);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001465}
1466
1467#endif
1468
1469uint32_t AudioPolicyManagerBase::getNewDevice(audio_io_handle_t output, bool fromCache)
1470{
1471 uint32_t device = 0;
1472
1473 AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output);
1474 // check the following by order of priority to request a routing change if necessary:
1475 // 1: we are in call or the strategy phone is active on the hardware output:
1476 // use device for strategy phone
1477 // 2: the strategy sonification is active on the hardware output:
1478 // use device for strategy sonification
1479 // 3: the strategy media is active on the hardware output:
1480 // use device for strategy media
1481 // 4: the strategy DTMF is active on the hardware output:
1482 // use device for strategy DTMF
1483 if (mPhoneState == AudioSystem::MODE_IN_CALL ||
1484 outputDesc->isUsedByStrategy(STRATEGY_PHONE)) {
1485 device = getDeviceForStrategy(STRATEGY_PHONE, fromCache);
1486 } else if (outputDesc->isUsedByStrategy(STRATEGY_SONIFICATION)) {
1487 device = getDeviceForStrategy(STRATEGY_SONIFICATION, fromCache);
1488 } else if (outputDesc->isUsedByStrategy(STRATEGY_MEDIA)) {
1489 device = getDeviceForStrategy(STRATEGY_MEDIA, fromCache);
1490 } else if (outputDesc->isUsedByStrategy(STRATEGY_DTMF)) {
1491 device = getDeviceForStrategy(STRATEGY_DTMF, fromCache);
1492 }
1493
1494 LOGV("getNewDevice() selected device %x", device);
1495 return device;
1496}
1497
Eric Laurentde070132010-07-13 04:45:46 -07001498uint32_t AudioPolicyManagerBase::getStrategyForStream(AudioSystem::stream_type stream) {
1499 return (uint32_t)getStrategy(stream);
1500}
1501
1502AudioPolicyManagerBase::routing_strategy AudioPolicyManagerBase::getStrategy(
1503 AudioSystem::stream_type stream) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001504 // stream to strategy mapping
1505 switch (stream) {
1506 case AudioSystem::VOICE_CALL:
1507 case AudioSystem::BLUETOOTH_SCO:
1508 return STRATEGY_PHONE;
1509 case AudioSystem::RING:
1510 case AudioSystem::NOTIFICATION:
1511 case AudioSystem::ALARM:
1512 case AudioSystem::ENFORCED_AUDIBLE:
1513 return STRATEGY_SONIFICATION;
1514 case AudioSystem::DTMF:
1515 return STRATEGY_DTMF;
1516 default:
1517 LOGE("unknown stream type");
1518 case AudioSystem::SYSTEM:
1519 // NOTE: SYSTEM stream uses MEDIA strategy because muting music and switching outputs
1520 // while key clicks are played produces a poor result
1521 case AudioSystem::TTS:
1522 case AudioSystem::MUSIC:
1523 return STRATEGY_MEDIA;
1524 }
1525}
1526
1527uint32_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy strategy, bool fromCache)
1528{
1529 uint32_t device = 0;
1530
1531 if (fromCache) {
1532 LOGV("getDeviceForStrategy() from cache strategy %d, device %x", strategy, mDeviceForStrategy[strategy]);
1533 return mDeviceForStrategy[strategy];
1534 }
1535
1536 switch (strategy) {
1537 case STRATEGY_DTMF:
1538 if (mPhoneState != AudioSystem::MODE_IN_CALL) {
1539 // when off call, DTMF strategy follows the same rules as MEDIA strategy
1540 device = getDeviceForStrategy(STRATEGY_MEDIA, false);
1541 break;
1542 }
1543 // when in call, DTMF and PHONE strategies follow the same rules
1544 // FALL THROUGH
1545
1546 case STRATEGY_PHONE:
1547 // for phone strategy, we first consider the forced use and then the available devices by order
1548 // of priority
1549 switch (mForceUse[AudioSystem::FOR_COMMUNICATION]) {
1550 case AudioSystem::FORCE_BT_SCO:
1551 if (mPhoneState != AudioSystem::MODE_IN_CALL || strategy != STRATEGY_DTMF) {
1552 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
1553 if (device) break;
1554 }
1555 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
1556 if (device) break;
1557 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO;
1558 if (device) break;
1559 // if SCO device is requested but no SCO device is available, fall back to default case
1560 // FALL THROUGH
1561
1562 default: // FORCE_NONE
1563 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE;
1564 if (device) break;
1565 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET;
1566 if (device) break;
Praveen Bharathib235dee2010-10-06 15:23:14 -05001567 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET;
1568 if (device) break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001569#ifdef WITH_A2DP
1570 // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP
1571 if (mPhoneState != AudioSystem::MODE_IN_CALL) {
1572 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP;
1573 if (device) break;
1574 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
1575 if (device) break;
1576 }
1577#endif
1578 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_EARPIECE;
1579 if (device == 0) {
1580 LOGE("getDeviceForStrategy() earpiece device not found");
1581 }
1582 break;
1583
1584 case AudioSystem::FORCE_SPEAKER:
1585 if (mPhoneState != AudioSystem::MODE_IN_CALL || strategy != STRATEGY_DTMF) {
1586 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
1587 if (device) break;
1588 }
1589#ifdef WITH_A2DP
1590 // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to
1591 // A2DP speaker when forcing to speaker output
1592 if (mPhoneState != AudioSystem::MODE_IN_CALL) {
1593 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
1594 if (device) break;
1595 }
1596#endif
1597 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
1598 if (device == 0) {
1599 LOGE("getDeviceForStrategy() speaker device not found");
1600 }
1601 break;
1602 }
1603 break;
1604
1605 case STRATEGY_SONIFICATION:
1606
1607 // If incall, just select the STRATEGY_PHONE device: The rest of the behavior is handled by
1608 // handleIncallSonification().
1609 if (mPhoneState == AudioSystem::MODE_IN_CALL) {
1610 device = getDeviceForStrategy(STRATEGY_PHONE, false);
1611 break;
1612 }
1613 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
1614 if (device == 0) {
1615 LOGE("getDeviceForStrategy() speaker device not found");
1616 }
1617 // The second device used for sonification is the same as the device used by media strategy
1618 // FALL THROUGH
1619
1620 case STRATEGY_MEDIA: {
1621 uint32_t device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL;
1622 if (device2 == 0) {
1623 device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE;
1624 }
1625 if (device2 == 0) {
1626 device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET;
1627 }
Praveen Bharathib235dee2010-10-06 15:23:14 -05001628 if (device2 == 0) {
1629 device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET;
1630 }
1631 if (device2 == 0) {
1632 device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET;
1633 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001634#ifdef WITH_A2DP
1635 if (mA2dpOutput != 0) {
1636 if (strategy == STRATEGY_SONIFICATION && !a2dpUsedForSonification()) {
1637 break;
1638 }
1639 if (device2 == 0) {
1640 device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP;
1641 }
1642 if (device2 == 0) {
1643 device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
1644 }
1645 if (device2 == 0) {
1646 device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
1647 }
1648 }
1649#endif
1650 if (device2 == 0) {
1651 device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
1652 }
1653
1654 // device is DEVICE_OUT_SPEAKER if we come from case STRATEGY_SONIFICATION, 0 otherwise
1655 device |= device2;
1656 if (device == 0) {
1657 LOGE("getDeviceForStrategy() speaker device not found");
1658 }
1659 } break;
1660
1661 default:
1662 LOGW("getDeviceForStrategy() unknown strategy: %d", strategy);
1663 break;
1664 }
1665
1666 LOGV("getDeviceForStrategy() strategy %d, device %x", strategy, device);
1667 return device;
1668}
1669
1670void AudioPolicyManagerBase::updateDeviceForStrategy()
1671{
1672 for (int i = 0; i < NUM_STRATEGIES; i++) {
1673 mDeviceForStrategy[i] = getDeviceForStrategy((routing_strategy)i, false);
1674 }
1675}
1676
1677void AudioPolicyManagerBase::setOutputDevice(audio_io_handle_t output, uint32_t device, bool force, int delayMs)
1678{
1679 LOGV("setOutputDevice() output %d device %x delayMs %d", output, device, delayMs);
1680 AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output);
1681
1682
1683 if (outputDesc->isDuplicated()) {
1684 setOutputDevice(outputDesc->mOutput1->mId, device, force, delayMs);
1685 setOutputDevice(outputDesc->mOutput2->mId, device, force, delayMs);
1686 return;
1687 }
1688#ifdef WITH_A2DP
1689 // filter devices according to output selected
1690 if (output == mA2dpOutput) {
1691 device &= AudioSystem::DEVICE_OUT_ALL_A2DP;
1692 } else {
1693 device &= ~AudioSystem::DEVICE_OUT_ALL_A2DP;
1694 }
1695#endif
1696
1697 uint32_t prevDevice = (uint32_t)outputDesc->device();
1698 // Do not change the routing if:
1699 // - the requestede device is 0
1700 // - the requested device is the same as current device and force is not specified.
1701 // Doing this check here allows the caller to call setOutputDevice() without conditions
1702 if ((device == 0 || device == prevDevice) && !force) {
1703 LOGV("setOutputDevice() setting same device %x or null device for output %d", device, output);
1704 return;
1705 }
1706
1707 outputDesc->mDevice = device;
1708 // mute media streams if both speaker and headset are selected
1709 if (output == mHardwareOutput && AudioSystem::popCount(device) == 2) {
1710 setStrategyMute(STRATEGY_MEDIA, true, output);
1711 // wait for the PCM output buffers to empty before proceeding with the rest of the command
1712 usleep(outputDesc->mLatency*2*1000);
1713 }
1714#ifdef WITH_A2DP
1715 // suspend A2DP output if SCO device is selected
1716 if (AudioSystem::isBluetoothScoDevice((AudioSystem::audio_devices)device)) {
1717 if (mA2dpOutput != 0) {
1718 mpClientInterface->suspendOutput(mA2dpOutput);
1719 }
1720 }
1721#endif
1722 // do the routing
1723 AudioParameter param = AudioParameter();
1724 param.addInt(String8(AudioParameter::keyRouting), (int)device);
1725 mpClientInterface->setParameters(mHardwareOutput, param.toString(), delayMs);
1726 // update stream volumes according to new device
1727 applyStreamVolumes(output, device, delayMs);
1728
1729#ifdef WITH_A2DP
1730 // if disconnecting SCO device, restore A2DP output
1731 if (AudioSystem::isBluetoothScoDevice((AudioSystem::audio_devices)prevDevice)) {
1732 if (mA2dpOutput != 0) {
1733 LOGV("restore A2DP output");
1734 mpClientInterface->restoreOutput(mA2dpOutput);
1735 }
1736 }
1737#endif
1738 // if changing from a combined headset + speaker route, unmute media streams
1739 if (output == mHardwareOutput && AudioSystem::popCount(prevDevice) == 2) {
1740 setStrategyMute(STRATEGY_MEDIA, false, output, delayMs);
1741 }
1742}
1743
1744uint32_t AudioPolicyManagerBase::getDeviceForInputSource(int inputSource)
1745{
1746 uint32_t device;
1747
1748 switch(inputSource) {
1749 case AUDIO_SOURCE_DEFAULT:
1750 case AUDIO_SOURCE_MIC:
1751 case AUDIO_SOURCE_VOICE_RECOGNITION:
Jean-Michel Trivic643d772010-11-08 18:38:14 -08001752 case AUDIO_SOURCE_VOICE_COMMUNICATION:
Mathias Agopian65ab4712010-07-14 17:59:35 -07001753 if (mForceUse[AudioSystem::FOR_RECORD] == AudioSystem::FORCE_BT_SCO &&
1754 mAvailableInputDevices & AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
1755 device = AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET;
1756 } else if (mAvailableInputDevices & AudioSystem::DEVICE_IN_WIRED_HEADSET) {
1757 device = AudioSystem::DEVICE_IN_WIRED_HEADSET;
1758 } else {
1759 device = AudioSystem::DEVICE_IN_BUILTIN_MIC;
1760 }
1761 break;
1762 case AUDIO_SOURCE_CAMCORDER:
1763 if (hasBackMicrophone()) {
1764 device = AudioSystem::DEVICE_IN_BACK_MIC;
1765 } else {
1766 device = AudioSystem::DEVICE_IN_BUILTIN_MIC;
1767 }
1768 break;
1769 case AUDIO_SOURCE_VOICE_UPLINK:
1770 case AUDIO_SOURCE_VOICE_DOWNLINK:
1771 case AUDIO_SOURCE_VOICE_CALL:
1772 device = AudioSystem::DEVICE_IN_VOICE_CALL;
1773 break;
1774 default:
1775 LOGW("getInput() invalid input source %d", inputSource);
1776 device = 0;
1777 break;
1778 }
1779 LOGV("getDeviceForInputSource()input source %d, device %08x", inputSource, device);
1780 return device;
1781}
1782
1783audio_io_handle_t AudioPolicyManagerBase::getActiveInput()
1784{
1785 for (size_t i = 0; i < mInputs.size(); i++) {
1786 if (mInputs.valueAt(i)->mRefCount > 0) {
1787 return mInputs.keyAt(i);
1788 }
1789 }
1790 return 0;
1791}
1792
1793float AudioPolicyManagerBase::computeVolume(int stream, int index, audio_io_handle_t output, uint32_t device)
1794{
1795 float volume = 1.0;
1796 AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output);
1797 StreamDescriptor &streamDesc = mStreams[stream];
1798
1799 if (device == 0) {
1800 device = outputDesc->device();
1801 }
1802
1803 int volInt = (100 * (index - streamDesc.mIndexMin)) / (streamDesc.mIndexMax - streamDesc.mIndexMin);
1804 volume = AudioSystem::linearToLog(volInt);
1805
1806 // if a headset is connected, apply the following rules to ring tones and notifications
1807 // to avoid sound level bursts in user's ears:
1808 // - always attenuate ring tones and notifications volume by 6dB
1809 // - if music is playing, always limit the volume to current music volume,
1810 // with a minimum threshold at -36dB so that notification is always perceived.
1811 if ((device &
1812 (AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP |
1813 AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
1814 AudioSystem::DEVICE_OUT_WIRED_HEADSET |
Praveen Bharathib235dee2010-10-06 15:23:14 -05001815 AudioSystem::DEVICE_OUT_WIRED_HEADPHONE |
1816 AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET |
1817 AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)) &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07001818 (getStrategy((AudioSystem::stream_type)stream) == STRATEGY_SONIFICATION) &&
1819 streamDesc.mCanBeMuted) {
1820 volume *= SONIFICATION_HEADSET_VOLUME_FACTOR;
1821 // when the phone is ringing we must consider that music could have been paused just before
1822 // by the music application and behave as if music was active if the last music track was
1823 // just stopped
1824 if (outputDesc->mRefCount[AudioSystem::MUSIC] || mLimitRingtoneVolume) {
1825 float musicVol = computeVolume(AudioSystem::MUSIC, mStreams[AudioSystem::MUSIC].mIndexCur, output, device);
1826 float minVol = (musicVol > SONIFICATION_HEADSET_VOLUME_MIN) ? musicVol : SONIFICATION_HEADSET_VOLUME_MIN;
1827 if (volume > minVol) {
1828 volume = minVol;
1829 LOGV("computeVolume limiting volume to %f musicVol %f", minVol, musicVol);
1830 }
1831 }
1832 }
1833
1834 return volume;
1835}
1836
1837status_t AudioPolicyManagerBase::checkAndSetVolume(int stream, int index, audio_io_handle_t output, uint32_t device, int delayMs, bool force)
1838{
1839
1840 // do not change actual stream volume if the stream is muted
1841 if (mOutputs.valueFor(output)->mMuteCount[stream] != 0) {
1842 LOGV("checkAndSetVolume() stream %d muted count %d", stream, mOutputs.valueFor(output)->mMuteCount[stream]);
1843 return NO_ERROR;
1844 }
1845
1846 // do not change in call volume if bluetooth is connected and vice versa
1847 if ((stream == AudioSystem::VOICE_CALL && mForceUse[AudioSystem::FOR_COMMUNICATION] == AudioSystem::FORCE_BT_SCO) ||
1848 (stream == AudioSystem::BLUETOOTH_SCO && mForceUse[AudioSystem::FOR_COMMUNICATION] != AudioSystem::FORCE_BT_SCO)) {
1849 LOGV("checkAndSetVolume() cannot set stream %d volume with force use = %d for comm",
1850 stream, mForceUse[AudioSystem::FOR_COMMUNICATION]);
1851 return INVALID_OPERATION;
1852 }
1853
1854 float volume = computeVolume(stream, index, output, device);
Mathias Agopian094c96d2010-07-14 18:48:58 -07001855 // We actually change the volume if:
1856 // - the float value returned by computeVolume() changed
1857 // - the force flag is set
1858 if (volume != mOutputs.valueFor(output)->mCurVolume[stream] ||
1859 force) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001860 mOutputs.valueFor(output)->mCurVolume[stream] = volume;
1861 LOGV("setStreamVolume() for output %d stream %d, volume %f, delay %d", output, stream, volume, delayMs);
1862 if (stream == AudioSystem::VOICE_CALL ||
1863 stream == AudioSystem::DTMF ||
1864 stream == AudioSystem::BLUETOOTH_SCO) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001865 // offset value to reflect actual hardware volume that never reaches 0
1866 // 1% corresponds roughly to first step in VOICE_CALL stream volume setting (see AudioService.java)
1867 volume = 0.01 + 0.99 * volume;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001868 }
1869 mpClientInterface->setStreamVolume((AudioSystem::stream_type)stream, volume, output, delayMs);
1870 }
1871
Mathias Agopian094c96d2010-07-14 18:48:58 -07001872 if (stream == AudioSystem::VOICE_CALL ||
1873 stream == AudioSystem::BLUETOOTH_SCO) {
1874 float voiceVolume;
1875 // Force voice volume to max for bluetooth SCO as volume is managed by the headset
1876 if (stream == AudioSystem::VOICE_CALL) {
1877 voiceVolume = (float)index/(float)mStreams[stream].mIndexMax;
1878 } else {
1879 voiceVolume = 1.0;
1880 }
1881 if (voiceVolume != mLastVoiceVolume && output == mHardwareOutput) {
1882 mpClientInterface->setVoiceVolume(voiceVolume, delayMs);
1883 mLastVoiceVolume = voiceVolume;
1884 }
1885 }
1886
Mathias Agopian65ab4712010-07-14 17:59:35 -07001887 return NO_ERROR;
1888}
1889
1890void AudioPolicyManagerBase::applyStreamVolumes(audio_io_handle_t output, uint32_t device, int delayMs)
1891{
1892 LOGV("applyStreamVolumes() for output %d and device %x", output, device);
1893
1894 for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
1895 checkAndSetVolume(stream, mStreams[stream].mIndexCur, output, device, delayMs);
1896 }
1897}
1898
1899void AudioPolicyManagerBase::setStrategyMute(routing_strategy strategy, bool on, audio_io_handle_t output, int delayMs)
1900{
1901 LOGV("setStrategyMute() strategy %d, mute %d, output %d", strategy, on, output);
1902 for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
1903 if (getStrategy((AudioSystem::stream_type)stream) == strategy) {
1904 setStreamMute(stream, on, output, delayMs);
1905 }
1906 }
1907}
1908
1909void AudioPolicyManagerBase::setStreamMute(int stream, bool on, audio_io_handle_t output, int delayMs)
1910{
1911 StreamDescriptor &streamDesc = mStreams[stream];
1912 AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output);
1913
1914 LOGV("setStreamMute() stream %d, mute %d, output %d, mMuteCount %d", stream, on, output, outputDesc->mMuteCount[stream]);
1915
1916 if (on) {
1917 if (outputDesc->mMuteCount[stream] == 0) {
1918 if (streamDesc.mCanBeMuted) {
1919 checkAndSetVolume(stream, 0, output, outputDesc->device(), delayMs);
1920 }
1921 }
1922 // increment mMuteCount after calling checkAndSetVolume() so that volume change is not ignored
1923 outputDesc->mMuteCount[stream]++;
1924 } else {
1925 if (outputDesc->mMuteCount[stream] == 0) {
1926 LOGW("setStreamMute() unmuting non muted stream!");
1927 return;
1928 }
1929 if (--outputDesc->mMuteCount[stream] == 0) {
1930 checkAndSetVolume(stream, streamDesc.mIndexCur, output, outputDesc->device(), delayMs);
1931 }
1932 }
1933}
1934
1935void AudioPolicyManagerBase::handleIncallSonification(int stream, bool starting, bool stateChange)
1936{
1937 // if the stream pertains to sonification strategy and we are in call we must
1938 // mute the stream if it is low visibility. If it is high visibility, we must play a tone
1939 // in the device used for phone strategy and play the tone if the selected device does not
1940 // interfere with the device used for phone strategy
1941 // if stateChange is true, we are called from setPhoneState() and we must mute or unmute as
1942 // many times as there are active tracks on the output
1943
1944 if (getStrategy((AudioSystem::stream_type)stream) == STRATEGY_SONIFICATION) {
1945 AudioOutputDescriptor *outputDesc = mOutputs.valueFor(mHardwareOutput);
1946 LOGV("handleIncallSonification() stream %d starting %d device %x stateChange %d",
1947 stream, starting, outputDesc->mDevice, stateChange);
1948 if (outputDesc->mRefCount[stream]) {
1949 int muteCount = 1;
1950 if (stateChange) {
1951 muteCount = outputDesc->mRefCount[stream];
1952 }
1953 if (AudioSystem::isLowVisibility((AudioSystem::stream_type)stream)) {
1954 LOGV("handleIncallSonification() low visibility, muteCount %d", muteCount);
1955 for (int i = 0; i < muteCount; i++) {
1956 setStreamMute(stream, starting, mHardwareOutput);
1957 }
1958 } else {
1959 LOGV("handleIncallSonification() high visibility");
1960 if (outputDesc->device() & getDeviceForStrategy(STRATEGY_PHONE)) {
1961 LOGV("handleIncallSonification() high visibility muted, muteCount %d", muteCount);
1962 for (int i = 0; i < muteCount; i++) {
1963 setStreamMute(stream, starting, mHardwareOutput);
1964 }
1965 }
1966 if (starting) {
1967 mpClientInterface->startTone(ToneGenerator::TONE_SUP_CALL_WAITING, AudioSystem::VOICE_CALL);
1968 } else {
1969 mpClientInterface->stopTone();
1970 }
1971 }
1972 }
1973 }
1974}
1975
1976bool AudioPolicyManagerBase::needsDirectOuput(AudioSystem::stream_type stream,
1977 uint32_t samplingRate,
1978 uint32_t format,
1979 uint32_t channels,
1980 AudioSystem::output_flags flags,
1981 uint32_t device)
1982{
1983 return ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) ||
1984 (format !=0 && !AudioSystem::isLinearPCM(format)));
1985}
1986
Eric Laurentde070132010-07-13 04:45:46 -07001987uint32_t AudioPolicyManagerBase::getMaxEffectsCpuLoad()
1988{
1989 return MAX_EFFECTS_CPU_LOAD;
1990}
1991
1992uint32_t AudioPolicyManagerBase::getMaxEffectsMemory()
1993{
1994 return MAX_EFFECTS_MEMORY;
1995}
1996
Mathias Agopian65ab4712010-07-14 17:59:35 -07001997// --- AudioOutputDescriptor class implementation
1998
1999AudioPolicyManagerBase::AudioOutputDescriptor::AudioOutputDescriptor()
2000 : mId(0), mSamplingRate(0), mFormat(0), mChannels(0), mLatency(0),
2001 mFlags((AudioSystem::output_flags)0), mDevice(0), mOutput1(0), mOutput2(0)
2002{
2003 // clear usage count for all stream types
2004 for (int i = 0; i < AudioSystem::NUM_STREAM_TYPES; i++) {
2005 mRefCount[i] = 0;
2006 mCurVolume[i] = -1.0;
2007 mMuteCount[i] = 0;
2008 }
2009}
2010
2011uint32_t AudioPolicyManagerBase::AudioOutputDescriptor::device()
2012{
2013 uint32_t device = 0;
2014 if (isDuplicated()) {
2015 device = mOutput1->mDevice | mOutput2->mDevice;
2016 } else {
2017 device = mDevice;
2018 }
2019 return device;
2020}
2021
2022void AudioPolicyManagerBase::AudioOutputDescriptor::changeRefCount(AudioSystem::stream_type stream, int delta)
2023{
2024 // forward usage count change to attached outputs
2025 if (isDuplicated()) {
2026 mOutput1->changeRefCount(stream, delta);
2027 mOutput2->changeRefCount(stream, delta);
2028 }
2029 if ((delta + (int)mRefCount[stream]) < 0) {
2030 LOGW("changeRefCount() invalid delta %d for stream %d, refCount %d", delta, stream, mRefCount[stream]);
2031 mRefCount[stream] = 0;
2032 return;
2033 }
2034 mRefCount[stream] += delta;
2035 LOGV("changeRefCount() stream %d, count %d", stream, mRefCount[stream]);
2036}
2037
2038uint32_t AudioPolicyManagerBase::AudioOutputDescriptor::refCount()
2039{
2040 uint32_t refcount = 0;
2041 for (int i = 0; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) {
2042 refcount += mRefCount[i];
2043 }
2044 return refcount;
2045}
2046
2047uint32_t AudioPolicyManagerBase::AudioOutputDescriptor::strategyRefCount(routing_strategy strategy)
2048{
2049 uint32_t refCount = 0;
2050 for (int i = 0; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) {
2051 if (getStrategy((AudioSystem::stream_type)i) == strategy) {
2052 refCount += mRefCount[i];
2053 }
2054 }
2055 return refCount;
2056}
2057
2058
2059status_t AudioPolicyManagerBase::AudioOutputDescriptor::dump(int fd)
2060{
2061 const size_t SIZE = 256;
2062 char buffer[SIZE];
2063 String8 result;
2064
2065 snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate);
2066 result.append(buffer);
2067 snprintf(buffer, SIZE, " Format: %d\n", mFormat);
2068 result.append(buffer);
2069 snprintf(buffer, SIZE, " Channels: %08x\n", mChannels);
2070 result.append(buffer);
2071 snprintf(buffer, SIZE, " Latency: %d\n", mLatency);
2072 result.append(buffer);
2073 snprintf(buffer, SIZE, " Flags %08x\n", mFlags);
2074 result.append(buffer);
2075 snprintf(buffer, SIZE, " Devices %08x\n", device());
2076 result.append(buffer);
2077 snprintf(buffer, SIZE, " Stream volume refCount muteCount\n");
2078 result.append(buffer);
2079 for (int i = 0; i < AudioSystem::NUM_STREAM_TYPES; i++) {
2080 snprintf(buffer, SIZE, " %02d %.03f %02d %02d\n", i, mCurVolume[i], mRefCount[i], mMuteCount[i]);
2081 result.append(buffer);
2082 }
2083 write(fd, result.string(), result.size());
2084
2085 return NO_ERROR;
2086}
2087
2088// --- AudioInputDescriptor class implementation
2089
2090AudioPolicyManagerBase::AudioInputDescriptor::AudioInputDescriptor()
2091 : mSamplingRate(0), mFormat(0), mChannels(0),
2092 mAcoustics((AudioSystem::audio_in_acoustics)0), mDevice(0), mRefCount(0)
2093{
2094}
2095
2096status_t AudioPolicyManagerBase::AudioInputDescriptor::dump(int fd)
2097{
2098 const size_t SIZE = 256;
2099 char buffer[SIZE];
2100 String8 result;
2101
2102 snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate);
2103 result.append(buffer);
2104 snprintf(buffer, SIZE, " Format: %d\n", mFormat);
2105 result.append(buffer);
2106 snprintf(buffer, SIZE, " Channels: %08x\n", mChannels);
2107 result.append(buffer);
2108 snprintf(buffer, SIZE, " Acoustics %08x\n", mAcoustics);
2109 result.append(buffer);
2110 snprintf(buffer, SIZE, " Devices %08x\n", mDevice);
2111 result.append(buffer);
2112 snprintf(buffer, SIZE, " Ref Count %d\n", mRefCount);
2113 result.append(buffer);
2114 write(fd, result.string(), result.size());
2115
2116 return NO_ERROR;
2117}
2118
2119// --- StreamDescriptor class implementation
2120
2121void AudioPolicyManagerBase::StreamDescriptor::dump(char* buffer, size_t size)
2122{
2123 snprintf(buffer, size, " %02d %02d %02d %d\n",
2124 mIndexMin,
2125 mIndexMax,
2126 mIndexCur,
2127 mCanBeMuted);
2128}
2129
Eric Laurentde070132010-07-13 04:45:46 -07002130// --- EffectDescriptor class implementation
2131
2132status_t AudioPolicyManagerBase::EffectDescriptor::dump(int fd)
2133{
2134 const size_t SIZE = 256;
2135 char buffer[SIZE];
2136 String8 result;
2137
2138 snprintf(buffer, SIZE, " Output: %d\n", mOutput);
2139 result.append(buffer);
2140 snprintf(buffer, SIZE, " Strategy: %d\n", mStrategy);
2141 result.append(buffer);
2142 snprintf(buffer, SIZE, " Session: %d\n", mSession);
2143 result.append(buffer);
2144 snprintf(buffer, SIZE, " Name: %s\n", mDesc.name);
2145 result.append(buffer);
2146 write(fd, result.string(), result.size());
2147
2148 return NO_ERROR;
2149}
2150
2151
Mathias Agopian65ab4712010-07-14 17:59:35 -07002152
2153}; // namespace android