blob: a6c2e73decb62be6eba36ff522a20474e5f6c8b4 [file] [log] [blame]
Iliyan Malchev4765c432012-06-11 14:36:16 -07001/*
2 * Copyright (C) 2009 The Android Open Source Project
3 * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
Iliyan Malchev4113f342012-06-11 14:39:47 -070018#define LOG_TAG "audio_policy.msm8960"
Iliyan Malchev4765c432012-06-11 14:36:16 -070019//#define LOG_NDEBUG 0
Iliyan Malchev4765c432012-06-11 14:36:16 -070020#include <utils/Log.h>
Iliyan Malchev4113f342012-06-11 14:39:47 -070021
Iliyan Malchev4765c432012-06-11 14:36:16 -070022#include "AudioPolicyManagerALSA.h"
23#include <media/mediarecorder.h>
24
25namespace android_audio_legacy {
26
27// ----------------------------------------------------------------------------
Iliyan Malchev4113f342012-06-11 14:39:47 -070028audio_devices_t AudioPolicyManager::getDeviceForStrategy(routing_strategy strategy, bool fromCache)
Iliyan Malchev4765c432012-06-11 14:36:16 -070029{
30 uint32_t device = 0;
31
32 if (fromCache) {
Iliyan Malchev4113f342012-06-11 14:39:47 -070033 ALOGV("getDeviceForStrategy() from cache strategy %d, device %x", strategy, mDeviceForStrategy[strategy]);
Iliyan Malchev4765c432012-06-11 14:36:16 -070034 return mDeviceForStrategy[strategy];
35 }
36
37 switch (strategy) {
38 case STRATEGY_DTMF:
39 if (!isInCall()) {
40 // when off call, DTMF strategy follows the same rules as MEDIA strategy
41 device = getDeviceForStrategy(STRATEGY_MEDIA, false);
42 break;
43 }
44 // when in call, DTMF and PHONE strategies follow the same rules
45 // FALL THROUGH
46
47 case STRATEGY_PHONE:
48 // for phone strategy, we first consider the forced use and then the available devices by order
49 // of priority
50 switch (mForceUse[AudioSystem::FOR_COMMUNICATION]) {
51 case AudioSystem::FORCE_BT_SCO:
52 if (!isInCall() || strategy != STRATEGY_DTMF) {
53 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
54 if (device) break;
55 }
56 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
57 if (device) break;
58 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO;
59 if (device) break;
60 // if SCO device is requested but no SCO device is available, fall back to default case
61 // FALL THROUGH
62
63 default: // FORCE_NONE
64 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_PROXY;
65 if (device) break;
66#ifdef WITH_A2DP
67 // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP
68 if (!isInCall()) {
69 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP;
70 if (device) break;
71 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
72 if (device) break;
73 }
74#endif
75 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET;
76 if (device) break;
77 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL;
78 if (device) break;
79 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET;
80 if (device) break;
81 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE;
82 if (device) break;
83 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET;
84 if (device) break;
85 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE;
86 if (device) break;
87 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_ANC_HEADSET;
88 if (device) break;
89 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_EARPIECE;
90 if (device == 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -070091 ALOGE("getDeviceForStrategy() earpiece device not found");
Iliyan Malchev4765c432012-06-11 14:36:16 -070092 }
93 break;
94
95 case AudioSystem::FORCE_SPEAKER:
96 if (!isInCall() || strategy != STRATEGY_DTMF) {
97 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
98 if (device) break;
99 }
100#ifdef WITH_A2DP
101 // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to
102 // A2DP speaker when forcing to speaker output
103 if (!isInCall()) {
104 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
105 if (device) break;
106 }
107#endif
108 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET;
109 if (device) break;
110 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET;
111 if (device) break;
112 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
113 if (device == 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700114 ALOGE("getDeviceForStrategy() speaker device not found");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700115 }
116 break;
117 }
118#ifdef FM_ENABLED
119 if (mAvailableOutputDevices & AudioSystem::DEVICE_OUT_FM) {
120 device |= AudioSystem::DEVICE_OUT_FM;
121 if (mForceUse[AudioSystem::FOR_MEDIA] == AudioSystem::FORCE_SPEAKER) {
122 device &= ~(AudioSystem::DEVICE_OUT_WIRED_HEADSET);
123 device &= ~(AudioSystem::DEVICE_OUT_WIRED_HEADPHONE);
124 device |= AudioSystem::DEVICE_OUT_SPEAKER;
125 }
126 }
127#endif
128 break;
129
130 case STRATEGY_SONIFICATION:
131
132 // If incall, just select the STRATEGY_PHONE device: The rest of the behavior is handled by
133 // handleIncallSonification().
134 if (isInCall()) {
135 device = getDeviceForStrategy(STRATEGY_PHONE, false);
136 break;
137 }
138 // FALL THROUGH
139
140 case STRATEGY_ENFORCED_AUDIBLE:
141 // strategy STRATEGY_ENFORCED_AUDIBLE uses same routing policy as STRATEGY_SONIFICATION
142 // except when in call where it doesn't default to STRATEGY_PHONE behavior
143
144 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
145 if (device == 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700146 ALOGE("getDeviceForStrategy() speaker device not found");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700147 }
148 // The second device used for sonification is the same as the device used by media strategy
149 // FALL THROUGH
150
151 case STRATEGY_MEDIA: {
152 //To route FM stream to speaker when headset is connected, a new switch case is added.
153 //case AudioSystem::FORCE_SPEAKER for STRATEGY_MEDIA will come only when we need to route
154 //FM stream to speaker.
155 switch (mForceUse[AudioSystem::FOR_MEDIA]) {
156 default:{
157 uint32_t device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_PROXY;
158 if(device2 != 0) {
159 // No combo device allowed with proxy device
160 device = 0;
161 }
162 #ifdef WITH_A2DP
163 if (mA2dpOutput != 0) {
164 if (strategy == STRATEGY_SONIFICATION && !a2dpUsedForSonification()) {
165 break;
166 }
167 if (device2 == 0) {
168 device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP;
169 }
170 if (device2 == 0) {
171 device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
172 }
173 if (device2 == 0) {
174 device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
175 }
176 }
177 #endif
178 if (device2 == 0) {
179 device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET;
180 }
181 if (device2 == 0) {
182 device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL;
183 }
184 if (device2 == 0) {
185 device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET;
186 }
187 if (device2 == 0) {
188 device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE;
189 }
190 if (device2 == 0) {
191 device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET;
192 }
193 if (device2 == 0) {
194 device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE;
195 }
196 if (device2 == 0) {
197 device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_ANC_HEADSET;
198 }
199 if (device2 == 0) {
200 device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_FM_TX;
201 }
202 if (device2 == 0) {
203 device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
204 }
205
206 if (device2 == 0) {
207 device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_EARPIECE;
208 }
209
210 // device is DEVICE_OUT_SPEAKER if we come from case STRATEGY_SONIFICATION or
211 // STRATEGY_ENFORCED_AUDIBLE, 0 otherwise
212 device |= device2;
213 }
214 break;
215 case AudioSystem::FORCE_SPEAKER:
216 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
217 break;
218 }
219#ifdef FM_ENABLED
220 if (mAvailableOutputDevices & AudioSystem::DEVICE_OUT_FM) {
221 device |= AudioSystem::DEVICE_OUT_FM;
222 }
223#endif
224 if (mAvailableOutputDevices & AudioSystem::DEVICE_OUT_ANC_HEADSET) {
225 device |= AudioSystem::DEVICE_OUT_ANC_HEADSET;
226 }
227 if (mAvailableOutputDevices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE) {
228 device |= AudioSystem::DEVICE_OUT_ANC_HEADPHONE;
229 }
230 // Do not play media stream if in call and the requested device would change the hardware
231 // output routing
232 if (mPhoneState == AudioSystem::MODE_IN_CALL &&
233 !AudioSystem::isA2dpDevice((AudioSystem::audio_devices)device) &&
Iliyan Malchev4113f342012-06-11 14:39:47 -0700234 device != getDeviceForStrategy(STRATEGY_PHONE, true)) {
235 device = getDeviceForStrategy(STRATEGY_PHONE, true);
236 ALOGV("getDeviceForStrategy() incompatible media and phone devices");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700237 }
238 } break;
239
240 default:
Iliyan Malchev4113f342012-06-11 14:39:47 -0700241 ALOGW("getDeviceForStrategy() unknown strategy: %d", strategy);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700242 break;
243 }
244
Iliyan Malchev4113f342012-06-11 14:39:47 -0700245 ALOGV("getDeviceForStrategy() strategy %d, device %x", strategy, device);
246 return (audio_devices_t)device;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700247}
248
249
250status_t AudioPolicyManager::setDeviceConnectionState(AudioSystem::audio_devices device,
251 AudioSystem::device_connection_state state,
252 const char *device_address)
253{
254
Iliyan Malchev4113f342012-06-11 14:39:47 -0700255 ALOGV("setDeviceConnectionState() device: %x, state %d, address %s", device, state, device_address);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700256
257 // connect/disconnect only 1 device at a time
258 if (AudioSystem::popCount(device) != 1) return BAD_VALUE;
259
260 if (strlen(device_address) >= MAX_DEVICE_ADDRESS_LEN) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700261 ALOGE("setDeviceConnectionState() invalid address: %s", device_address);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700262 return BAD_VALUE;
263 }
264
265 // handle output devices
266 if (AudioSystem::isOutputDevice(device)) {
267
268#ifndef WITH_A2DP
269 if (AudioSystem::isA2dpDevice(device)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700270 ALOGE("setDeviceConnectionState() invalid device: %x", device);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700271 return BAD_VALUE;
272 }
273#endif
274
275 switch (state)
276 {
277 // handle output device connection
278 case AudioSystem::DEVICE_STATE_AVAILABLE:
279 if (mAvailableOutputDevices & device) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700280 ALOGW("setDeviceConnectionState() device already connected: %x", device);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700281 return INVALID_OPERATION;
282 }
Iliyan Malchev4113f342012-06-11 14:39:47 -0700283 ALOGV("setDeviceConnectionState() connecting device %x", device);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700284
285 // register new device as available
Iliyan Malchev4113f342012-06-11 14:39:47 -0700286 mAvailableOutputDevices = (audio_devices_t)((uint32_t)mAvailableOutputDevices | device);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700287
288#ifdef WITH_A2DP
289 // handle A2DP device connection
290 if (AudioSystem::isA2dpDevice(device)) {
291 status_t status = AudioPolicyManagerBase::handleA2dpConnection(device, device_address);
292 if (status != NO_ERROR) {
293 mAvailableOutputDevices &= ~device;
294 return status;
295 }
296 } else
297#endif
298 {
299 if (AudioSystem::isBluetoothScoDevice(device)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700300 ALOGV("setDeviceConnectionState() BT SCO device, address %s", device_address);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700301 // keep track of SCO device address
302 mScoDeviceAddress = String8(device_address, MAX_DEVICE_ADDRESS_LEN);
303 }
304 }
305 break;
306 // handle output device disconnection
307 case AudioSystem::DEVICE_STATE_UNAVAILABLE: {
308 if (!(mAvailableOutputDevices & device)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700309 ALOGW("setDeviceConnectionState() device not connected: %x", device);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700310 return INVALID_OPERATION;
311 }
312
313
Iliyan Malchev4113f342012-06-11 14:39:47 -0700314 ALOGV("setDeviceConnectionState() disconnecting device %x", device);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700315 // remove device from available output devices
Iliyan Malchev4113f342012-06-11 14:39:47 -0700316 mAvailableOutputDevices = (audio_devices_t)((uint32_t)mAvailableOutputDevices & ~device);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700317
318#ifdef WITH_A2DP
319 // handle A2DP device disconnection
320 if (AudioSystem::isA2dpDevice(device)) {
321 status_t status = AudioPolicyManagerBase::handleA2dpDisconnection(device, device_address);
322 if (status != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700323 mAvailableOutputDevices = (audio_devices_t)((uint32_t)mAvailableOutputDevices | device);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700324 return status;
325 }
326 } else
327#endif
328 {
329 if (AudioSystem::isBluetoothScoDevice(device)) {
330 mScoDeviceAddress = "";
331 }
332 }
333 } break;
334
335 default:
Iliyan Malchev4113f342012-06-11 14:39:47 -0700336 ALOGE("setDeviceConnectionState() invalid state: %x", state);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700337 return BAD_VALUE;
338 }
339
340 // request routing change if necessary
Iliyan Malchev4113f342012-06-11 14:39:47 -0700341 uint32_t newDevice = AudioPolicyManagerBase::getNewDevice(mPrimaryOutput, false);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700342
343 if(newDevice == 0 && mLPADecodeOutput != -1) {
344 newDevice = AudioPolicyManagerBase::getNewDevice(mLPADecodeOutput, false);
345 }
346#ifdef FM_ENABLED
347 if(device == AudioSystem::DEVICE_OUT_FM) {
348 if (state == AudioSystem::DEVICE_STATE_AVAILABLE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700349 mOutputs.valueFor(mPrimaryOutput)->changeRefCount(AudioSystem::FM, 1);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700350 }
351 else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700352 mOutputs.valueFor(mPrimaryOutput)->changeRefCount(AudioSystem::FM, -1);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700353 }
354 if(newDevice == 0){
355 newDevice = getDeviceForStrategy(STRATEGY_MEDIA, false);
356 }
357 AudioParameter param = AudioParameter();
358 param.addInt(String8(AudioParameter::keyHandleFm), (int)newDevice);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700359 mpClientInterface->setParameters(mPrimaryOutput, param.toString());
Iliyan Malchev4765c432012-06-11 14:36:16 -0700360 }
361#endif
362 if(device == AudioSystem::DEVICE_OUT_ANC_HEADPHONE ||
363 device == AudioSystem::DEVICE_OUT_ANC_HEADSET) {
364 if(newDevice == 0){
365 newDevice = getDeviceForStrategy(STRATEGY_MEDIA, false);
366 }
367 }
368#ifdef WITH_A2DP
369 AudioPolicyManagerBase::checkA2dpSuspend();
370 AudioPolicyManagerBase::checkOutputForAllStrategies();
371 // A2DP outputs must be closed after checkOutputForAllStrategies() is executed
372 if (state == AudioSystem::DEVICE_STATE_UNAVAILABLE && AudioSystem::isA2dpDevice(device)) {
373 AudioPolicyManagerBase::closeA2dpOutputs();
374 }
375#endif
376 AudioPolicyManagerBase::updateDeviceForStrategy();
377
378 int delayMs = 0;
379 if (AudioSystem::DEVICE_OUT_SPEAKER == newDevice
380 && AudioSystem::DEVICE_OUT_WIRED_HEADSET == device) {
381 //Add some delay(192ms) while switching from wired headset to speaker before pause
382 //music keeps playing from speaker if there's not delay or delay is too small.
Iliyan Malchev4113f342012-06-11 14:39:47 -0700383 delayMs = mOutputs.valueFor(mPrimaryOutput)->mLatency*8;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700384 }
385
386 if(mLPADecodeOutput != -1)
387 setOutputDevice(mLPADecodeOutput, newDevice, false, delayMs);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700388 setOutputDevice(mPrimaryOutput, newDevice, false, delayMs);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700389
390 if (device == AudioSystem::DEVICE_OUT_WIRED_HEADSET) {
391 device = AudioSystem::DEVICE_IN_WIRED_HEADSET;
392 } else if (device == AudioSystem::DEVICE_OUT_BLUETOOTH_SCO ||
393 device == AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET ||
394 device == AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT) {
395 device = AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET;
396 } else if(device == AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET){
397 device = AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET;
398 } else if(device == AudioSystem::DEVICE_OUT_ANC_HEADSET){
399 device = AudioSystem::DEVICE_IN_ANC_HEADSET; //wait for actual ANC device
400 } else {
401 return NO_ERROR;
402 }
403 }
404 // handle input devices
405 if (AudioSystem::isInputDevice(device)) {
406
407 switch (state)
408 {
409 // handle input device connection
410 case AudioSystem::DEVICE_STATE_AVAILABLE: {
411 if (mAvailableInputDevices & device) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700412 ALOGW("setDeviceConnectionState() device already connected: %d", device);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700413 return INVALID_OPERATION;
414 }
Iliyan Malchev4113f342012-06-11 14:39:47 -0700415 mAvailableInputDevices = (audio_devices_t)(mAvailableInputDevices | device);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700416 }
417 break;
418
419 // handle input device disconnection
420 case AudioSystem::DEVICE_STATE_UNAVAILABLE: {
421 if (!(mAvailableInputDevices & device)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700422 ALOGW("setDeviceConnectionState() device not connected: %d", device);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700423 return INVALID_OPERATION;
424 }
Iliyan Malchev4113f342012-06-11 14:39:47 -0700425 mAvailableInputDevices = (audio_devices_t)((uint32_t)mAvailableInputDevices & ~device);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700426 } break;
427
428 default:
Iliyan Malchev4113f342012-06-11 14:39:47 -0700429 ALOGE("setDeviceConnectionState() invalid state: %x", state);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700430 return BAD_VALUE;
431 }
432
433 audio_io_handle_t activeInput = AudioPolicyManagerBase::getActiveInput();
434 if (activeInput != 0) {
435 AudioInputDescriptor *inputDesc = mInputs.valueFor(activeInput);
436 uint32_t newDevice = AudioPolicyManagerBase::getDeviceForInputSource(inputDesc->mInputSource);
437 if (newDevice != inputDesc->mDevice) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700438 ALOGV("setDeviceConnectionState() changing device from %x to %x for input %d",
Iliyan Malchev4765c432012-06-11 14:36:16 -0700439 inputDesc->mDevice, newDevice, activeInput);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700440 inputDesc->mDevice = (audio_devices_t)newDevice;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700441 AudioParameter param = AudioParameter();
442 param.addInt(String8(AudioParameter::keyRouting), (int)newDevice);
443 mpClientInterface->setParameters(activeInput, param.toString());
444 }
445 }
446
447 return NO_ERROR;
448 }
449
Iliyan Malchev4113f342012-06-11 14:39:47 -0700450 ALOGW("setDeviceConnectionState() invalid device: %x", device);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700451 return BAD_VALUE;
452}
453
454
455void AudioPolicyManager::setPhoneState(int state)
456{
Iliyan Malchev4113f342012-06-11 14:39:47 -0700457 ALOGD("setPhoneState() state %d", state);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700458 uint32_t newDevice = 0;
459 if (state < 0 || state >= AudioSystem::NUM_MODES) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700460 ALOGW("setPhoneState() invalid state %d", state);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700461 return;
462 }
463
464 if (state == mPhoneState ) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700465 ALOGW("setPhoneState() setting same state %d", state);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700466 return;
467 }
468
469 // if leaving call state, handle special case of active streams
470 // pertaining to sonification strategy see handleIncallSonification()
471 if (isInCall()) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700472 ALOGV("setPhoneState() in call state management: new state is %d", state);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700473 for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
474 AudioPolicyManagerBase::handleIncallSonification(stream, false, true);
475 }
476 }
477
478 // store previous phone state for management of sonification strategy below
479 int oldState = mPhoneState;
480 mPhoneState = state;
481 // force routing command to audio hardware when starting call
482 // even if no device change is needed
483 bool force = (mPhoneState == AudioSystem::MODE_IN_CALL);
484
485 // are we entering or starting a call
486 if (!isStateInCall(oldState) && isStateInCall(state)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700487 ALOGV(" Entering call in setPhoneState()");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700488 // force routing command to audio hardware when starting a call
489 // even if no device change is needed
490 force = true;
491 } else if (isStateInCall(oldState) && (state == AudioSystem::MODE_NORMAL)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700492 ALOGV(" Exiting call in setPhoneState()");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700493 // force routing command to audio hardware when exiting a call
494 // even if no device change is needed
495 force = true;
496 } else if (isStateInCall(state) && (state != oldState)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700497 ALOGV(" Switching between telephony and VoIP in setPhoneState()");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700498 // force routing command to audio hardware when switching between telephony and VoIP
499 // even if no device change is needed
500 force = true;
501 }
502
503 // check for device and output changes triggered by new phone state
Iliyan Malchev4113f342012-06-11 14:39:47 -0700504 newDevice = AudioPolicyManagerBase::getNewDevice(mPrimaryOutput, false);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700505 if (newDevice == 0 && (mLPADecodeOutput != -1 &&
506 mOutputs.valueFor(mLPADecodeOutput)->isUsedByStrategy(STRATEGY_MEDIA))) {
507 newDevice = getDeviceForStrategy(STRATEGY_MEDIA, false);
508 }
509
510#ifdef WITH_A2DP
511 AudioPolicyManagerBase::checkA2dpSuspend();
512 AudioPolicyManagerBase::checkOutputForAllStrategies();
513#endif
514 AudioPolicyManagerBase::updateDeviceForStrategy();
515
Iliyan Malchev4113f342012-06-11 14:39:47 -0700516 AudioOutputDescriptor *hwOutputDesc = mOutputs.valueFor(mPrimaryOutput);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700517
518 // force routing command to audio hardware when ending call
519 // even if no device change is needed
520 if (isStateInCall(oldState) && newDevice == 0) {
521 newDevice = hwOutputDesc->device();
522 if(state == AudioSystem::MODE_NORMAL) {
523 force = true;
524 }
525 }
526
527 // when changing from ring tone to in call mode, mute the ringing tone
528 // immediately and delay the route change to avoid sending the ring tone
529 // tail into the earpiece or headset.
530 int delayMs = 0;
531 if (isStateInCall(state) && oldState == AudioSystem::MODE_RINGTONE) {
532 // delay the device change command by twice the output latency to have some margin
533 // and be sure that audio buffers not yet affected by the mute are out when
534 // we actually apply the route change
535 delayMs = hwOutputDesc->mLatency*2;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700536 setStreamMute(AudioSystem::RING, true, mPrimaryOutput);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700537 }
538
539 // change routing is necessary
Iliyan Malchev4113f342012-06-11 14:39:47 -0700540 setOutputDevice(mPrimaryOutput, newDevice, force, delayMs);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700541
542 // if entering in call state, handle special case of active streams
543 // pertaining to sonification strategy see handleIncallSonification()
544 if (isStateInCall(state)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700545 ALOGV("setPhoneState() in call state management: new state is %d", state);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700546 // unmute the ringing tone after a sufficient delay if it was muted before
547 // setting output device above
548 if (oldState == AudioSystem::MODE_RINGTONE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700549 setStreamMute(AudioSystem::RING, false, mPrimaryOutput, MUTE_TIME_MS);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700550 }
551 for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
552 AudioPolicyManagerBase::handleIncallSonification(stream, true, true);
553 }
554 }
555
556 // Flag that ringtone volume must be limited to music volume until we exit MODE_RINGTONE
557 if (state == AudioSystem::MODE_RINGTONE &&
558 (hwOutputDesc->mRefCount[AudioSystem::MUSIC] ||
559 (systemTime() - hwOutputDesc->mStopTime[AudioSystem::MUSIC]) < seconds(SONIFICATION_HEADSET_MUSIC_DELAY))) {
560 // (systemTime() - mMusicStopTime) < seconds(SONIFICATION_HEADSET_MUSIC_DELAY))) {
561 mLimitRingtoneVolume = true;
562 } else {
563 mLimitRingtoneVolume = false;
564 }
565}
566
567#ifdef TUNNEL_LPA_ENABLED
568audio_io_handle_t AudioPolicyManager::getSession(AudioSystem::stream_type stream,
569 uint32_t format,
570 AudioSystem::output_flags flags,
571 int32_t sessionId,
572 uint32_t samplingRate,
573 uint32_t channels)
574{
575 audio_io_handle_t output = 0;
576 uint32_t latency = 0;
577 routing_strategy strategy = getStrategy((AudioSystem::stream_type)stream);
578 uint32_t device = getDeviceForStrategy(strategy);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700579 ALOGV("getSession() stream %d, format %d, sessionId %x, flags %x device %d", stream, format, sessionId, flags, device);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700580 AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();
581 outputDesc->mDevice = device;
582 outputDesc->mSamplingRate = 0;
583 outputDesc->mFormat = format;
584 outputDesc->mChannels = 2;
585 outputDesc->mLatency = 0;
586 outputDesc->mFlags = (AudioSystem::output_flags)(flags | AudioSystem::OUTPUT_FLAG_DIRECT);
587 outputDesc->mRefCount[stream] = 0;
588 output = mpClientInterface->openSession(&outputDesc->mDevice,
589 &outputDesc->mFormat,
590 outputDesc->mFlags,
591 stream,
592 sessionId,
593 samplingRate,
594 channels);
595
596 // only accept an output with the requeted parameters
597 if ((format != 0 && format != outputDesc->mFormat) || !output) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700598 ALOGE("openSession() failed opening a session: format %d, sessionId %d output %d",
Iliyan Malchev4765c432012-06-11 14:36:16 -0700599 format, sessionId, output);
600 if(output) {
601 mpClientInterface->closeSession(output);
602 }
603 delete outputDesc;
604 return 0;
605 }
606
607 //reset it here, it will get updated in startoutput
608 outputDesc->mDevice = 0;
609
610 mOutputs.add(output, outputDesc);
611 mLPADecodeOutput = output;
612 mLPAStreamType = stream;
613 return output;
614}
615
616void AudioPolicyManager::pauseSession(audio_io_handle_t output, AudioSystem::stream_type stream)
617{
Iliyan Malchev4113f342012-06-11 14:39:47 -0700618 ALOGV("pauseSession() Output [%d] and stream is [%d]", output, stream);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700619
620 if ( (output == mLPADecodeOutput) &&
621 (stream == mLPAStreamType) ) {
622 AudioPolicyManager::stopOutput(output, mLPAStreamType);
623 mLPAActiveOuput = mLPADecodeOutput;
624 mLPAActiveStreamType = mLPAStreamType;
625 mLPADecodeOutput = -1;
626 mLPAStreamType = AudioSystem::DEFAULT;
627 mLPAMuted = false;
628 }
629}
630
631void AudioPolicyManager::resumeSession(audio_io_handle_t output, AudioSystem::stream_type stream)
632{
Iliyan Malchev4113f342012-06-11 14:39:47 -0700633 ALOGV("resumeSession() Output [%d] and stream is [%d]", output, stream);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700634
635 if (output == mLPAActiveOuput)
636 {
637 mLPADecodeOutput = mLPAActiveOuput;
638 mLPAStreamType = stream;
639 AudioPolicyManager::startOutput(mLPADecodeOutput, mLPAStreamType);
640
641 // Set Volume if the music stream volume is changed in the Pause state of LPA Jagan
642 mLPAActiveOuput = -1;
643 mLPAActiveStreamType = AudioSystem::DEFAULT;
644 }
645}
646
647void AudioPolicyManager::releaseSession(audio_io_handle_t output)
648{
Iliyan Malchev4113f342012-06-11 14:39:47 -0700649 ALOGV("releaseSession() %d", output);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700650
651 // This means the Output is put into Pause state
652 if (output == mLPAActiveOuput && mLPADecodeOutput == -1) {
653 mLPADecodeOutput = mLPAActiveOuput;
654 mLPAStreamType = mLPAActiveStreamType;
655 }
656
657 ssize_t index = mOutputs.indexOfKey(output);
658 if (index < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700659 ALOGW("releaseSession() releasing unknown output %d", output);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700660 return;
661 }
662
663 AudioPolicyManager::stopOutput(output, mLPAStreamType);
664 delete mOutputs.valueAt(index);
665 mOutputs.removeItem(output);
666 mLPADecodeOutput = -1;
667 mLPAActiveOuput = -1;
668 mLPAStreamType = AudioSystem::DEFAULT;
669 mLPAActiveStreamType = AudioSystem::DEFAULT;
670 mLPAMuted = false;
671}
672#endif
673
674status_t AudioPolicyManager::startOutput(audio_io_handle_t output, AudioSystem::stream_type stream, int session)
675{
Iliyan Malchev4113f342012-06-11 14:39:47 -0700676 ALOGV("startOutput() output %d, stream %d", output, stream);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700677 ssize_t index = mOutputs.indexOfKey(output);
678 if (index < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700679 ALOGW("startOutput() unknow output %d", output);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700680 return BAD_VALUE;
681 }
682
683 AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index);
684 routing_strategy strategy = getStrategy((AudioSystem::stream_type)stream);
685
686#ifdef WITH_A2DP
687 if (mA2dpOutput != 0 && !a2dpUsedForSonification() &&
688 (strategy == STRATEGY_SONIFICATION || strategy == STRATEGY_ENFORCED_AUDIBLE)) {
689 setStrategyMute(STRATEGY_MEDIA, true, mA2dpOutput);
690 }
691#endif
692
693 // incremenent usage count for this stream on the requested output:
694 // NOTE that the usage count is the same for duplicated output and hardware output which is
695 // necassary for a correct control of hardware output routing by startOutput() and stopOutput()
696 outputDesc->changeRefCount(stream, 1);
697#ifdef FM_ENABLED
698 if(stream == AudioSystem::FM && output == mA2dpOutput) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700699 setOutputDevice(output, AudioPolicyManagerBase::getNewDevice(output, true), true);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700700 } else
701#endif
702#ifdef TUNNEL_LPA_ENABLED
703 if (output != mLPADecodeOutput) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700704 setOutputDevice(output, AudioPolicyManagerBase::getNewDevice(output, true));
Iliyan Malchev4765c432012-06-11 14:36:16 -0700705 } else
706#endif
707 {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700708 setOutputDevice(output, AudioPolicyManagerBase::getNewDevice(output, true), true);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700709 }
710
711 // handle special case for sonification while in call
712 if (isInCall()) {
713 AudioPolicyManagerBase::handleIncallSonification(stream, true, false);
714 }
715
716 // apply volume rules for current stream and device if necessary
Iliyan Malchev4113f342012-06-11 14:39:47 -0700717 checkAndSetVolume((int)stream, mStreams[stream].mIndexCur.valueFor(outputDesc->device()), output, outputDesc->device());
Iliyan Malchev4765c432012-06-11 14:36:16 -0700718
719 return NO_ERROR;
720}
721
722status_t AudioPolicyManager::stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream, int session)
723{
Iliyan Malchev4113f342012-06-11 14:39:47 -0700724 ALOGV("stopOutput() output %d, stream %d", output, stream);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700725 ssize_t index = mOutputs.indexOfKey(output);
726 if (index < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700727 ALOGW("stopOutput() unknow output %d", output);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700728 return BAD_VALUE;
729 }
730
731 AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index);
732 routing_strategy strategy = AudioPolicyManagerBase::getStrategy((AudioSystem::stream_type)stream);
733
734 // handle special case for sonification while in call
735 if (isInCall()) {
736 AudioPolicyManagerBase::handleIncallSonification(stream, false, false);
737 }
738
739 if (outputDesc->mRefCount[stream] > 0) {
740 // decrement usage count of this stream on the output
741 outputDesc->changeRefCount(stream, -1);
742 // store time at which the last music track was stopped - see computeVolume()
743 if (stream == AudioSystem::MUSIC) {
744 outputDesc->mStopTime[stream] = systemTime();
745 // mMusicStopTime = systemTime();
746 }
747
Iliyan Malchev4113f342012-06-11 14:39:47 -0700748 uint32_t newDevice = AudioPolicyManagerBase::getNewDevice(mPrimaryOutput, false);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700749
750 if(newDevice == 0 && mLPADecodeOutput != -1) {
751 newDevice = AudioPolicyManagerBase::getNewDevice(mLPADecodeOutput, false);
752 }
753
754 setOutputDevice(output, newDevice);
755
756#ifdef WITH_A2DP
757 if (mA2dpOutput != 0 && !a2dpUsedForSonification() &&
758 (strategy == STRATEGY_SONIFICATION || strategy == STRATEGY_ENFORCED_AUDIBLE)) {
759 setStrategyMute(STRATEGY_MEDIA,
760 false,
761 mA2dpOutput,
Iliyan Malchev4113f342012-06-11 14:39:47 -0700762 mOutputs.valueFor(mPrimaryOutput)->mLatency*2);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700763 }
764#endif
Iliyan Malchev4113f342012-06-11 14:39:47 -0700765 if (output != mPrimaryOutput) {
766 setOutputDevice(mPrimaryOutput, AudioPolicyManagerBase::getNewDevice(mPrimaryOutput, true), true);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700767 }
768 return NO_ERROR;
769 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700770 ALOGW("stopOutput() refcount is already 0 for output %d", output);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700771 return INVALID_OPERATION;
772 }
773}
774// ----------------------------------------------------------------------------
775// AudioPolicyManagerALSA
776// ----------------------------------------------------------------------------
777
778// --- class factory
779
780extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)
781{
782 return new AudioPolicyManager(clientInterface);
783}
784
785extern "C" void destroyAudioPolicyManager(AudioPolicyInterface *interface)
786{
787 delete interface;
788}
789
790// ---
791
792void AudioPolicyManager::setOutputDevice(audio_io_handle_t output, uint32_t device, bool force, int delayMs)
793{
Iliyan Malchev4113f342012-06-11 14:39:47 -0700794 ALOGV("setOutputDevice() output %d device %x delayMs %d", output, device, delayMs);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700795 AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output);
796
797
798 if (outputDesc->isDuplicated()) {
799 setOutputDevice(outputDesc->mOutput1->mId, device, force, delayMs);
800 setOutputDevice(outputDesc->mOutput2->mId, device, force, delayMs);
801 return;
802 }
803#ifdef WITH_A2DP
804 // filter devices according to output selected
805 if (output == mA2dpOutput) {
806 device &= AudioSystem::DEVICE_OUT_ALL_A2DP;
807 } else {
808 device &= ~AudioSystem::DEVICE_OUT_ALL_A2DP;
809 }
810#endif
811
812 uint32_t prevDevice = (uint32_t)outputDesc->device();
813 // Do not change the routing if:
814 // - the requestede device is 0
815 // - the requested device is the same as current device and force is not specified.
816 // Doing this check here allows the caller to call setOutputDevice() without conditions
817 if ((device == 0 || device == prevDevice) && !force) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700818 ALOGV("setOutputDevice() setting same device %x or null device for output %d", device, output);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700819 return;
820 }
821
Iliyan Malchev4113f342012-06-11 14:39:47 -0700822 outputDesc->mDevice = (audio_devices_t)device;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700823 // mute media streams if both speaker and headset are selected
824 if (device == (AudioSystem::DEVICE_OUT_SPEAKER | AudioSystem::DEVICE_OUT_WIRED_HEADSET)
825 || device == (AudioSystem::DEVICE_OUT_SPEAKER | AudioSystem::DEVICE_OUT_ANC_HEADSET)
826 || device == (AudioSystem::DEVICE_OUT_SPEAKER | AudioSystem::DEVICE_OUT_ANC_HEADPHONE)
827 || device == (AudioSystem::DEVICE_OUT_SPEAKER | AudioSystem::DEVICE_OUT_WIRED_HEADPHONE)
828 || device == (AudioSystem::DEVICE_OUT_SPEAKER | AudioSystem::DEVICE_OUT_WIRED_HEADSET | AudioSystem::DEVICE_OUT_FM)
829 || device == (AudioSystem::DEVICE_OUT_SPEAKER | AudioSystem::DEVICE_OUT_WIRED_HEADPHONE | AudioSystem::DEVICE_OUT_FM)
830 || device == (AudioSystem::DEVICE_OUT_SPEAKER | AudioSystem::DEVICE_OUT_FM_TX)) {
831 setStrategyMute(STRATEGY_MEDIA, true, output);
832 // Mute LPA output also if it belongs to STRATEGY_MEDIA
833 if(((mLPADecodeOutput != -1) && (mLPADecodeOutput != output) &&
834 mOutputs.valueFor(mLPADecodeOutput)->isUsedByStrategy(STRATEGY_MEDIA))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700835 ALOGV("setOutputDevice: Muting mLPADecodeOutput:%d",mLPADecodeOutput);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700836 setStrategyMute(STRATEGY_MEDIA, true, mLPADecodeOutput);
837 }
838 // Mute hardware output also if it belongs to STRATEGY_MEDIA
Iliyan Malchev4113f342012-06-11 14:39:47 -0700839 if(((mPrimaryOutput != -1) && (mPrimaryOutput != output) &&
840 mOutputs.valueFor(mPrimaryOutput)->isUsedByStrategy(STRATEGY_MEDIA))) {
841 ALOGV("setOutputDevice: Muting mPrimaryOutput:%d",mPrimaryOutput);
842 setStrategyMute(STRATEGY_MEDIA, true, mPrimaryOutput);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700843 }
844 // wait for the PCM output buffers to empty before proceeding with the rest of the command
845 usleep(outputDesc->mLatency*2*1000);
846 }
847
848 // wait for output buffers to be played on the HDMI device before routing to new device
849 if(prevDevice == AudioSystem::DEVICE_OUT_AUX_DIGITAL) {
850 if((mLPADecodeOutput != -1 && output == mLPADecodeOutput &&
851 mOutputs.valueFor(mLPADecodeOutput)->isUsedByStrategy(STRATEGY_MEDIA))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700852 checkAndSetVolume(AudioSystem::MUSIC,
853 mStreams[AudioSystem::MUSIC].mIndexCur.valueFor((audio_devices_t)device),
854 mLPADecodeOutput, (audio_devices_t)device, delayMs, force);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700855 usleep(150*1000);
856 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700857 checkAndSetVolume(AudioSystem::MUSIC,
858 mStreams[AudioSystem::MUSIC].mIndexCur.valueFor((audio_devices_t)device),
859 output, (audio_devices_t)device, delayMs, force);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700860 usleep(outputDesc->mLatency*6*1000);
861 }
862 }
863
864 // do the routing
865 AudioParameter param = AudioParameter();
866 param.addInt(String8(AudioParameter::keyRouting), (int)device);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700867 mpClientInterface->setParameters(mPrimaryOutput, param.toString(), delayMs);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700868 // update stream volumes according to new device
Iliyan Malchev4113f342012-06-11 14:39:47 -0700869 AudioPolicyManagerBase::applyStreamVolumes(output, (audio_devices_t)device, delayMs);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700870 if((mLPADecodeOutput != -1 &&
871 mOutputs.valueFor(mLPADecodeOutput)->isUsedByStrategy(STRATEGY_MEDIA))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700872 AudioPolicyManagerBase::applyStreamVolumes(mLPADecodeOutput, (audio_devices_t)device, delayMs);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700873 }
874
875 // if changing from a combined headset + speaker route, unmute media streams
876 if (prevDevice == (AudioSystem::DEVICE_OUT_SPEAKER | AudioSystem::DEVICE_OUT_WIRED_HEADSET)
877 || prevDevice == (AudioSystem::DEVICE_OUT_SPEAKER | AudioSystem::DEVICE_OUT_ANC_HEADSET)
878 || prevDevice == (AudioSystem::DEVICE_OUT_SPEAKER | AudioSystem::DEVICE_OUT_ANC_HEADPHONE)
879 || prevDevice == (AudioSystem::DEVICE_OUT_SPEAKER | AudioSystem::DEVICE_OUT_WIRED_HEADPHONE)
880 || prevDevice == (AudioSystem::DEVICE_OUT_SPEAKER | AudioSystem::DEVICE_OUT_WIRED_HEADSET | AudioSystem::DEVICE_OUT_FM)
881 || prevDevice == (AudioSystem::DEVICE_OUT_SPEAKER | AudioSystem::DEVICE_OUT_WIRED_HEADPHONE | AudioSystem::DEVICE_OUT_FM)
882 || prevDevice == (AudioSystem::DEVICE_OUT_SPEAKER | AudioSystem::DEVICE_OUT_FM_TX)) {
883 setStrategyMute(STRATEGY_MEDIA, false, output, delayMs);
884 // Unmute LPA output also if it belongs to STRATEGY_MEDIA
885 if(((mLPADecodeOutput != -1) && (mLPADecodeOutput != output) &&
886 mOutputs.valueFor(mLPADecodeOutput)->isUsedByStrategy(STRATEGY_MEDIA))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700887 ALOGV("setOutputDevice: Unmuting mLPADecodeOutput:%d delayMs:%d",mLPADecodeOutput,delayMs);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700888 setStrategyMute(STRATEGY_MEDIA, false, mLPADecodeOutput, delayMs);
889 }
890 // Unmute hardware output also if it belongs to STRATEGY_MEDIA
Iliyan Malchev4113f342012-06-11 14:39:47 -0700891 if(((mPrimaryOutput != -1) && (mPrimaryOutput != output) &&
892 mOutputs.valueFor(mPrimaryOutput)->isUsedByStrategy(STRATEGY_MEDIA))) {
893 ALOGV("setOutputDevice: Unmuting mPrimaryOutput:%d delayMs:%d",mPrimaryOutput,delayMs);
894 setStrategyMute(STRATEGY_MEDIA, false, mPrimaryOutput, delayMs);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700895 }
896 }
897}
898
899status_t AudioPolicyManager::checkAndSetVolume(int stream, int index, audio_io_handle_t output, uint32_t device, int delayMs, bool force)
900{
901 // do not change actual stream volume if the stream is muted
902 if ((mOutputs.valueFor(output)->mMuteCount[stream] != 0 && output != mLPADecodeOutput) ||
903 (output == mLPADecodeOutput && stream == mLPAStreamType && mLPAMuted == true)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700904 ALOGV("checkAndSetVolume() stream %d muted count %d", stream, mOutputs.valueFor(output)->mMuteCount[stream]);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700905 return NO_ERROR;
906 }
907
908 // do not change in call volume if bluetooth is connected and vice versa
909 if ((stream == AudioSystem::VOICE_CALL && mForceUse[AudioSystem::FOR_COMMUNICATION] == AudioSystem::FORCE_BT_SCO) ||
910 (stream == AudioSystem::BLUETOOTH_SCO && mForceUse[AudioSystem::FOR_COMMUNICATION] != AudioSystem::FORCE_BT_SCO)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700911 ALOGV("checkAndSetVolume() cannot set stream %d volume with force use = %d for comm",
Iliyan Malchev4765c432012-06-11 14:36:16 -0700912 stream, mForceUse[AudioSystem::FOR_COMMUNICATION]);
913 return INVALID_OPERATION;
914 }
915
Iliyan Malchev4113f342012-06-11 14:39:47 -0700916 float volume = computeVolume(stream, index, output, (audio_devices_t)device);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700917 // do not set volume if the float value did not change
918 if ((volume != mOutputs.valueFor(output)->mCurVolume[stream]) || (stream == AudioSystem::VOICE_CALL) ||
919#ifdef FM_ENABLED
920 (stream == AudioSystem::FM) ||
921#endif
922 force) {
923 mOutputs.valueFor(output)->mCurVolume[stream] = volume;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700924 ALOGD("setStreamVolume() for output %d stream %d, volume %f, delay %d", output, stream, volume, delayMs);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700925 if (stream == AudioSystem::VOICE_CALL ||
926 stream == AudioSystem::DTMF ||
927 stream == AudioSystem::BLUETOOTH_SCO) {
928 float voiceVolume = -1.0;
929 // offset value to reflect actual hardware volume that never reaches 0
930 // 1% corresponds roughly to first step in VOICE_CALL stream volume setting (see AudioService.java)
931 volume = 0.01 + 0.99 * volume;
932 if (stream == AudioSystem::VOICE_CALL) {
933 voiceVolume = (float)index/(float)mStreams[stream].mIndexMax;
934 } else if (stream == AudioSystem::BLUETOOTH_SCO) {
935 String8 key ("bt_headset_vgs");
936 mpClientInterface->getParameters(output,key);
937 AudioParameter result(mpClientInterface->getParameters(0,key));
938 int value;
939 if(result.getInt(String8("isVGS"),value) == NO_ERROR){
Iliyan Malchev4113f342012-06-11 14:39:47 -0700940 ALOGD("BT-SCO Voice Volume %f",(float)index/(float)mStreams[stream].mIndexMax);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700941 voiceVolume = 1.0;
942 } else {
943 voiceVolume = (float)index/(float)mStreams[stream].mIndexMax;
944 }
945 }
Iliyan Malchev4113f342012-06-11 14:39:47 -0700946 if (voiceVolume >= 0 && output == mPrimaryOutput) {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700947 mpClientInterface->setVoiceVolume(voiceVolume, delayMs);
948 }
949 }
950#ifdef FM_ENABLED
951 else if (stream == AudioSystem::FM) {
952 float fmVolume = -1.0;
953 fmVolume = computeVolume(stream, index, output, device);
954 if (fmVolume >= 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700955 if(output == mPrimaryOutput)
Iliyan Malchev4765c432012-06-11 14:36:16 -0700956 mpClientInterface->setFmVolume(fmVolume, delayMs);
957 else if(output == mA2dpOutput)
958 mpClientInterface->setStreamVolume((AudioSystem::stream_type)stream, volume, output, delayMs);
959 }
960 return NO_ERROR;
961 }
962#endif
963 mpClientInterface->setStreamVolume((AudioSystem::stream_type)stream, volume, output, delayMs);
964 }
965
966 return NO_ERROR;
967}
968
969void AudioPolicyManager::setStreamMute(int stream, bool on, audio_io_handle_t output, int delayMs)
970{
971 StreamDescriptor &streamDesc = mStreams[stream];
972 AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output);
973
Iliyan Malchev4113f342012-06-11 14:39:47 -0700974 ALOGV("setStreamMute() stream %d, mute %d, output %d, mMuteCount %d", stream, on, output, outputDesc->mMuteCount[stream]);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700975
976 if (on) {
977 if ((outputDesc->mMuteCount[stream] == 0 && output != mLPADecodeOutput) ||
978 (output == mLPADecodeOutput && stream == mLPAStreamType && false == mLPAMuted)) {
979 if (streamDesc.mCanBeMuted) {
980 checkAndSetVolume(stream, 0, output, outputDesc->device(), delayMs);
981 }
982 }
983 // increment mMuteCount after calling checkAndSetVolume() so that volume change is not ignored
984 if(output == mLPADecodeOutput) {
985 if(stream == mLPAStreamType && false == mLPAMuted) {
986 mLPAMuted = true;
987 }
988 } else {
989 outputDesc->mMuteCount[stream]++;
990 }
991 } else {
992 if ((outputDesc->mMuteCount[stream] == 0 && output != mLPADecodeOutput) ||
993 (output == mLPADecodeOutput && stream == mLPAStreamType && false == mLPAMuted)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700994 ALOGW("setStreamMute() unmuting non muted stream!");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700995 return;
996 }
997 if(output == mLPADecodeOutput) {
998 if(stream == mLPAStreamType && true == mLPAMuted) {
999 mLPAMuted = false;
Iliyan Malchev4113f342012-06-11 14:39:47 -07001000 checkAndSetVolume(stream, streamDesc.mIndexCur.valueFor(outputDesc->device()), output, outputDesc->device(), delayMs);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001001 }
1002 } else {
1003 if(--outputDesc->mMuteCount[stream] == 0){
Iliyan Malchev4113f342012-06-11 14:39:47 -07001004 checkAndSetVolume(stream, streamDesc.mIndexCur.valueFor(outputDesc->device()), output, outputDesc->device(), delayMs);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001005 }
1006 }
1007 }
1008}
1009
1010void AudioPolicyManager::setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config)
1011{
Iliyan Malchev4113f342012-06-11 14:39:47 -07001012 ALOGD("setForceUse() usage %d, config %d, mPhoneState %d", usage, config, mPhoneState);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001013
1014 bool forceVolumeReeval = false;
1015 switch(usage) {
1016 case AudioSystem::FOR_COMMUNICATION:
1017 if (config != AudioSystem::FORCE_SPEAKER && config != AudioSystem::FORCE_BT_SCO &&
1018 config != AudioSystem::FORCE_NONE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001019 ALOGW("setForceUse() invalid config %d for FOR_COMMUNICATION", config);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001020 return;
1021 }
1022 mForceUse[usage] = config;
1023 break;
1024 case AudioSystem::FOR_MEDIA:
1025 if (config != AudioSystem::FORCE_HEADPHONES && config != AudioSystem::FORCE_BT_A2DP &&
1026 config != AudioSystem::FORCE_WIRED_ACCESSORY && config != AudioSystem::FORCE_NONE &&
1027 config != AudioSystem::FORCE_SPEAKER) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001028 ALOGW("setForceUse() invalid config %d for FOR_MEDIA", config);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001029 return;
1030 }
1031 mForceUse[usage] = config;
1032 {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001033 uint32_t device = getDeviceForStrategy(STRATEGY_MEDIA, true);
1034 setOutputDevice(mPrimaryOutput, device);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001035 }
1036 break;
1037 case AudioSystem::FOR_RECORD:
1038 if (config != AudioSystem::FORCE_BT_SCO && config != AudioSystem::FORCE_WIRED_ACCESSORY &&
1039 config != AudioSystem::FORCE_NONE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001040 ALOGW("setForceUse() invalid config %d for FOR_RECORD", config);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001041 return;
1042 }
1043 mForceUse[usage] = config;
1044 break;
1045 case AudioSystem::FOR_DOCK:
1046 if (config != AudioSystem::FORCE_NONE && config != AudioSystem::FORCE_BT_CAR_DOCK &&
1047 config != AudioSystem::FORCE_BT_DESK_DOCK && config != AudioSystem::FORCE_WIRED_ACCESSORY) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001048 ALOGW("setForceUse() invalid config %d for FOR_DOCK", config);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001049 }
1050 forceVolumeReeval = true;
1051 mForceUse[usage] = config;
1052 break;
1053 default:
Iliyan Malchev4113f342012-06-11 14:39:47 -07001054 ALOGW("setForceUse() invalid usage %d", usage);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001055 break;
1056 }
1057
1058 // check for device and output changes triggered by new phone state
Iliyan Malchev4113f342012-06-11 14:39:47 -07001059 uint32_t newDevice = getNewDevice(mPrimaryOutput, false);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001060#ifdef WITH_A2DP
1061 AudioPolicyManagerBase::checkA2dpSuspend();
1062 checkOutputForAllStrategies();
1063#endif
1064 updateDeviceForStrategy();
Iliyan Malchev4113f342012-06-11 14:39:47 -07001065 setOutputDevice(mPrimaryOutput, newDevice);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001066 if (forceVolumeReeval) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001067 applyStreamVolumes(mPrimaryOutput, (audio_devices_t)newDevice);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001068 }
1069}
1070
Iliyan Malchev4113f342012-06-11 14:39:47 -07001071audio_devices_t AudioPolicyManager::getDeviceForInputSource(int inputSource)
Iliyan Malchev4765c432012-06-11 14:36:16 -07001072{
1073 uint32_t device;
1074
1075 switch(inputSource) {
1076 case AUDIO_SOURCE_DEFAULT:
1077 case AUDIO_SOURCE_MIC:
1078 case AUDIO_SOURCE_VOICE_RECOGNITION:
1079 if (mForceUse[AudioSystem::FOR_RECORD] == AudioSystem::FORCE_BT_SCO &&
1080 mAvailableInputDevices & AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
1081 device = AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET;
1082 } else if (mAvailableInputDevices & AudioSystem::DEVICE_IN_WIRED_HEADSET) {
1083 device = AudioSystem::DEVICE_IN_WIRED_HEADSET;
1084 } else if (mAvailableInputDevices & AudioSystem::DEVICE_IN_ANC_HEADSET) {
1085 device = AudioSystem::DEVICE_IN_ANC_HEADSET;
1086 } else if (mAvailableInputDevices & AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET) {
1087 device = AudioSystem::DEVICE_IN_PROXY;
1088 } else {
1089 device = AudioSystem::DEVICE_IN_BUILTIN_MIC;
1090 }
1091 break;
1092 case AUDIO_SOURCE_VOICE_COMMUNICATION:
1093 device = AudioSystem::DEVICE_IN_COMMUNICATION;
1094 break;
1095 case AUDIO_SOURCE_CAMCORDER:
1096 if (hasBackMicrophone()) {
1097 device = AudioSystem::DEVICE_IN_BACK_MIC;
1098 } else {
1099 device = AudioSystem::DEVICE_IN_BUILTIN_MIC;
1100 }
1101 break;
1102 case AUDIO_SOURCE_VOICE_UPLINK:
1103 case AUDIO_SOURCE_VOICE_DOWNLINK:
1104 case AUDIO_SOURCE_VOICE_CALL:
1105 device = AudioSystem::DEVICE_IN_VOICE_CALL;
1106 break;
Iliyan Malchev4113f342012-06-11 14:39:47 -07001107#if 0
Iliyan Malchev4765c432012-06-11 14:36:16 -07001108 case AUDIO_SOURCE_FM_RX:
1109 device = AudioSystem::DEVICE_IN_FM_RX;
1110 break;
1111 case AUDIO_SOURCE_FM_RX_A2DP:
1112 device = AudioSystem::DEVICE_IN_FM_RX_A2DP;
1113 break;
Iliyan Malchev4113f342012-06-11 14:39:47 -07001114#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001115 default:
Iliyan Malchev4113f342012-06-11 14:39:47 -07001116 ALOGW("getInput() invalid input source %d", inputSource);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001117 device = 0;
1118 break;
1119 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001120 ALOGV("getDeviceForInputSource()input source %d, device %08x", inputSource, device);
1121 if (!device)
1122 ALOGE("%s: did not select device for input source %d",
1123 __FUNCTION__, inputSource);
1124 return (audio_devices_t)device;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001125}
1126
1127/*
1128Overwriting this function from base class to allow 2 acitve AudioRecord clients in case of FM.
1129One for FM A2DP playbck and other for FM recording.
1130*/
1131status_t AudioPolicyManager::startInput(audio_io_handle_t input)
1132{
Iliyan Malchev4113f342012-06-11 14:39:47 -07001133 ALOGV("startInput() input %d", input);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001134 ssize_t index = mInputs.indexOfKey(input);
1135 if (index < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001136 ALOGW("startInput() unknow input %d", input);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001137 return BAD_VALUE;
1138 }
1139 AudioInputDescriptor *inputDesc = mInputs.valueAt(index);
1140 AudioParameter param = AudioParameter();
1141 param.addInt(String8(AudioParameter::keyRouting), (int)inputDesc->mDevice);
1142 // use Voice Recognition mode or not for this input based on input source
1143 int vr_enabled = inputDesc->mInputSource == AUDIO_SOURCE_VOICE_RECOGNITION ? 1 : 0;
1144 param.addInt(String8("vr_mode"), vr_enabled);
Iliyan Malchev4113f342012-06-11 14:39:47 -07001145 ALOGV("AudioPolicyManager::startInput(%d), setting vr_mode to %d", inputDesc->mInputSource, vr_enabled);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001146 mpClientInterface->setParameters(input, param.toString());
1147 inputDesc->mRefCount = 1;
1148 return NO_ERROR;
1149}
1150
1151}; // namespace androidi_audio_legacy