blob: b17584ab8213546b9ee81ad5cd0559c2a293fed8 [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
Jean-Michel Trivi56ecd202010-11-09 14:06:52 -0800763 param.addInt(String8(AudioParameter::keyInputSource), (int)inputDesc->mInputSource);
764 LOGV("AudioPolicyManager::startInput() input source = %d", inputDesc->mInputSource);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700765
766 mpClientInterface->setParameters(input, param.toString());
767
768 inputDesc->mRefCount = 1;
769 return NO_ERROR;
770}
771
772status_t AudioPolicyManagerBase::stopInput(audio_io_handle_t input)
773{
774 LOGV("stopInput() input %d", input);
775 ssize_t index = mInputs.indexOfKey(input);
776 if (index < 0) {
777 LOGW("stopInput() unknow input %d", input);
778 return BAD_VALUE;
779 }
780 AudioInputDescriptor *inputDesc = mInputs.valueAt(index);
781
782 if (inputDesc->mRefCount == 0) {
783 LOGW("stopInput() input %d already stopped", input);
784 return INVALID_OPERATION;
785 } else {
786 AudioParameter param = AudioParameter();
787 param.addInt(String8(AudioParameter::keyRouting), 0);
788 mpClientInterface->setParameters(input, param.toString());
789 inputDesc->mRefCount = 0;
790 return NO_ERROR;
791 }
792}
793
794void AudioPolicyManagerBase::releaseInput(audio_io_handle_t input)
795{
796 LOGV("releaseInput() %d", input);
797 ssize_t index = mInputs.indexOfKey(input);
798 if (index < 0) {
799 LOGW("releaseInput() releasing unknown input %d", input);
800 return;
801 }
802 mpClientInterface->closeInput(input);
803 delete mInputs.valueAt(index);
804 mInputs.removeItem(input);
805 LOGV("releaseInput() exit");
806}
807
808void AudioPolicyManagerBase::initStreamVolume(AudioSystem::stream_type stream,
809 int indexMin,
810 int indexMax)
811{
812 LOGV("initStreamVolume() stream %d, min %d, max %d", stream , indexMin, indexMax);
813 if (indexMin < 0 || indexMin >= indexMax) {
814 LOGW("initStreamVolume() invalid index limits for stream %d, min %d, max %d", stream , indexMin, indexMax);
815 return;
816 }
817 mStreams[stream].mIndexMin = indexMin;
818 mStreams[stream].mIndexMax = indexMax;
819}
820
821status_t AudioPolicyManagerBase::setStreamVolumeIndex(AudioSystem::stream_type stream, int index)
822{
823
824 if ((index < mStreams[stream].mIndexMin) || (index > mStreams[stream].mIndexMax)) {
825 return BAD_VALUE;
826 }
827
828 // Force max volume if stream cannot be muted
829 if (!mStreams[stream].mCanBeMuted) index = mStreams[stream].mIndexMax;
830
831 LOGV("setStreamVolumeIndex() stream %d, index %d", stream, index);
832 mStreams[stream].mIndexCur = index;
833
834 // compute and apply stream volume on all outputs according to connected device
835 status_t status = NO_ERROR;
836 for (size_t i = 0; i < mOutputs.size(); i++) {
837 status_t volStatus = checkAndSetVolume(stream, index, mOutputs.keyAt(i), mOutputs.valueAt(i)->device());
838 if (volStatus != NO_ERROR) {
839 status = volStatus;
840 }
841 }
842 return status;
843}
844
845status_t AudioPolicyManagerBase::getStreamVolumeIndex(AudioSystem::stream_type stream, int *index)
846{
847 if (index == 0) {
848 return BAD_VALUE;
849 }
850 LOGV("getStreamVolumeIndex() stream %d", stream);
851 *index = mStreams[stream].mIndexCur;
852 return NO_ERROR;
853}
854
Eric Laurentde070132010-07-13 04:45:46 -0700855audio_io_handle_t AudioPolicyManagerBase::getOutputForEffect(effect_descriptor_t *desc)
856{
857 LOGV("getOutputForEffect()");
858 // apply simple rule where global effects are attached to the same output as MUSIC streams
859 return getOutput(AudioSystem::MUSIC);
860}
861
862status_t AudioPolicyManagerBase::registerEffect(effect_descriptor_t *desc,
863 audio_io_handle_t output,
864 uint32_t strategy,
865 int session,
866 int id)
867{
868 ssize_t index = mOutputs.indexOfKey(output);
869 if (index < 0) {
870 LOGW("registerEffect() unknown output %d", output);
871 return INVALID_OPERATION;
872 }
873
874 if (mTotalEffectsCpuLoad + desc->cpuLoad > getMaxEffectsCpuLoad()) {
875 LOGW("registerEffect() CPU Load limit exceeded for Fx %s, CPU %f MIPS",
876 desc->name, (float)desc->cpuLoad/10);
877 return INVALID_OPERATION;
878 }
879 if (mTotalEffectsMemory + desc->memoryUsage > getMaxEffectsMemory()) {
880 LOGW("registerEffect() memory limit exceeded for Fx %s, Memory %d KB",
881 desc->name, desc->memoryUsage);
882 return INVALID_OPERATION;
883 }
884 mTotalEffectsCpuLoad += desc->cpuLoad;
885 mTotalEffectsMemory += desc->memoryUsage;
886 LOGV("registerEffect() effect %s, output %d, strategy %d session %d id %d",
887 desc->name, output, strategy, session, id);
888
889 LOGV("registerEffect() CPU %d, memory %d", desc->cpuLoad, desc->memoryUsage);
890 LOGV(" total CPU %d, total memory %d", mTotalEffectsCpuLoad, mTotalEffectsMemory);
891
892 EffectDescriptor *pDesc = new EffectDescriptor();
893 memcpy (&pDesc->mDesc, desc, sizeof(effect_descriptor_t));
894 pDesc->mOutput = output;
895 pDesc->mStrategy = (routing_strategy)strategy;
896 pDesc->mSession = session;
897 mEffects.add(id, pDesc);
898
899 return NO_ERROR;
900}
901
902status_t AudioPolicyManagerBase::unregisterEffect(int id)
903{
904 ssize_t index = mEffects.indexOfKey(id);
905 if (index < 0) {
906 LOGW("unregisterEffect() unknown effect ID %d", id);
907 return INVALID_OPERATION;
908 }
909
910 EffectDescriptor *pDesc = mEffects.valueAt(index);
911
912 if (mTotalEffectsCpuLoad < pDesc->mDesc.cpuLoad) {
913 LOGW("unregisterEffect() CPU load %d too high for total %d",
914 pDesc->mDesc.cpuLoad, mTotalEffectsCpuLoad);
915 pDesc->mDesc.cpuLoad = mTotalEffectsCpuLoad;
916 }
917 mTotalEffectsCpuLoad -= pDesc->mDesc.cpuLoad;
918 if (mTotalEffectsMemory < pDesc->mDesc.memoryUsage) {
919 LOGW("unregisterEffect() memory %d too big for total %d",
920 pDesc->mDesc.memoryUsage, mTotalEffectsMemory);
921 pDesc->mDesc.memoryUsage = mTotalEffectsMemory;
922 }
923 mTotalEffectsMemory -= pDesc->mDesc.memoryUsage;
924 LOGV("unregisterEffect() effect %s, ID %d, CPU %d, memory %d",
925 pDesc->mDesc.name, id, pDesc->mDesc.cpuLoad, pDesc->mDesc.memoryUsage);
926 LOGV(" total CPU %d, total memory %d", mTotalEffectsCpuLoad, mTotalEffectsMemory);
927
928 mEffects.removeItem(id);
929 delete pDesc;
930
931 return NO_ERROR;
932}
933
Mathias Agopian65ab4712010-07-14 17:59:35 -0700934status_t AudioPolicyManagerBase::dump(int fd)
935{
936 const size_t SIZE = 256;
937 char buffer[SIZE];
938 String8 result;
939
940 snprintf(buffer, SIZE, "\nAudioPolicyManager Dump: %p\n", this);
941 result.append(buffer);
942 snprintf(buffer, SIZE, " Hardware Output: %d\n", mHardwareOutput);
943 result.append(buffer);
944#ifdef WITH_A2DP
945 snprintf(buffer, SIZE, " A2DP Output: %d\n", mA2dpOutput);
946 result.append(buffer);
947 snprintf(buffer, SIZE, " Duplicated Output: %d\n", mDuplicatedOutput);
948 result.append(buffer);
949 snprintf(buffer, SIZE, " A2DP device address: %s\n", mA2dpDeviceAddress.string());
950 result.append(buffer);
951#endif
952 snprintf(buffer, SIZE, " SCO device address: %s\n", mScoDeviceAddress.string());
953 result.append(buffer);
954 snprintf(buffer, SIZE, " Output devices: %08x\n", mAvailableOutputDevices);
955 result.append(buffer);
956 snprintf(buffer, SIZE, " Input devices: %08x\n", mAvailableInputDevices);
957 result.append(buffer);
958 snprintf(buffer, SIZE, " Phone state: %d\n", mPhoneState);
959 result.append(buffer);
960 snprintf(buffer, SIZE, " Ringer mode: %d\n", mRingerMode);
961 result.append(buffer);
962 snprintf(buffer, SIZE, " Force use for communications %d\n", mForceUse[AudioSystem::FOR_COMMUNICATION]);
963 result.append(buffer);
964 snprintf(buffer, SIZE, " Force use for media %d\n", mForceUse[AudioSystem::FOR_MEDIA]);
965 result.append(buffer);
966 snprintf(buffer, SIZE, " Force use for record %d\n", mForceUse[AudioSystem::FOR_RECORD]);
967 result.append(buffer);
968 snprintf(buffer, SIZE, " Force use for dock %d\n", mForceUse[AudioSystem::FOR_DOCK]);
969 result.append(buffer);
970 write(fd, result.string(), result.size());
971
972 snprintf(buffer, SIZE, "\nOutputs dump:\n");
973 write(fd, buffer, strlen(buffer));
974 for (size_t i = 0; i < mOutputs.size(); i++) {
975 snprintf(buffer, SIZE, "- Output %d dump:\n", mOutputs.keyAt(i));
976 write(fd, buffer, strlen(buffer));
977 mOutputs.valueAt(i)->dump(fd);
978 }
979
980 snprintf(buffer, SIZE, "\nInputs dump:\n");
981 write(fd, buffer, strlen(buffer));
982 for (size_t i = 0; i < mInputs.size(); i++) {
983 snprintf(buffer, SIZE, "- Input %d dump:\n", mInputs.keyAt(i));
984 write(fd, buffer, strlen(buffer));
985 mInputs.valueAt(i)->dump(fd);
986 }
987
988 snprintf(buffer, SIZE, "\nStreams dump:\n");
989 write(fd, buffer, strlen(buffer));
990 snprintf(buffer, SIZE, " Stream Index Min Index Max Index Cur Can be muted\n");
991 write(fd, buffer, strlen(buffer));
992 for (size_t i = 0; i < AudioSystem::NUM_STREAM_TYPES; i++) {
993 snprintf(buffer, SIZE, " %02d", i);
994 mStreams[i].dump(buffer + 3, SIZE);
995 write(fd, buffer, strlen(buffer));
996 }
997
Eric Laurentde070132010-07-13 04:45:46 -0700998 snprintf(buffer, SIZE, "\nTotal Effects CPU: %f MIPS, Total Effects memory: %d KB\n",
999 (float)mTotalEffectsCpuLoad/10, mTotalEffectsMemory);
1000 write(fd, buffer, strlen(buffer));
1001
1002 snprintf(buffer, SIZE, "Registered effects:\n");
1003 write(fd, buffer, strlen(buffer));
1004 for (size_t i = 0; i < mEffects.size(); i++) {
1005 snprintf(buffer, SIZE, "- Effect %d dump:\n", mEffects.keyAt(i));
1006 write(fd, buffer, strlen(buffer));
1007 mEffects.valueAt(i)->dump(fd);
1008 }
1009
1010
Mathias Agopian65ab4712010-07-14 17:59:35 -07001011 return NO_ERROR;
1012}
1013
1014// ----------------------------------------------------------------------------
1015// AudioPolicyManagerBase
1016// ----------------------------------------------------------------------------
1017
1018AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clientInterface)
1019 :
1020#ifdef AUDIO_POLICY_TEST
1021 Thread(false),
1022#endif //AUDIO_POLICY_TEST
Mathias Agopian094c96d2010-07-14 18:48:58 -07001023 mPhoneState(AudioSystem::MODE_NORMAL), mRingerMode(0), mMusicStopTime(0), mLimitRingtoneVolume(false),
Eric Laurent8184a572010-07-20 13:37:19 -07001024 mLastVoiceVolume(-1.0f), mTotalEffectsCpuLoad(0), mTotalEffectsMemory(0)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001025{
1026 mpClientInterface = clientInterface;
1027
1028 for (int i = 0; i < AudioSystem::NUM_FORCE_USE; i++) {
1029 mForceUse[i] = AudioSystem::FORCE_NONE;
1030 }
1031
1032 // devices available by default are speaker, ear piece and microphone
1033 mAvailableOutputDevices = AudioSystem::DEVICE_OUT_EARPIECE |
1034 AudioSystem::DEVICE_OUT_SPEAKER;
1035 mAvailableInputDevices = AudioSystem::DEVICE_IN_BUILTIN_MIC;
1036
1037#ifdef WITH_A2DP
1038 mA2dpOutput = 0;
1039 mDuplicatedOutput = 0;
1040 mA2dpDeviceAddress = String8("");
1041#endif
1042 mScoDeviceAddress = String8("");
1043
1044 // open hardware output
1045 AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();
1046 outputDesc->mDevice = (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER;
1047 mHardwareOutput = mpClientInterface->openOutput(&outputDesc->mDevice,
1048 &outputDesc->mSamplingRate,
1049 &outputDesc->mFormat,
1050 &outputDesc->mChannels,
1051 &outputDesc->mLatency,
1052 outputDesc->mFlags);
1053
1054 if (mHardwareOutput == 0) {
1055 LOGE("Failed to initialize hardware output stream, samplingRate: %d, format %d, channels %d",
1056 outputDesc->mSamplingRate, outputDesc->mFormat, outputDesc->mChannels);
1057 } else {
1058 addOutput(mHardwareOutput, outputDesc);
1059 setOutputDevice(mHardwareOutput, (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER, true);
Eric Laurentde070132010-07-13 04:45:46 -07001060 //TODO: configure audio effect output stage here
Mathias Agopian65ab4712010-07-14 17:59:35 -07001061 }
1062
1063 updateDeviceForStrategy();
1064#ifdef AUDIO_POLICY_TEST
1065 AudioParameter outputCmd = AudioParameter();
1066 outputCmd.addInt(String8("set_id"), 0);
1067 mpClientInterface->setParameters(mHardwareOutput, outputCmd.toString());
1068
1069 mTestDevice = AudioSystem::DEVICE_OUT_SPEAKER;
1070 mTestSamplingRate = 44100;
1071 mTestFormat = AudioSystem::PCM_16_BIT;
1072 mTestChannels = AudioSystem::CHANNEL_OUT_STEREO;
1073 mTestLatencyMs = 0;
1074 mCurOutput = 0;
1075 mDirectOutput = false;
1076 for (int i = 0; i < NUM_TEST_OUTPUTS; i++) {
1077 mTestOutputs[i] = 0;
1078 }
1079
1080 const size_t SIZE = 256;
1081 char buffer[SIZE];
1082 snprintf(buffer, SIZE, "AudioPolicyManagerTest");
1083 run(buffer, ANDROID_PRIORITY_AUDIO);
1084#endif //AUDIO_POLICY_TEST
1085}
1086
1087AudioPolicyManagerBase::~AudioPolicyManagerBase()
1088{
1089#ifdef AUDIO_POLICY_TEST
1090 exit();
1091#endif //AUDIO_POLICY_TEST
1092 for (size_t i = 0; i < mOutputs.size(); i++) {
1093 mpClientInterface->closeOutput(mOutputs.keyAt(i));
1094 delete mOutputs.valueAt(i);
1095 }
1096 mOutputs.clear();
1097 for (size_t i = 0; i < mInputs.size(); i++) {
1098 mpClientInterface->closeInput(mInputs.keyAt(i));
1099 delete mInputs.valueAt(i);
1100 }
1101 mInputs.clear();
1102}
1103
1104#ifdef AUDIO_POLICY_TEST
1105bool AudioPolicyManagerBase::threadLoop()
1106{
1107 LOGV("entering threadLoop()");
1108 while (!exitPending())
1109 {
1110 String8 command;
1111 int valueInt;
1112 String8 value;
1113
1114 Mutex::Autolock _l(mLock);
1115 mWaitWorkCV.waitRelative(mLock, milliseconds(50));
1116
1117 command = mpClientInterface->getParameters(0, String8("test_cmd_policy"));
1118 AudioParameter param = AudioParameter(command);
1119
1120 if (param.getInt(String8("test_cmd_policy"), valueInt) == NO_ERROR &&
1121 valueInt != 0) {
1122 LOGV("Test command %s received", command.string());
1123 String8 target;
1124 if (param.get(String8("target"), target) != NO_ERROR) {
1125 target = "Manager";
1126 }
1127 if (param.getInt(String8("test_cmd_policy_output"), valueInt) == NO_ERROR) {
1128 param.remove(String8("test_cmd_policy_output"));
1129 mCurOutput = valueInt;
1130 }
1131 if (param.get(String8("test_cmd_policy_direct"), value) == NO_ERROR) {
1132 param.remove(String8("test_cmd_policy_direct"));
1133 if (value == "false") {
1134 mDirectOutput = false;
1135 } else if (value == "true") {
1136 mDirectOutput = true;
1137 }
1138 }
1139 if (param.getInt(String8("test_cmd_policy_input"), valueInt) == NO_ERROR) {
1140 param.remove(String8("test_cmd_policy_input"));
1141 mTestInput = valueInt;
1142 }
1143
1144 if (param.get(String8("test_cmd_policy_format"), value) == NO_ERROR) {
1145 param.remove(String8("test_cmd_policy_format"));
1146 int format = AudioSystem::INVALID_FORMAT;
1147 if (value == "PCM 16 bits") {
1148 format = AudioSystem::PCM_16_BIT;
1149 } else if (value == "PCM 8 bits") {
1150 format = AudioSystem::PCM_8_BIT;
1151 } else if (value == "Compressed MP3") {
1152 format = AudioSystem::MP3;
1153 }
1154 if (format != AudioSystem::INVALID_FORMAT) {
1155 if (target == "Manager") {
1156 mTestFormat = format;
1157 } else if (mTestOutputs[mCurOutput] != 0) {
1158 AudioParameter outputParam = AudioParameter();
1159 outputParam.addInt(String8("format"), format);
1160 mpClientInterface->setParameters(mTestOutputs[mCurOutput], outputParam.toString());
1161 }
1162 }
1163 }
1164 if (param.get(String8("test_cmd_policy_channels"), value) == NO_ERROR) {
1165 param.remove(String8("test_cmd_policy_channels"));
1166 int channels = 0;
1167
1168 if (value == "Channels Stereo") {
1169 channels = AudioSystem::CHANNEL_OUT_STEREO;
1170 } else if (value == "Channels Mono") {
1171 channels = AudioSystem::CHANNEL_OUT_MONO;
1172 }
1173 if (channels != 0) {
1174 if (target == "Manager") {
1175 mTestChannels = channels;
1176 } else if (mTestOutputs[mCurOutput] != 0) {
1177 AudioParameter outputParam = AudioParameter();
1178 outputParam.addInt(String8("channels"), channels);
1179 mpClientInterface->setParameters(mTestOutputs[mCurOutput], outputParam.toString());
1180 }
1181 }
1182 }
1183 if (param.getInt(String8("test_cmd_policy_sampleRate"), valueInt) == NO_ERROR) {
1184 param.remove(String8("test_cmd_policy_sampleRate"));
1185 if (valueInt >= 0 && valueInt <= 96000) {
1186 int samplingRate = valueInt;
1187 if (target == "Manager") {
1188 mTestSamplingRate = samplingRate;
1189 } else if (mTestOutputs[mCurOutput] != 0) {
1190 AudioParameter outputParam = AudioParameter();
1191 outputParam.addInt(String8("sampling_rate"), samplingRate);
1192 mpClientInterface->setParameters(mTestOutputs[mCurOutput], outputParam.toString());
1193 }
1194 }
1195 }
1196
1197 if (param.get(String8("test_cmd_policy_reopen"), value) == NO_ERROR) {
1198 param.remove(String8("test_cmd_policy_reopen"));
1199
1200 mpClientInterface->closeOutput(mHardwareOutput);
1201 delete mOutputs.valueFor(mHardwareOutput);
1202 mOutputs.removeItem(mHardwareOutput);
1203
1204 AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();
1205 outputDesc->mDevice = (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER;
1206 mHardwareOutput = mpClientInterface->openOutput(&outputDesc->mDevice,
1207 &outputDesc->mSamplingRate,
1208 &outputDesc->mFormat,
1209 &outputDesc->mChannels,
1210 &outputDesc->mLatency,
1211 outputDesc->mFlags);
1212 if (mHardwareOutput == 0) {
1213 LOGE("Failed to reopen hardware output stream, samplingRate: %d, format %d, channels %d",
1214 outputDesc->mSamplingRate, outputDesc->mFormat, outputDesc->mChannels);
1215 } else {
1216 AudioParameter outputCmd = AudioParameter();
1217 outputCmd.addInt(String8("set_id"), 0);
1218 mpClientInterface->setParameters(mHardwareOutput, outputCmd.toString());
1219 addOutput(mHardwareOutput, outputDesc);
1220 }
1221 }
1222
1223
1224 mpClientInterface->setParameters(0, String8("test_cmd_policy="));
1225 }
1226 }
1227 return false;
1228}
1229
1230void AudioPolicyManagerBase::exit()
1231{
1232 {
1233 AutoMutex _l(mLock);
1234 requestExit();
1235 mWaitWorkCV.signal();
1236 }
1237 requestExitAndWait();
1238}
1239
1240int AudioPolicyManagerBase::testOutputIndex(audio_io_handle_t output)
1241{
1242 for (int i = 0; i < NUM_TEST_OUTPUTS; i++) {
1243 if (output == mTestOutputs[i]) return i;
1244 }
1245 return 0;
1246}
1247#endif //AUDIO_POLICY_TEST
1248
1249// ---
1250
1251void AudioPolicyManagerBase::addOutput(audio_io_handle_t id, AudioOutputDescriptor *outputDesc)
1252{
1253 outputDesc->mId = id;
1254 mOutputs.add(id, outputDesc);
1255}
1256
1257
1258#ifdef WITH_A2DP
1259status_t AudioPolicyManagerBase::handleA2dpConnection(AudioSystem::audio_devices device,
1260 const char *device_address)
1261{
1262 // when an A2DP device is connected, open an A2DP and a duplicated output
1263 LOGV("opening A2DP output for device %s", device_address);
1264 AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();
1265 outputDesc->mDevice = device;
1266 mA2dpOutput = mpClientInterface->openOutput(&outputDesc->mDevice,
1267 &outputDesc->mSamplingRate,
1268 &outputDesc->mFormat,
1269 &outputDesc->mChannels,
1270 &outputDesc->mLatency,
1271 outputDesc->mFlags);
1272 if (mA2dpOutput) {
1273 // add A2DP output descriptor
1274 addOutput(mA2dpOutput, outputDesc);
Eric Laurentde070132010-07-13 04:45:46 -07001275
1276 //TODO: configure audio effect output stage here
1277
Mathias Agopian65ab4712010-07-14 17:59:35 -07001278 // set initial stream volume for A2DP device
1279 applyStreamVolumes(mA2dpOutput, device);
1280 if (a2dpUsedForSonification()) {
1281 mDuplicatedOutput = mpClientInterface->openDuplicateOutput(mA2dpOutput, mHardwareOutput);
1282 }
1283 if (mDuplicatedOutput != 0 ||
1284 !a2dpUsedForSonification()) {
1285 // If both A2DP and duplicated outputs are open, send device address to A2DP hardware
1286 // interface
1287 AudioParameter param;
1288 param.add(String8("a2dp_sink_address"), String8(device_address));
1289 mpClientInterface->setParameters(mA2dpOutput, param.toString());
1290 mA2dpDeviceAddress = String8(device_address, MAX_DEVICE_ADDRESS_LEN);
1291
1292 if (a2dpUsedForSonification()) {
1293 // add duplicated output descriptor
1294 AudioOutputDescriptor *dupOutputDesc = new AudioOutputDescriptor();
1295 dupOutputDesc->mOutput1 = mOutputs.valueFor(mHardwareOutput);
1296 dupOutputDesc->mOutput2 = mOutputs.valueFor(mA2dpOutput);
1297 dupOutputDesc->mSamplingRate = outputDesc->mSamplingRate;
1298 dupOutputDesc->mFormat = outputDesc->mFormat;
1299 dupOutputDesc->mChannels = outputDesc->mChannels;
1300 dupOutputDesc->mLatency = outputDesc->mLatency;
1301 addOutput(mDuplicatedOutput, dupOutputDesc);
1302 applyStreamVolumes(mDuplicatedOutput, device);
1303 }
1304 } else {
1305 LOGW("getOutput() could not open duplicated output for %d and %d",
1306 mHardwareOutput, mA2dpOutput);
1307 mpClientInterface->closeOutput(mA2dpOutput);
1308 mOutputs.removeItem(mA2dpOutput);
1309 mA2dpOutput = 0;
1310 delete outputDesc;
1311 return NO_INIT;
1312 }
1313 } else {
1314 LOGW("setDeviceConnectionState() could not open A2DP output for device %x", device);
1315 delete outputDesc;
1316 return NO_INIT;
1317 }
1318 AudioOutputDescriptor *hwOutputDesc = mOutputs.valueFor(mHardwareOutput);
1319
1320 if (mScoDeviceAddress != "") {
1321 // It is normal to suspend twice if we are both in call,
1322 // and have the hardware audio output routed to BT SCO
1323 if (mPhoneState != AudioSystem::MODE_NORMAL) {
1324 mpClientInterface->suspendOutput(mA2dpOutput);
1325 }
1326 if (AudioSystem::isBluetoothScoDevice((AudioSystem::audio_devices)hwOutputDesc->device())) {
1327 mpClientInterface->suspendOutput(mA2dpOutput);
1328 }
1329 }
1330
1331 if (!a2dpUsedForSonification()) {
1332 // mute music on A2DP output if a notification or ringtone is playing
1333 uint32_t refCount = hwOutputDesc->strategyRefCount(STRATEGY_SONIFICATION);
1334 for (uint32_t i = 0; i < refCount; i++) {
1335 setStrategyMute(STRATEGY_MEDIA, true, mA2dpOutput);
1336 }
1337 }
1338 return NO_ERROR;
1339}
1340
1341status_t AudioPolicyManagerBase::handleA2dpDisconnection(AudioSystem::audio_devices device,
1342 const char *device_address)
1343{
1344 if (mA2dpOutput == 0) {
1345 LOGW("setDeviceConnectionState() disconnecting A2DP and no A2DP output!");
1346 return INVALID_OPERATION;
1347 }
1348
1349 if (mA2dpDeviceAddress != device_address) {
1350 LOGW("setDeviceConnectionState() disconnecting unknow A2DP sink address %s", device_address);
1351 return INVALID_OPERATION;
1352 }
1353
1354 // mute media strategy to avoid outputting sound on hardware output while music stream
1355 // is switched from A2DP output and before music is paused by music application
1356 setStrategyMute(STRATEGY_MEDIA, true, mHardwareOutput);
1357 setStrategyMute(STRATEGY_MEDIA, false, mHardwareOutput, MUTE_TIME_MS);
1358
1359 if (!a2dpUsedForSonification()) {
1360 // unmute music on A2DP output if a notification or ringtone is playing
1361 uint32_t refCount = mOutputs.valueFor(mHardwareOutput)->strategyRefCount(STRATEGY_SONIFICATION);
1362 for (uint32_t i = 0; i < refCount; i++) {
1363 setStrategyMute(STRATEGY_MEDIA, false, mA2dpOutput);
1364 }
1365 }
1366 mA2dpDeviceAddress = "";
1367 return NO_ERROR;
1368}
1369
1370void AudioPolicyManagerBase::closeA2dpOutputs()
1371{
Praveen Bharathib235dee2010-10-06 15:23:14 -05001372
Mathias Agopian65ab4712010-07-14 17:59:35 -07001373 LOGV("setDeviceConnectionState() closing A2DP and duplicated output!");
1374
1375 if (mDuplicatedOutput != 0) {
1376 AudioOutputDescriptor *dupOutputDesc = mOutputs.valueFor(mDuplicatedOutput);
1377 AudioOutputDescriptor *hwOutputDesc = mOutputs.valueFor(mHardwareOutput);
1378 // As all active tracks on duplicated output will be deleted,
1379 // and as they were also referenced on hardware output, the reference
1380 // count for their stream type must be adjusted accordingly on
1381 // hardware output.
1382 for (int i = 0; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) {
1383 int refCount = dupOutputDesc->mRefCount[i];
1384 hwOutputDesc->changeRefCount((AudioSystem::stream_type)i,-refCount);
1385 }
1386
1387 mpClientInterface->closeOutput(mDuplicatedOutput);
1388 delete mOutputs.valueFor(mDuplicatedOutput);
1389 mOutputs.removeItem(mDuplicatedOutput);
1390 mDuplicatedOutput = 0;
1391 }
1392 if (mA2dpOutput != 0) {
1393 AudioParameter param;
1394 param.add(String8("closing"), String8("true"));
1395 mpClientInterface->setParameters(mA2dpOutput, param.toString());
Eric Laurentde070132010-07-13 04:45:46 -07001396
Mathias Agopian65ab4712010-07-14 17:59:35 -07001397 mpClientInterface->closeOutput(mA2dpOutput);
1398 delete mOutputs.valueFor(mA2dpOutput);
1399 mOutputs.removeItem(mA2dpOutput);
1400 mA2dpOutput = 0;
1401 }
1402}
1403
Eric Laurentc1c88e22010-08-27 17:10:36 -07001404void AudioPolicyManagerBase::checkOutputForStrategy(routing_strategy strategy)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001405{
1406 uint32_t prevDevice = getDeviceForStrategy(strategy);
1407 uint32_t curDevice = getDeviceForStrategy(strategy, false);
1408 bool a2dpWasUsed = AudioSystem::isA2dpDevice((AudioSystem::audio_devices)(prevDevice & ~AudioSystem::DEVICE_OUT_SPEAKER));
1409 bool a2dpIsUsed = AudioSystem::isA2dpDevice((AudioSystem::audio_devices)(curDevice & ~AudioSystem::DEVICE_OUT_SPEAKER));
Eric Laurentde070132010-07-13 04:45:46 -07001410 audio_io_handle_t srcOutput = 0;
1411 audio_io_handle_t dstOutput = 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001412
1413 if (a2dpWasUsed && !a2dpIsUsed) {
1414 bool dupUsed = a2dpUsedForSonification() && a2dpWasUsed && (AudioSystem::popCount(prevDevice) == 2);
Eric Laurentde070132010-07-13 04:45:46 -07001415 dstOutput = mHardwareOutput;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001416 if (dupUsed) {
Eric Laurentde070132010-07-13 04:45:46 -07001417 LOGV("checkOutputForStrategy() moving strategy %d from duplicated", strategy);
1418 srcOutput = mDuplicatedOutput;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001419 } else {
Eric Laurentde070132010-07-13 04:45:46 -07001420 LOGV("checkOutputForStrategy() moving strategy %d from a2dp", strategy);
1421 srcOutput = mA2dpOutput;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001422 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001423 }
1424 if (a2dpIsUsed && !a2dpWasUsed) {
1425 bool dupUsed = a2dpUsedForSonification() && a2dpIsUsed && (AudioSystem::popCount(curDevice) == 2);
Eric Laurentde070132010-07-13 04:45:46 -07001426 srcOutput = mHardwareOutput;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001427 if (dupUsed) {
Eric Laurentde070132010-07-13 04:45:46 -07001428 LOGV("checkOutputForStrategy() moving strategy %d to duplicated", strategy);
1429 dstOutput = mDuplicatedOutput;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001430 } else {
Eric Laurentde070132010-07-13 04:45:46 -07001431 LOGV("checkOutputForStrategy() moving strategy %d to a2dp", strategy);
1432 dstOutput = mA2dpOutput;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001433 }
Eric Laurentde070132010-07-13 04:45:46 -07001434 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001435
Eric Laurentde070132010-07-13 04:45:46 -07001436 if (srcOutput != 0 && dstOutput != 0) {
1437 // Move effects associated to this strategy from previous output to new output
1438 for (size_t i = 0; i < mEffects.size(); i++) {
1439 EffectDescriptor *desc = mEffects.valueAt(i);
1440 if (desc->mSession != AudioSystem::SESSION_OUTPUT_STAGE &&
1441 desc->mStrategy == strategy &&
1442 desc->mOutput == srcOutput) {
1443 LOGV("checkOutputForStrategy() moving effect %d to output %d", mEffects.keyAt(i), dstOutput);
1444 mpClientInterface->moveEffects(desc->mSession, srcOutput, dstOutput);
1445 desc->mOutput = dstOutput;
1446 }
1447 }
1448 // Move tracks associated to this strategy from previous output to new output
Mathias Agopian65ab4712010-07-14 17:59:35 -07001449 for (int i = 0; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) {
1450 if (getStrategy((AudioSystem::stream_type)i) == strategy) {
Eric Laurentde070132010-07-13 04:45:46 -07001451 mpClientInterface->setStreamOutput((AudioSystem::stream_type)i, dstOutput);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001452 }
1453 }
1454 }
1455}
1456
Eric Laurentc1c88e22010-08-27 17:10:36 -07001457void AudioPolicyManagerBase::checkOutputForAllStrategies()
Mathias Agopian65ab4712010-07-14 17:59:35 -07001458{
Eric Laurentc1c88e22010-08-27 17:10:36 -07001459 checkOutputForStrategy(STRATEGY_PHONE);
1460 checkOutputForStrategy(STRATEGY_SONIFICATION);
1461 checkOutputForStrategy(STRATEGY_MEDIA);
1462 checkOutputForStrategy(STRATEGY_DTMF);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001463}
1464
1465#endif
1466
1467uint32_t AudioPolicyManagerBase::getNewDevice(audio_io_handle_t output, bool fromCache)
1468{
1469 uint32_t device = 0;
1470
1471 AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output);
1472 // check the following by order of priority to request a routing change if necessary:
1473 // 1: we are in call or the strategy phone is active on the hardware output:
1474 // use device for strategy phone
1475 // 2: the strategy sonification is active on the hardware output:
1476 // use device for strategy sonification
1477 // 3: the strategy media is active on the hardware output:
1478 // use device for strategy media
1479 // 4: the strategy DTMF is active on the hardware output:
1480 // use device for strategy DTMF
1481 if (mPhoneState == AudioSystem::MODE_IN_CALL ||
1482 outputDesc->isUsedByStrategy(STRATEGY_PHONE)) {
1483 device = getDeviceForStrategy(STRATEGY_PHONE, fromCache);
1484 } else if (outputDesc->isUsedByStrategy(STRATEGY_SONIFICATION)) {
1485 device = getDeviceForStrategy(STRATEGY_SONIFICATION, fromCache);
1486 } else if (outputDesc->isUsedByStrategy(STRATEGY_MEDIA)) {
1487 device = getDeviceForStrategy(STRATEGY_MEDIA, fromCache);
1488 } else if (outputDesc->isUsedByStrategy(STRATEGY_DTMF)) {
1489 device = getDeviceForStrategy(STRATEGY_DTMF, fromCache);
1490 }
1491
1492 LOGV("getNewDevice() selected device %x", device);
1493 return device;
1494}
1495
Eric Laurentde070132010-07-13 04:45:46 -07001496uint32_t AudioPolicyManagerBase::getStrategyForStream(AudioSystem::stream_type stream) {
1497 return (uint32_t)getStrategy(stream);
1498}
1499
1500AudioPolicyManagerBase::routing_strategy AudioPolicyManagerBase::getStrategy(
1501 AudioSystem::stream_type stream) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001502 // stream to strategy mapping
1503 switch (stream) {
1504 case AudioSystem::VOICE_CALL:
1505 case AudioSystem::BLUETOOTH_SCO:
1506 return STRATEGY_PHONE;
1507 case AudioSystem::RING:
1508 case AudioSystem::NOTIFICATION:
1509 case AudioSystem::ALARM:
1510 case AudioSystem::ENFORCED_AUDIBLE:
1511 return STRATEGY_SONIFICATION;
1512 case AudioSystem::DTMF:
1513 return STRATEGY_DTMF;
1514 default:
1515 LOGE("unknown stream type");
1516 case AudioSystem::SYSTEM:
1517 // NOTE: SYSTEM stream uses MEDIA strategy because muting music and switching outputs
1518 // while key clicks are played produces a poor result
1519 case AudioSystem::TTS:
1520 case AudioSystem::MUSIC:
1521 return STRATEGY_MEDIA;
1522 }
1523}
1524
1525uint32_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy strategy, bool fromCache)
1526{
1527 uint32_t device = 0;
1528
1529 if (fromCache) {
1530 LOGV("getDeviceForStrategy() from cache strategy %d, device %x", strategy, mDeviceForStrategy[strategy]);
1531 return mDeviceForStrategy[strategy];
1532 }
1533
1534 switch (strategy) {
1535 case STRATEGY_DTMF:
1536 if (mPhoneState != AudioSystem::MODE_IN_CALL) {
1537 // when off call, DTMF strategy follows the same rules as MEDIA strategy
1538 device = getDeviceForStrategy(STRATEGY_MEDIA, false);
1539 break;
1540 }
1541 // when in call, DTMF and PHONE strategies follow the same rules
1542 // FALL THROUGH
1543
1544 case STRATEGY_PHONE:
1545 // for phone strategy, we first consider the forced use and then the available devices by order
1546 // of priority
1547 switch (mForceUse[AudioSystem::FOR_COMMUNICATION]) {
1548 case AudioSystem::FORCE_BT_SCO:
1549 if (mPhoneState != AudioSystem::MODE_IN_CALL || strategy != STRATEGY_DTMF) {
1550 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
1551 if (device) break;
1552 }
1553 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
1554 if (device) break;
1555 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO;
1556 if (device) break;
1557 // if SCO device is requested but no SCO device is available, fall back to default case
1558 // FALL THROUGH
1559
1560 default: // FORCE_NONE
1561 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE;
1562 if (device) break;
1563 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET;
1564 if (device) break;
Praveen Bharathib235dee2010-10-06 15:23:14 -05001565 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET;
1566 if (device) break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001567#ifdef WITH_A2DP
1568 // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP
1569 if (mPhoneState != AudioSystem::MODE_IN_CALL) {
1570 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP;
1571 if (device) break;
1572 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
1573 if (device) break;
1574 }
1575#endif
1576 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_EARPIECE;
1577 if (device == 0) {
1578 LOGE("getDeviceForStrategy() earpiece device not found");
1579 }
1580 break;
1581
1582 case AudioSystem::FORCE_SPEAKER:
1583 if (mPhoneState != AudioSystem::MODE_IN_CALL || strategy != STRATEGY_DTMF) {
1584 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
1585 if (device) break;
1586 }
1587#ifdef WITH_A2DP
1588 // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to
1589 // A2DP speaker when forcing to speaker output
1590 if (mPhoneState != AudioSystem::MODE_IN_CALL) {
1591 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
1592 if (device) break;
1593 }
1594#endif
1595 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
1596 if (device == 0) {
1597 LOGE("getDeviceForStrategy() speaker device not found");
1598 }
1599 break;
1600 }
1601 break;
1602
1603 case STRATEGY_SONIFICATION:
1604
1605 // If incall, just select the STRATEGY_PHONE device: The rest of the behavior is handled by
1606 // handleIncallSonification().
1607 if (mPhoneState == AudioSystem::MODE_IN_CALL) {
1608 device = getDeviceForStrategy(STRATEGY_PHONE, false);
1609 break;
1610 }
1611 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
1612 if (device == 0) {
1613 LOGE("getDeviceForStrategy() speaker device not found");
1614 }
1615 // The second device used for sonification is the same as the device used by media strategy
1616 // FALL THROUGH
1617
1618 case STRATEGY_MEDIA: {
1619 uint32_t device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL;
1620 if (device2 == 0) {
1621 device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE;
1622 }
1623 if (device2 == 0) {
1624 device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET;
1625 }
Praveen Bharathib235dee2010-10-06 15:23:14 -05001626 if (device2 == 0) {
1627 device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET;
1628 }
1629 if (device2 == 0) {
1630 device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET;
1631 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001632#ifdef WITH_A2DP
1633 if (mA2dpOutput != 0) {
1634 if (strategy == STRATEGY_SONIFICATION && !a2dpUsedForSonification()) {
1635 break;
1636 }
1637 if (device2 == 0) {
1638 device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP;
1639 }
1640 if (device2 == 0) {
1641 device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
1642 }
1643 if (device2 == 0) {
1644 device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
1645 }
1646 }
1647#endif
1648 if (device2 == 0) {
1649 device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
1650 }
1651
1652 // device is DEVICE_OUT_SPEAKER if we come from case STRATEGY_SONIFICATION, 0 otherwise
1653 device |= device2;
1654 if (device == 0) {
1655 LOGE("getDeviceForStrategy() speaker device not found");
1656 }
1657 } break;
1658
1659 default:
1660 LOGW("getDeviceForStrategy() unknown strategy: %d", strategy);
1661 break;
1662 }
1663
1664 LOGV("getDeviceForStrategy() strategy %d, device %x", strategy, device);
1665 return device;
1666}
1667
1668void AudioPolicyManagerBase::updateDeviceForStrategy()
1669{
1670 for (int i = 0; i < NUM_STRATEGIES; i++) {
1671 mDeviceForStrategy[i] = getDeviceForStrategy((routing_strategy)i, false);
1672 }
1673}
1674
1675void AudioPolicyManagerBase::setOutputDevice(audio_io_handle_t output, uint32_t device, bool force, int delayMs)
1676{
1677 LOGV("setOutputDevice() output %d device %x delayMs %d", output, device, delayMs);
1678 AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output);
1679
1680
1681 if (outputDesc->isDuplicated()) {
1682 setOutputDevice(outputDesc->mOutput1->mId, device, force, delayMs);
1683 setOutputDevice(outputDesc->mOutput2->mId, device, force, delayMs);
1684 return;
1685 }
1686#ifdef WITH_A2DP
1687 // filter devices according to output selected
1688 if (output == mA2dpOutput) {
1689 device &= AudioSystem::DEVICE_OUT_ALL_A2DP;
1690 } else {
1691 device &= ~AudioSystem::DEVICE_OUT_ALL_A2DP;
1692 }
1693#endif
1694
1695 uint32_t prevDevice = (uint32_t)outputDesc->device();
1696 // Do not change the routing if:
1697 // - the requestede device is 0
1698 // - the requested device is the same as current device and force is not specified.
1699 // Doing this check here allows the caller to call setOutputDevice() without conditions
1700 if ((device == 0 || device == prevDevice) && !force) {
1701 LOGV("setOutputDevice() setting same device %x or null device for output %d", device, output);
1702 return;
1703 }
1704
1705 outputDesc->mDevice = device;
1706 // mute media streams if both speaker and headset are selected
1707 if (output == mHardwareOutput && AudioSystem::popCount(device) == 2) {
1708 setStrategyMute(STRATEGY_MEDIA, true, output);
1709 // wait for the PCM output buffers to empty before proceeding with the rest of the command
1710 usleep(outputDesc->mLatency*2*1000);
1711 }
1712#ifdef WITH_A2DP
1713 // suspend A2DP output if SCO device is selected
1714 if (AudioSystem::isBluetoothScoDevice((AudioSystem::audio_devices)device)) {
1715 if (mA2dpOutput != 0) {
1716 mpClientInterface->suspendOutput(mA2dpOutput);
1717 }
1718 }
1719#endif
1720 // do the routing
1721 AudioParameter param = AudioParameter();
1722 param.addInt(String8(AudioParameter::keyRouting), (int)device);
1723 mpClientInterface->setParameters(mHardwareOutput, param.toString(), delayMs);
1724 // update stream volumes according to new device
1725 applyStreamVolumes(output, device, delayMs);
1726
1727#ifdef WITH_A2DP
1728 // if disconnecting SCO device, restore A2DP output
1729 if (AudioSystem::isBluetoothScoDevice((AudioSystem::audio_devices)prevDevice)) {
1730 if (mA2dpOutput != 0) {
1731 LOGV("restore A2DP output");
1732 mpClientInterface->restoreOutput(mA2dpOutput);
1733 }
1734 }
1735#endif
1736 // if changing from a combined headset + speaker route, unmute media streams
1737 if (output == mHardwareOutput && AudioSystem::popCount(prevDevice) == 2) {
1738 setStrategyMute(STRATEGY_MEDIA, false, output, delayMs);
1739 }
1740}
1741
1742uint32_t AudioPolicyManagerBase::getDeviceForInputSource(int inputSource)
1743{
1744 uint32_t device;
1745
1746 switch(inputSource) {
1747 case AUDIO_SOURCE_DEFAULT:
1748 case AUDIO_SOURCE_MIC:
1749 case AUDIO_SOURCE_VOICE_RECOGNITION:
Jean-Michel Trivic643d772010-11-08 18:38:14 -08001750 case AUDIO_SOURCE_VOICE_COMMUNICATION:
Mathias Agopian65ab4712010-07-14 17:59:35 -07001751 if (mForceUse[AudioSystem::FOR_RECORD] == AudioSystem::FORCE_BT_SCO &&
1752 mAvailableInputDevices & AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
1753 device = AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET;
1754 } else if (mAvailableInputDevices & AudioSystem::DEVICE_IN_WIRED_HEADSET) {
1755 device = AudioSystem::DEVICE_IN_WIRED_HEADSET;
1756 } else {
1757 device = AudioSystem::DEVICE_IN_BUILTIN_MIC;
1758 }
1759 break;
1760 case AUDIO_SOURCE_CAMCORDER:
1761 if (hasBackMicrophone()) {
1762 device = AudioSystem::DEVICE_IN_BACK_MIC;
1763 } else {
1764 device = AudioSystem::DEVICE_IN_BUILTIN_MIC;
1765 }
1766 break;
1767 case AUDIO_SOURCE_VOICE_UPLINK:
1768 case AUDIO_SOURCE_VOICE_DOWNLINK:
1769 case AUDIO_SOURCE_VOICE_CALL:
1770 device = AudioSystem::DEVICE_IN_VOICE_CALL;
1771 break;
1772 default:
1773 LOGW("getInput() invalid input source %d", inputSource);
1774 device = 0;
1775 break;
1776 }
1777 LOGV("getDeviceForInputSource()input source %d, device %08x", inputSource, device);
1778 return device;
1779}
1780
1781audio_io_handle_t AudioPolicyManagerBase::getActiveInput()
1782{
1783 for (size_t i = 0; i < mInputs.size(); i++) {
1784 if (mInputs.valueAt(i)->mRefCount > 0) {
1785 return mInputs.keyAt(i);
1786 }
1787 }
1788 return 0;
1789}
1790
1791float AudioPolicyManagerBase::computeVolume(int stream, int index, audio_io_handle_t output, uint32_t device)
1792{
1793 float volume = 1.0;
1794 AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output);
1795 StreamDescriptor &streamDesc = mStreams[stream];
1796
1797 if (device == 0) {
1798 device = outputDesc->device();
1799 }
1800
1801 int volInt = (100 * (index - streamDesc.mIndexMin)) / (streamDesc.mIndexMax - streamDesc.mIndexMin);
1802 volume = AudioSystem::linearToLog(volInt);
1803
1804 // if a headset is connected, apply the following rules to ring tones and notifications
1805 // to avoid sound level bursts in user's ears:
1806 // - always attenuate ring tones and notifications volume by 6dB
1807 // - if music is playing, always limit the volume to current music volume,
1808 // with a minimum threshold at -36dB so that notification is always perceived.
1809 if ((device &
1810 (AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP |
1811 AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
1812 AudioSystem::DEVICE_OUT_WIRED_HEADSET |
Praveen Bharathib235dee2010-10-06 15:23:14 -05001813 AudioSystem::DEVICE_OUT_WIRED_HEADPHONE |
1814 AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET |
1815 AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)) &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07001816 (getStrategy((AudioSystem::stream_type)stream) == STRATEGY_SONIFICATION) &&
1817 streamDesc.mCanBeMuted) {
1818 volume *= SONIFICATION_HEADSET_VOLUME_FACTOR;
1819 // when the phone is ringing we must consider that music could have been paused just before
1820 // by the music application and behave as if music was active if the last music track was
1821 // just stopped
1822 if (outputDesc->mRefCount[AudioSystem::MUSIC] || mLimitRingtoneVolume) {
1823 float musicVol = computeVolume(AudioSystem::MUSIC, mStreams[AudioSystem::MUSIC].mIndexCur, output, device);
1824 float minVol = (musicVol > SONIFICATION_HEADSET_VOLUME_MIN) ? musicVol : SONIFICATION_HEADSET_VOLUME_MIN;
1825 if (volume > minVol) {
1826 volume = minVol;
1827 LOGV("computeVolume limiting volume to %f musicVol %f", minVol, musicVol);
1828 }
1829 }
1830 }
1831
1832 return volume;
1833}
1834
1835status_t AudioPolicyManagerBase::checkAndSetVolume(int stream, int index, audio_io_handle_t output, uint32_t device, int delayMs, bool force)
1836{
1837
1838 // do not change actual stream volume if the stream is muted
1839 if (mOutputs.valueFor(output)->mMuteCount[stream] != 0) {
1840 LOGV("checkAndSetVolume() stream %d muted count %d", stream, mOutputs.valueFor(output)->mMuteCount[stream]);
1841 return NO_ERROR;
1842 }
1843
1844 // do not change in call volume if bluetooth is connected and vice versa
1845 if ((stream == AudioSystem::VOICE_CALL && mForceUse[AudioSystem::FOR_COMMUNICATION] == AudioSystem::FORCE_BT_SCO) ||
1846 (stream == AudioSystem::BLUETOOTH_SCO && mForceUse[AudioSystem::FOR_COMMUNICATION] != AudioSystem::FORCE_BT_SCO)) {
1847 LOGV("checkAndSetVolume() cannot set stream %d volume with force use = %d for comm",
1848 stream, mForceUse[AudioSystem::FOR_COMMUNICATION]);
1849 return INVALID_OPERATION;
1850 }
1851
1852 float volume = computeVolume(stream, index, output, device);
Mathias Agopian094c96d2010-07-14 18:48:58 -07001853 // We actually change the volume if:
1854 // - the float value returned by computeVolume() changed
1855 // - the force flag is set
1856 if (volume != mOutputs.valueFor(output)->mCurVolume[stream] ||
1857 force) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001858 mOutputs.valueFor(output)->mCurVolume[stream] = volume;
1859 LOGV("setStreamVolume() for output %d stream %d, volume %f, delay %d", output, stream, volume, delayMs);
1860 if (stream == AudioSystem::VOICE_CALL ||
1861 stream == AudioSystem::DTMF ||
1862 stream == AudioSystem::BLUETOOTH_SCO) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001863 // offset value to reflect actual hardware volume that never reaches 0
1864 // 1% corresponds roughly to first step in VOICE_CALL stream volume setting (see AudioService.java)
1865 volume = 0.01 + 0.99 * volume;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001866 }
1867 mpClientInterface->setStreamVolume((AudioSystem::stream_type)stream, volume, output, delayMs);
1868 }
1869
Mathias Agopian094c96d2010-07-14 18:48:58 -07001870 if (stream == AudioSystem::VOICE_CALL ||
1871 stream == AudioSystem::BLUETOOTH_SCO) {
1872 float voiceVolume;
1873 // Force voice volume to max for bluetooth SCO as volume is managed by the headset
1874 if (stream == AudioSystem::VOICE_CALL) {
1875 voiceVolume = (float)index/(float)mStreams[stream].mIndexMax;
1876 } else {
1877 voiceVolume = 1.0;
1878 }
1879 if (voiceVolume != mLastVoiceVolume && output == mHardwareOutput) {
1880 mpClientInterface->setVoiceVolume(voiceVolume, delayMs);
1881 mLastVoiceVolume = voiceVolume;
1882 }
1883 }
1884
Mathias Agopian65ab4712010-07-14 17:59:35 -07001885 return NO_ERROR;
1886}
1887
1888void AudioPolicyManagerBase::applyStreamVolumes(audio_io_handle_t output, uint32_t device, int delayMs)
1889{
1890 LOGV("applyStreamVolumes() for output %d and device %x", output, device);
1891
1892 for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
1893 checkAndSetVolume(stream, mStreams[stream].mIndexCur, output, device, delayMs);
1894 }
1895}
1896
1897void AudioPolicyManagerBase::setStrategyMute(routing_strategy strategy, bool on, audio_io_handle_t output, int delayMs)
1898{
1899 LOGV("setStrategyMute() strategy %d, mute %d, output %d", strategy, on, output);
1900 for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
1901 if (getStrategy((AudioSystem::stream_type)stream) == strategy) {
1902 setStreamMute(stream, on, output, delayMs);
1903 }
1904 }
1905}
1906
1907void AudioPolicyManagerBase::setStreamMute(int stream, bool on, audio_io_handle_t output, int delayMs)
1908{
1909 StreamDescriptor &streamDesc = mStreams[stream];
1910 AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output);
1911
1912 LOGV("setStreamMute() stream %d, mute %d, output %d, mMuteCount %d", stream, on, output, outputDesc->mMuteCount[stream]);
1913
1914 if (on) {
1915 if (outputDesc->mMuteCount[stream] == 0) {
1916 if (streamDesc.mCanBeMuted) {
1917 checkAndSetVolume(stream, 0, output, outputDesc->device(), delayMs);
1918 }
1919 }
1920 // increment mMuteCount after calling checkAndSetVolume() so that volume change is not ignored
1921 outputDesc->mMuteCount[stream]++;
1922 } else {
1923 if (outputDesc->mMuteCount[stream] == 0) {
1924 LOGW("setStreamMute() unmuting non muted stream!");
1925 return;
1926 }
1927 if (--outputDesc->mMuteCount[stream] == 0) {
1928 checkAndSetVolume(stream, streamDesc.mIndexCur, output, outputDesc->device(), delayMs);
1929 }
1930 }
1931}
1932
1933void AudioPolicyManagerBase::handleIncallSonification(int stream, bool starting, bool stateChange)
1934{
1935 // if the stream pertains to sonification strategy and we are in call we must
1936 // mute the stream if it is low visibility. If it is high visibility, we must play a tone
1937 // in the device used for phone strategy and play the tone if the selected device does not
1938 // interfere with the device used for phone strategy
1939 // if stateChange is true, we are called from setPhoneState() and we must mute or unmute as
1940 // many times as there are active tracks on the output
1941
1942 if (getStrategy((AudioSystem::stream_type)stream) == STRATEGY_SONIFICATION) {
1943 AudioOutputDescriptor *outputDesc = mOutputs.valueFor(mHardwareOutput);
1944 LOGV("handleIncallSonification() stream %d starting %d device %x stateChange %d",
1945 stream, starting, outputDesc->mDevice, stateChange);
1946 if (outputDesc->mRefCount[stream]) {
1947 int muteCount = 1;
1948 if (stateChange) {
1949 muteCount = outputDesc->mRefCount[stream];
1950 }
1951 if (AudioSystem::isLowVisibility((AudioSystem::stream_type)stream)) {
1952 LOGV("handleIncallSonification() low visibility, muteCount %d", muteCount);
1953 for (int i = 0; i < muteCount; i++) {
1954 setStreamMute(stream, starting, mHardwareOutput);
1955 }
1956 } else {
1957 LOGV("handleIncallSonification() high visibility");
1958 if (outputDesc->device() & getDeviceForStrategy(STRATEGY_PHONE)) {
1959 LOGV("handleIncallSonification() high visibility muted, muteCount %d", muteCount);
1960 for (int i = 0; i < muteCount; i++) {
1961 setStreamMute(stream, starting, mHardwareOutput);
1962 }
1963 }
1964 if (starting) {
1965 mpClientInterface->startTone(ToneGenerator::TONE_SUP_CALL_WAITING, AudioSystem::VOICE_CALL);
1966 } else {
1967 mpClientInterface->stopTone();
1968 }
1969 }
1970 }
1971 }
1972}
1973
1974bool AudioPolicyManagerBase::needsDirectOuput(AudioSystem::stream_type stream,
1975 uint32_t samplingRate,
1976 uint32_t format,
1977 uint32_t channels,
1978 AudioSystem::output_flags flags,
1979 uint32_t device)
1980{
1981 return ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) ||
1982 (format !=0 && !AudioSystem::isLinearPCM(format)));
1983}
1984
Eric Laurentde070132010-07-13 04:45:46 -07001985uint32_t AudioPolicyManagerBase::getMaxEffectsCpuLoad()
1986{
1987 return MAX_EFFECTS_CPU_LOAD;
1988}
1989
1990uint32_t AudioPolicyManagerBase::getMaxEffectsMemory()
1991{
1992 return MAX_EFFECTS_MEMORY;
1993}
1994
Mathias Agopian65ab4712010-07-14 17:59:35 -07001995// --- AudioOutputDescriptor class implementation
1996
1997AudioPolicyManagerBase::AudioOutputDescriptor::AudioOutputDescriptor()
1998 : mId(0), mSamplingRate(0), mFormat(0), mChannels(0), mLatency(0),
1999 mFlags((AudioSystem::output_flags)0), mDevice(0), mOutput1(0), mOutput2(0)
2000{
2001 // clear usage count for all stream types
2002 for (int i = 0; i < AudioSystem::NUM_STREAM_TYPES; i++) {
2003 mRefCount[i] = 0;
2004 mCurVolume[i] = -1.0;
2005 mMuteCount[i] = 0;
2006 }
2007}
2008
2009uint32_t AudioPolicyManagerBase::AudioOutputDescriptor::device()
2010{
2011 uint32_t device = 0;
2012 if (isDuplicated()) {
2013 device = mOutput1->mDevice | mOutput2->mDevice;
2014 } else {
2015 device = mDevice;
2016 }
2017 return device;
2018}
2019
2020void AudioPolicyManagerBase::AudioOutputDescriptor::changeRefCount(AudioSystem::stream_type stream, int delta)
2021{
2022 // forward usage count change to attached outputs
2023 if (isDuplicated()) {
2024 mOutput1->changeRefCount(stream, delta);
2025 mOutput2->changeRefCount(stream, delta);
2026 }
2027 if ((delta + (int)mRefCount[stream]) < 0) {
2028 LOGW("changeRefCount() invalid delta %d for stream %d, refCount %d", delta, stream, mRefCount[stream]);
2029 mRefCount[stream] = 0;
2030 return;
2031 }
2032 mRefCount[stream] += delta;
2033 LOGV("changeRefCount() stream %d, count %d", stream, mRefCount[stream]);
2034}
2035
2036uint32_t AudioPolicyManagerBase::AudioOutputDescriptor::refCount()
2037{
2038 uint32_t refcount = 0;
2039 for (int i = 0; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) {
2040 refcount += mRefCount[i];
2041 }
2042 return refcount;
2043}
2044
2045uint32_t AudioPolicyManagerBase::AudioOutputDescriptor::strategyRefCount(routing_strategy strategy)
2046{
2047 uint32_t refCount = 0;
2048 for (int i = 0; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) {
2049 if (getStrategy((AudioSystem::stream_type)i) == strategy) {
2050 refCount += mRefCount[i];
2051 }
2052 }
2053 return refCount;
2054}
2055
2056
2057status_t AudioPolicyManagerBase::AudioOutputDescriptor::dump(int fd)
2058{
2059 const size_t SIZE = 256;
2060 char buffer[SIZE];
2061 String8 result;
2062
2063 snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate);
2064 result.append(buffer);
2065 snprintf(buffer, SIZE, " Format: %d\n", mFormat);
2066 result.append(buffer);
2067 snprintf(buffer, SIZE, " Channels: %08x\n", mChannels);
2068 result.append(buffer);
2069 snprintf(buffer, SIZE, " Latency: %d\n", mLatency);
2070 result.append(buffer);
2071 snprintf(buffer, SIZE, " Flags %08x\n", mFlags);
2072 result.append(buffer);
2073 snprintf(buffer, SIZE, " Devices %08x\n", device());
2074 result.append(buffer);
2075 snprintf(buffer, SIZE, " Stream volume refCount muteCount\n");
2076 result.append(buffer);
2077 for (int i = 0; i < AudioSystem::NUM_STREAM_TYPES; i++) {
2078 snprintf(buffer, SIZE, " %02d %.03f %02d %02d\n", i, mCurVolume[i], mRefCount[i], mMuteCount[i]);
2079 result.append(buffer);
2080 }
2081 write(fd, result.string(), result.size());
2082
2083 return NO_ERROR;
2084}
2085
2086// --- AudioInputDescriptor class implementation
2087
2088AudioPolicyManagerBase::AudioInputDescriptor::AudioInputDescriptor()
2089 : mSamplingRate(0), mFormat(0), mChannels(0),
2090 mAcoustics((AudioSystem::audio_in_acoustics)0), mDevice(0), mRefCount(0)
2091{
2092}
2093
2094status_t AudioPolicyManagerBase::AudioInputDescriptor::dump(int fd)
2095{
2096 const size_t SIZE = 256;
2097 char buffer[SIZE];
2098 String8 result;
2099
2100 snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate);
2101 result.append(buffer);
2102 snprintf(buffer, SIZE, " Format: %d\n", mFormat);
2103 result.append(buffer);
2104 snprintf(buffer, SIZE, " Channels: %08x\n", mChannels);
2105 result.append(buffer);
2106 snprintf(buffer, SIZE, " Acoustics %08x\n", mAcoustics);
2107 result.append(buffer);
2108 snprintf(buffer, SIZE, " Devices %08x\n", mDevice);
2109 result.append(buffer);
2110 snprintf(buffer, SIZE, " Ref Count %d\n", mRefCount);
2111 result.append(buffer);
2112 write(fd, result.string(), result.size());
2113
2114 return NO_ERROR;
2115}
2116
2117// --- StreamDescriptor class implementation
2118
2119void AudioPolicyManagerBase::StreamDescriptor::dump(char* buffer, size_t size)
2120{
2121 snprintf(buffer, size, " %02d %02d %02d %d\n",
2122 mIndexMin,
2123 mIndexMax,
2124 mIndexCur,
2125 mCanBeMuted);
2126}
2127
Eric Laurentde070132010-07-13 04:45:46 -07002128// --- EffectDescriptor class implementation
2129
2130status_t AudioPolicyManagerBase::EffectDescriptor::dump(int fd)
2131{
2132 const size_t SIZE = 256;
2133 char buffer[SIZE];
2134 String8 result;
2135
2136 snprintf(buffer, SIZE, " Output: %d\n", mOutput);
2137 result.append(buffer);
2138 snprintf(buffer, SIZE, " Strategy: %d\n", mStrategy);
2139 result.append(buffer);
2140 snprintf(buffer, SIZE, " Session: %d\n", mSession);
2141 result.append(buffer);
2142 snprintf(buffer, SIZE, " Name: %s\n", mDesc.name);
2143 result.append(buffer);
2144 write(fd, result.string(), result.size());
2145
2146 return NO_ERROR;
2147}
2148
2149
Mathias Agopian65ab4712010-07-14 17:59:35 -07002150
2151}; // namespace android