msm8660: Update policy manager for MR1
* From 7x30 HAL
Change-Id: I4dc080e1fe3f81cb6e6ba3aa0e51c43143cd5b11
diff --git a/msm8660/AudioHardware.cpp b/msm8660/AudioHardware.cpp
index 4eb6d71..fb08523 100644
--- a/msm8660/AudioHardware.cpp
+++ b/msm8660/AudioHardware.cpp
@@ -17,7 +17,7 @@
#include <math.h>
-//#define LOG_NDEBUG 0
+#define LOG_NDEBUG 0
#define LOG_TAG "AudioHardwareMSM8660"
#include <utils/Log.h>
#include <utils/String8.h>
@@ -1040,9 +1040,14 @@
AudioStreamOut* AudioHardware::openOutputStream(
uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status)
{
+ ALOGD("AudioHardware::openOutputStream devices %x format %d channels %d samplerate %d",
+ devices, *format, *channels, *sampleRate);
+
+ audio_output_flags_t flags = static_cast<audio_output_flags_t> (*status);
+
{ // scope for the lock
status_t lStatus;
- audio_output_flags_t flags = static_cast<audio_output_flags_t> (*status);
+
Mutex::Autolock lock(mLock);
#ifdef QCOM_VOIP_ENABLED
// only one output stream allowed
@@ -1054,7 +1059,6 @@
ALOGE(" AudioHardware::openOutputStream Only one output stream allowed \n");
return 0;
}
-
if ((flags & AUDIO_OUTPUT_FLAG_DIRECT) && (flags & AUDIO_OUTPUT_FLAG_VOIP_RX)) {
// open direct output stream
if(mDirectOutput == 0) {
@@ -3050,6 +3054,7 @@
return -1;
}
deleteFromTable(PCM_PLAY);
+ updateDeviceInfo(cur_rx, cur_tx);
if(!getNodeByStreamType(VOICE_CALL)
#ifdef QCOM_TUNNEL_LPA_ENABLED
&& !getNodeByStreamType(LPA_DECODE)
@@ -3065,10 +3070,12 @@
//in case if ANC don't disable cur device.
if (anc_running == false){
#endif
+#if 0
if(enableDevice(cur_rx, 0)) {
ALOGE("Disabling device failed for cur_rx %d", cur_rx);
return 0;
}
+#endif
#ifdef QCOM_ANC_HEADSET_ENABLED
}
#endif
diff --git a/msm8660/AudioPolicyManager.cpp b/msm8660/AudioPolicyManager.cpp
index 429faf0..bd5be6a 100644
--- a/msm8660/AudioPolicyManager.cpp
+++ b/msm8660/AudioPolicyManager.cpp
@@ -1,6 +1,8 @@
/*
* Copyright (C) 2009 The Android Open Source Project
- * Copyright (C) 2010-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
+ * Not a Contribution, Apache license notifications and license are retained
+ * for attribution purposes only.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,9 +17,9 @@
* limitations under the License.
*/
-#define LOG_TAG "AudioPolicyManager"
+#define LOG_TAG "AudioPolicyManager8660"
+//#define LOG_NDDEBUG 0
-//#define LOG_NDEBUG 0
//#define VERY_VERBOSE_LOGGING
#ifdef VERY_VERBOSE_LOGGING
#define ALOGVV ALOGV
@@ -25,13 +27,22 @@
#define ALOGVV(a...) do { } while(0)
#endif
+// A device mask for all audio input devices that are considered "virtual" when evaluating
+// active inputs in getActiveInput()
+#define APM_AUDIO_IN_DEVICE_VIRTUAL_ALL AUDIO_DEVICE_IN_REMOTE_SUBMIX
+
#include <utils/Log.h>
#include "AudioPolicyManager.h"
+#include <hardware/audio_effect.h>
#include <media/mediarecorder.h>
#include <hardware/audio.h>
+#include <math.h>
+#include <hardware_legacy/audio_policy_conf.h>
namespace android_audio_legacy {
+
+
// ----------------------------------------------------------------------------
// AudioPolicyManager for msm8660 platform
// ----------------------------------------------------------------------------
@@ -95,22 +106,19 @@
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
if (device) break;
}
+
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE;
if (device) break;
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET;
if (device) break;
-#ifdef QCOM_ANC_HEADSET_ENABLED
- device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE;
- if (device) break;
- device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_ANC_HEADSET;
- if (device) break;
-#endif
device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_ACCESSORY;
if (device) break;
device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_DEVICE;
if (device) break;
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET;
if (device) break;
+ device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL;
+ if (device) break;
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET;
if (device) break;
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_EARPIECE;
@@ -136,6 +144,8 @@
if (device) break;
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET;
if (device) break;
+ device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL;
+ if (device) break;
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET;
if (device) break;
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
@@ -149,6 +159,10 @@
#ifdef QCOM_FM_ENABLED
if (mAvailableOutputDevices & AudioSystem::DEVICE_OUT_FM) {
device |= AudioSystem::DEVICE_OUT_FM;
+ if (mForceUse[AudioSystem::FOR_MEDIA] == AudioSystem::FORCE_SPEAKER) {
+ device &= ~(AudioSystem::DEVICE_OUT_WIRED_HEADSET);
+ device |= AudioSystem::DEVICE_OUT_SPEAKER;
+ }
}
#endif
break;
@@ -202,14 +216,6 @@
if (device2 == 0) {
device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET;
}
-#ifdef QCOM_ANC_HEADSET_ENABLED
- if (device2 == 0) {
- device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE;
- }
- if (device2 == 0) {
- device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_ANC_HEADSET;
- }
-#endif
#ifdef QCOM_FM_ENABLED
if (device2 == 0) {
device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_FM_TX;
@@ -241,56 +247,46 @@
device = mDefaultOutputDevice;
}
break;
+
case AudioSystem::FORCE_SPEAKER:
- device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
- break;
- }
+ device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
+ break;
+ }
#ifdef QCOM_FM_ENABLED
if (mAvailableOutputDevices & AudioSystem::DEVICE_OUT_FM) {
- device |= AudioSystem::DEVICE_OUT_FM;
- }
+ device |= AudioSystem::DEVICE_OUT_FM;
+ }
#endif
-#ifdef QCOM_ANC_HEADSET_ENABLED
- if (mAvailableOutputDevices & AudioSystem::DEVICE_OUT_ANC_HEADSET) {
- device |= AudioSystem::DEVICE_OUT_ANC_HEADSET;
- }
- if (mAvailableOutputDevices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE) {
- device |= AudioSystem::DEVICE_OUT_ANC_HEADPHONE;
- }
-#endif
- // Do not play media stream if in call and the requested device would change the hardware
- // output routing
- if (mPhoneState == AudioSystem::MODE_IN_CALL &&
- !AudioSystem::isA2dpDevice((AudioSystem::audio_devices)device) &&
- device != getDeviceForStrategy(STRATEGY_PHONE)) {
- device = getDeviceForStrategy(STRATEGY_PHONE);
- ALOGV("getDeviceForStrategy() incompatible media and phone devices");
- }
- if (device == 0) {
- ALOGE("getDeviceForStrategy() no device found for STRATEGY_MEDIA");
- }
- } break;
+ // Do not play media stream if in call and the requested device would change the hardware
+ // output routing
+ if (mPhoneState == AudioSystem::MODE_IN_CALL &&
+ !AudioSystem::isA2dpDevice((AudioSystem::audio_devices)device) &&
+ device != getDeviceForStrategy(STRATEGY_PHONE)) {
+ device = getDeviceForStrategy(STRATEGY_PHONE);
+ ALOGV("getDeviceForStrategy() incompatible media and phone devices");
+ }
+ } break;
default:
ALOGW("getDeviceForStrategy() unknown strategy: %d", strategy);
break;
}
- ALOGV("getDeviceForStrategy() strategy %d, device %x", strategy, device);
+ ALOGVV("getDeviceForStrategy() strategy %d, device %x", strategy, device);
+
return (audio_devices_t)device;
}
-
-status_t AudioPolicyManager::setDeviceConnectionState(AudioSystem::audio_devices device,
- AudioSystem::device_connection_state state,
- const char *device_address)
+status_t AudioPolicyManager::setDeviceConnectionState(audio_devices_t device,
+ AudioSystem::device_connection_state state,
+ const char *device_address)
{
SortedVector <audio_io_handle_t> outputs;
ALOGV("setDeviceConnectionState() device: %x, state %d, address %s", device, state, device_address);
// connect/disconnect only 1 device at a time
- if (AudioSystem::popCount(device) != 1) return BAD_VALUE;
+ if (!audio_is_output_device(device) && !audio_is_input_device(device)) return BAD_VALUE;
if (strlen(device_address) >= MAX_DEVICE_ADDRESS_LEN) {
ALOGE("setDeviceConnectionState() invalid address: %s", device_address);
@@ -298,17 +294,24 @@
}
// handle output devices
- if (AudioSystem::isOutputDevice(device)) {
+ if (audio_is_output_device(device)) {
- if (!mHasA2dp && AudioSystem::isA2dpDevice(device)) {
- ALOGE("setDeviceConnectionState() invalid device: %x", device);
+ if (!mHasA2dp && audio_is_a2dp_device(device)) {
+ ALOGE("setDeviceConnectionState() invalid A2DP device: %x", device);
return BAD_VALUE;
}
- if (!mHasUsb && audio_is_usb_device((audio_devices_t)device)) {
- ALOGE("setDeviceConnectionState() invalid device: %x", device);
+ if (!mHasUsb && audio_is_usb_device(device)) {
+ ALOGE("setDeviceConnectionState() invalid USB audio device: %x", device);
+ return BAD_VALUE;
+ }
+ if (!mHasRemoteSubmix && audio_is_remote_submix_device((audio_devices_t)device)) {
+ ALOGE("setDeviceConnectionState() invalid remote submix audio device: %x", device);
return BAD_VALUE;
}
+ // save a copy of the opened output descriptors before any output is opened or closed
+ // by checkOutputsForDevice(). This will be needed by checkOutputForAllStrategies()
+ mPreviousOutputs = mOutputs;
switch (state)
{
// handle output device connection
@@ -320,7 +323,7 @@
}
ALOGV("setDeviceConnectionState() connecting device %x", device);
- if (checkOutputsForDevice((audio_devices_t)device, state, outputs) != NO_ERROR) {
+ if (checkOutputsForDevice(device, state, outputs) != NO_ERROR) {
return INVALID_OPERATION;
}
ALOGV("setDeviceConnectionState() checkOutputsForDevice() returned %d outputs",
@@ -331,17 +334,17 @@
if (!outputs.isEmpty()) {
String8 paramStr;
- if (mHasA2dp && AudioSystem::isA2dpDevice(device)) {
+ if (mHasA2dp && audio_is_a2dp_device(device)) {
// handle A2DP device connection
AudioParameter param;
param.add(String8(AUDIO_PARAMETER_A2DP_SINK_ADDRESS), String8(device_address));
paramStr = param.toString();
mA2dpDeviceAddress = String8(device_address, MAX_DEVICE_ADDRESS_LEN);
mA2dpSuspended = false;
- } else if (AudioSystem::isBluetoothScoDevice(device)) {
+ } else if (audio_is_bluetooth_sco_device(device)) {
// handle SCO device connection
mScoDeviceAddress = String8(device_address, MAX_DEVICE_ADDRESS_LEN);
- } else if (mHasUsb && audio_is_usb_device((audio_devices_t)device)) {
+ } else if (mHasUsb && audio_is_usb_device(device)) {
// handle USB device connection
mUsbCardAndDevice = String8(device_address, MAX_DEVICE_ADDRESS_LEN);
paramStr = mUsbCardAndDevice;
@@ -364,15 +367,15 @@
// remove device from available output devices
mAvailableOutputDevices = (audio_devices_t)(mAvailableOutputDevices & ~device);
- checkOutputsForDevice((audio_devices_t)device, state, outputs);
- if (mHasA2dp && AudioSystem::isA2dpDevice(device)) {
+ checkOutputsForDevice(device, state, outputs);
+ if (mHasA2dp && audio_is_a2dp_device(device)) {
// handle A2DP device disconnection
mA2dpDeviceAddress = "";
mA2dpSuspended = false;
- } else if (AudioSystem::isBluetoothScoDevice(device)) {
+ } else if (audio_is_bluetooth_sco_device(device)) {
// handle SCO device disconnection
mScoDeviceAddress = "";
- } else if (mHasUsb && audio_is_usb_device((audio_devices_t)device)) {
+ } else if (mHasUsb && audio_is_usb_device(device)) {
// handle USB device disconnection
mUsbCardAndDevice = "";
}
@@ -382,9 +385,9 @@
ALOGE("setDeviceConnectionState() invalid state: %x", state);
return BAD_VALUE;
}
+#ifdef QCOM_FM_ENABLED
audio_devices_t NewDevice = AudioPolicyManagerBase::getNewDevice(mPrimaryOutput, false /*fromCache*/);
-#ifdef QCOM_FM_ENABLED
if (device == AudioSystem::DEVICE_OUT_FM) {
if (state == AudioSystem::DEVICE_STATE_AVAILABLE) {
mOutputs.valueFor(mPrimaryOutput)->changeRefCount(AudioSystem::FM, 1);
@@ -394,50 +397,38 @@
}
}
#endif
-#ifdef QCOM_ANC_HEADSET_ENABLED
- if(device == AudioSystem::DEVICE_OUT_ANC_HEADPHONE ||
- device == AudioSystem::DEVICE_OUT_ANC_HEADSET) {
- if(NewDevice == 0){
- NewDevice = getDeviceForStrategy(STRATEGY_MEDIA, false);
- }
- }
-#endif
-
checkA2dpSuspend();
AudioPolicyManagerBase::checkOutputForAllStrategies();
// outputs must be closed after checkOutputForAllStrategies() is executed
if (!outputs.isEmpty()) {
for (size_t i = 0; i < outputs.size(); i++) {
// close unused outputs after device disconnection or direct outputs that have been
- // opened by checkOutputsForDevice() to query dynamic parameters
- if ((state == AudioSystem::DEVICE_STATE_UNAVAILABLE) ||
- (mOutputs.valueFor(outputs[i])->mFlags & AUDIO_OUTPUT_FLAG_DIRECT)) {
+ if (state == AudioSystem::DEVICE_STATE_UNAVAILABLE){
closeOutput(outputs[i]);
}
}
}
- //updateDeviceForStrategy();
+ updateDevicesAndOutputs();
for (size_t i = 0; i < mOutputs.size(); i++) {
- setOutputDevice(mOutputs.keyAt(i), getNewDevice(mOutputs.keyAt(i), true /*fromCache*/));
+ setOutputDevice(mOutputs.keyAt(i),
+ getNewDevice(mOutputs.keyAt(i), true /*fromCache*/),
+ true,
+ 0);
}
- if (device == AudioSystem::DEVICE_OUT_WIRED_HEADSET) {
- device = AudioSystem::DEVICE_IN_WIRED_HEADSET;
- } else if (device == AudioSystem::DEVICE_OUT_BLUETOOTH_SCO ||
- device == AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET ||
- device == AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT) {
- device = AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET;
-#ifdef QCOM_ANC_HEADSET_ENABLED
- } else if (device == AudioSystem::DEVICE_OUT_ANC_HEADSET) {
- device = AudioSystem::DEVICE_IN_ANC_HEADSET; //wait for actual ANC device
-#endif
- }else {
+ if (device == AUDIO_DEVICE_OUT_WIRED_HEADSET) {
+ device = AUDIO_DEVICE_IN_WIRED_HEADSET;
+ } else if (device == AUDIO_DEVICE_OUT_BLUETOOTH_SCO ||
+ device == AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET ||
+ device == AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT) {
+ device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
+ } else {
return NO_ERROR;
}
}
// handle input devices
- if (AudioSystem::isInputDevice(device)) {
+ if (audio_is_input_device(device)) {
switch (state)
{
@@ -447,7 +438,7 @@
ALOGW("setDeviceConnectionState() device already connected: %d", device);
return INVALID_OPERATION;
}
- mAvailableInputDevices = (audio_devices_t)(mAvailableInputDevices | device);
+ mAvailableInputDevices = mAvailableInputDevices | (device & ~AUDIO_DEVICE_BIT_IN);
}
break;
@@ -469,7 +460,7 @@
if (activeInput != 0) {
AudioInputDescriptor *inputDesc = mInputs.valueFor(activeInput);
audio_devices_t newDevice = getDeviceForInputSource(inputDesc->mInputSource);
- if ((newDevice != 0) && (newDevice != inputDesc->mDevice)) {
+ if ((newDevice != AUDIO_DEVICE_NONE) && (newDevice != inputDesc->mDevice)) {
ALOGV("setDeviceConnectionState() changing device from %x to %x for input %d",
inputDesc->mDevice, newDevice, activeInput);
inputDesc->mDevice = newDevice;
@@ -486,7 +477,416 @@
return BAD_VALUE;
}
-status_t AudioPolicyManager::startOutput(audio_io_handle_t output, AudioSystem::stream_type stream, int session)
+AudioSystem::device_connection_state AudioPolicyManager::getDeviceConnectionState(audio_devices_t device,
+ const char *device_address)
+{
+ AudioSystem::device_connection_state state = AudioSystem::DEVICE_STATE_UNAVAILABLE;
+ String8 address = String8(device_address);
+ if (audio_is_output_device(device)) {
+ if (device & mAvailableOutputDevices) {
+ if (audio_is_a2dp_device(device) &&
+ (!mHasA2dp || (address != "" && mA2dpDeviceAddress != address))) {
+ return state;
+ }
+ if (audio_is_bluetooth_sco_device(device) &&
+ address != "" && mScoDeviceAddress != address) {
+ return state;
+ }
+ if (audio_is_usb_device(device) &&
+ (!mHasUsb || (address != "" && mUsbCardAndDevice != address))) {
+ ALOGE("getDeviceConnectionState() invalid device: %x", device);
+ return state;
+ }
+ if (audio_is_remote_submix_device((audio_devices_t)device) && !mHasRemoteSubmix) {
+ return state;
+ }
+ state = AudioSystem::DEVICE_STATE_AVAILABLE;
+ }
+ } else if (audio_is_input_device(device)) {
+ if (device & mAvailableInputDevices) {
+ state = AudioSystem::DEVICE_STATE_AVAILABLE;
+ }
+ }
+
+ return state;
+}
+
+void AudioPolicyManager::setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config)
+{
+ ALOGV("setForceUse() usage %d, config %d, mPhoneState %d", usage, config, mPhoneState);
+
+ bool forceVolumeReeval = false;
+ switch(usage) {
+ case AudioSystem::FOR_COMMUNICATION:
+ if (config != AudioSystem::FORCE_SPEAKER && config != AudioSystem::FORCE_BT_SCO &&
+ config != AudioSystem::FORCE_NONE) {
+ ALOGW("setForceUse() invalid config %d for FOR_COMMUNICATION", config);
+ return;
+ }
+ forceVolumeReeval = true;
+ mForceUse[usage] = config;
+ break;
+ case AudioSystem::FOR_MEDIA:
+ if (config != AudioSystem::FORCE_HEADPHONES && config != AudioSystem::FORCE_BT_A2DP &&
+ config != AudioSystem::FORCE_WIRED_ACCESSORY &&
+ config != AudioSystem::FORCE_ANALOG_DOCK &&
+ config != AudioSystem::FORCE_DIGITAL_DOCK && config != AudioSystem::FORCE_NONE &&
+ config != AudioSystem::FORCE_NO_BT_A2DP) {
+ ALOGW("setForceUse() invalid config %d for FOR_MEDIA", config);
+ return;
+ }
+ mForceUse[usage] = config;
+ break;
+ case AudioSystem::FOR_RECORD:
+ if (config != AudioSystem::FORCE_BT_SCO && config != AudioSystem::FORCE_WIRED_ACCESSORY &&
+ config != AudioSystem::FORCE_NONE) {
+ ALOGW("setForceUse() invalid config %d for FOR_RECORD", config);
+ return;
+ }
+ mForceUse[usage] = config;
+ break;
+ case AudioSystem::FOR_DOCK:
+ if (config != AudioSystem::FORCE_NONE && config != AudioSystem::FORCE_BT_CAR_DOCK &&
+ config != AudioSystem::FORCE_BT_DESK_DOCK &&
+ config != AudioSystem::FORCE_WIRED_ACCESSORY &&
+ config != AudioSystem::FORCE_ANALOG_DOCK &&
+ config != AudioSystem::FORCE_DIGITAL_DOCK) {
+ ALOGW("setForceUse() invalid config %d for FOR_DOCK", config);
+ }
+ forceVolumeReeval = true;
+ mForceUse[usage] = config;
+ break;
+ case AudioSystem::FOR_SYSTEM:
+ if (config != AudioSystem::FORCE_NONE &&
+ config != AudioSystem::FORCE_SYSTEM_ENFORCED) {
+ ALOGW("setForceUse() invalid config %d for FOR_SYSTEM", config);
+ }
+ forceVolumeReeval = true;
+ mForceUse[usage] = config;
+ break;
+ default:
+ ALOGW("setForceUse() invalid usage %d", usage);
+ break;
+ }
+
+ // check for device and output changes triggered by new force usage
+ checkA2dpSuspend();
+ checkOutputForAllStrategies();
+ updateDevicesAndOutputs();
+ for (size_t i = 0; i < mOutputs.size(); i++) {
+ audio_io_handle_t output = mOutputs.keyAt(i);
+ audio_devices_t newDevice = getNewDevice(output, true /*fromCache*/);
+ setOutputDevice(output, newDevice, (newDevice != AUDIO_DEVICE_NONE));
+ if (forceVolumeReeval && (newDevice != AUDIO_DEVICE_NONE)) {
+ applyStreamVolumes(output, newDevice, 0, true);
+ }
+ }
+
+ audio_io_handle_t activeInput = getActiveInput();
+ if (activeInput != 0) {
+ AudioInputDescriptor *inputDesc = mInputs.valueFor(activeInput);
+ audio_devices_t newDevice = getDeviceForInputSource(inputDesc->mInputSource);
+ if ((newDevice != AUDIO_DEVICE_NONE) && (newDevice != inputDesc->mDevice)) {
+ ALOGV("setForceUse() changing device from %x to %x for input %d",
+ inputDesc->mDevice, newDevice, activeInput);
+ inputDesc->mDevice = newDevice;
+ AudioParameter param = AudioParameter();
+ param.addInt(String8(AudioParameter::keyRouting), (int)newDevice);
+ mpClientInterface->setParameters(activeInput, param.toString());
+ }
+ }
+
+}
+
+
+AudioPolicyManagerBase::IOProfile *AudioPolicyManager::getProfileForDirectOutput(
+ audio_devices_t device,
+ uint32_t samplingRate,
+ uint32_t format,
+ uint32_t channelMask,
+ audio_output_flags_t flags)
+{
+ if( !((flags & AUDIO_OUTPUT_FLAG_LPA) ||
+ (flags & AUDIO_OUTPUT_FLAG_TUNNEL)||
+ (flags & AUDIO_OUTPUT_FLAG_VOIP_RX)) )
+ flags = AUDIO_OUTPUT_FLAG_DIRECT;
+
+ for (size_t i = 0; i < mHwModules.size(); i++) {
+ if (mHwModules[i]->mHandle == 0) {
+ continue;
+ }
+ for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++) {
+ AudioPolicyManagerBase::IOProfile *profile = mHwModules[i]->mOutputProfiles[j];
+ if (isCompatibleProfile(profile, device, samplingRate, format,
+ channelMask,
+ flags)) {
+ if (mAvailableOutputDevices & profile->mSupportedDevices) {
+ return mHwModules[i]->mOutputProfiles[j];
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+
+bool AudioPolicyManager::isCompatibleProfile(AudioPolicyManagerBase::IOProfile *profile,
+ audio_devices_t device,
+ uint32_t samplingRate,
+ uint32_t format,
+ uint32_t channelMask,
+ audio_output_flags_t flags)
+{
+ if ((profile->mSupportedDevices & device) != device) {
+ return false;
+ }
+ if (profile->mFlags != flags) {
+ return false;
+ }
+ if (samplingRate != 0) {
+ size_t i;
+ for (i = 0; i < profile->mSamplingRates.size(); i++)
+ {
+ if (profile->mSamplingRates[i] == samplingRate) {
+ break;
+ }
+ }
+ if (i == profile->mSamplingRates.size()) {
+ return false;
+ }
+ }
+ if (format != 0) {
+ size_t i;
+ for (i = 0; i < profile->mFormats.size(); i++)
+ {
+ if (profile->mFormats[i] == format) {
+ break;
+ }
+ }
+ if (i == profile->mFormats.size()) {
+ return false;
+ }
+ }
+ if (channelMask != 0) {
+ size_t i;
+ for (i = 0; i < profile->mChannelMasks.size(); i++)
+ {
+ if (profile->mChannelMasks[i] == channelMask) {
+ break;
+ }
+ }
+ if (i == profile->mChannelMasks.size()) {
+ return false;
+ }
+ }
+ ALOGD(" profile found: device %x, flags %x, samplingrate %d,\
+ format %x, channelMask %d",
+ device, flags, samplingRate, format, channelMask);
+ return true;
+}
+
+status_t AudioPolicyManager::checkOutputsForDevice(audio_devices_t device,
+ AudioSystem::device_connection_state state,
+ SortedVector<audio_io_handle_t>& outputs)
+{
+ AudioOutputDescriptor *desc;
+
+ if (state == AudioSystem::DEVICE_STATE_AVAILABLE) {
+ // first list already open outputs that can be routed to this device
+ for (size_t i = 0; i < mOutputs.size(); i++) {
+ desc = mOutputs.valueAt(i);
+ if (!desc->isDuplicated() && (desc->mProfile->mSupportedDevices & device)) {
+ ALOGV("checkOutputsForDevice(): adding opened output %d", mOutputs.keyAt(i));
+ outputs.add(mOutputs.keyAt(i));
+ }
+ }
+ // then look for output profiles that can be routed to this device
+ SortedVector<IOProfile *> profiles;
+ for (size_t i = 0; i < mHwModules.size(); i++)
+ {
+ if (mHwModules[i]->mHandle == 0) {
+ continue;
+ }
+ for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++)
+ {
+ if (mHwModules[i]->mOutputProfiles[j]->mSupportedDevices & device) {
+ ALOGV("checkOutputsForDevice(): adding profile %d from module %d", j, i);
+ profiles.add(mHwModules[i]->mOutputProfiles[j]);
+ }
+ }
+ }
+
+ if (profiles.isEmpty() && outputs.isEmpty()) {
+ ALOGW("checkOutputsForDevice(): No output available for device %04x", device);
+ return BAD_VALUE;
+ }
+
+ // open outputs for matching profiles if needed. Direct outputs are also opened to
+ // query for dynamic parameters and will be closed later by setDeviceConnectionState()
+ for (ssize_t profile_index = 0; profile_index < (ssize_t)profiles.size(); profile_index++) {
+ IOProfile *profile = profiles[profile_index];
+
+ // nothing to do if one output is already opened for this profile
+ size_t j;
+ for (j = 0; j < mOutputs.size(); j++) {
+ desc = mOutputs.valueAt(j);
+ if (!desc->isDuplicated() && desc->mProfile == profile) {
+ break;
+ }
+ }
+ if (j != mOutputs.size()) {
+ continue;
+ }
+
+ ALOGV("opening output for device %08x", device);
+ desc = new AudioOutputDescriptor(profile);
+ desc->mDevice = device;
+ audio_io_handle_t output = 0;
+ if (!(desc->mFlags & AUDIO_OUTPUT_FLAG_LPA || desc->mFlags & AUDIO_OUTPUT_FLAG_TUNNEL ||
+ desc->mFlags & AUDIO_OUTPUT_FLAG_VOIP_RX)) {
+ output = mpClientInterface->openOutput(profile->mModule->mHandle,
+ &desc->mDevice,
+ &desc->mSamplingRate,
+ &desc->mFormat,
+ &desc->mChannelMask,
+ &desc->mLatency,
+ desc->mFlags);
+ }
+ if (output != 0) {
+ if (desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) {
+ String8 reply;
+ char *value;
+ if (profile->mSamplingRates[0] == 0) {
+ reply = mpClientInterface->getParameters(output,
+ String8(AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES));
+ ALOGV("checkOutputsForDevice() direct output sup sampling rates %s",
+ reply.string());
+ value = strpbrk((char *)reply.string(), "=");
+ if (value != NULL) {
+ loadSamplingRates(value, profile);
+ }
+ }
+ if (profile->mFormats[0] == 0) {
+ reply = mpClientInterface->getParameters(output,
+ String8(AUDIO_PARAMETER_STREAM_SUP_FORMATS));
+ ALOGV("checkOutputsForDevice() direct output sup formats %s",
+ reply.string());
+ value = strpbrk((char *)reply.string(), "=");
+ if (value != NULL) {
+ loadFormats(value, profile);
+ }
+ }
+ if (profile->mChannelMasks[0] == 0) {
+ reply = mpClientInterface->getParameters(output,
+ String8(AUDIO_PARAMETER_STREAM_SUP_CHANNELS));
+ ALOGV("checkOutputsForDevice() direct output sup channel masks %s",
+ reply.string());
+ value = strpbrk((char *)reply.string(), "=");
+ if (value != NULL) {
+ loadOutChannels(value + 1, profile);
+ }
+ }
+ if (((profile->mSamplingRates[0] == 0) &&
+ (profile->mSamplingRates.size() < 2)) ||
+ ((profile->mFormats[0] == 0) &&
+ (profile->mFormats.size() < 2)) ||
+ ((profile->mFormats[0] == 0) &&
+ (profile->mChannelMasks.size() < 2))) {
+ ALOGW("checkOutputsForDevice() direct output missing param");
+ output = 0;
+ } else {
+ addOutput(output, desc);
+ }
+ } else {
+ audio_io_handle_t duplicatedOutput = 0;
+ // add output descriptor
+ addOutput(output, desc);
+ // set initial stream volume for device
+ applyStreamVolumes(output, device, 0, true);
+
+ //TODO: configure audio effect output stage here
+
+ // open a duplicating output thread for the new output and the primary output
+ duplicatedOutput = mpClientInterface->openDuplicateOutput(output,
+ mPrimaryOutput);
+ if (duplicatedOutput != 0) {
+ // add duplicated output descriptor
+ AudioOutputDescriptor *dupOutputDesc = new AudioOutputDescriptor(NULL);
+ dupOutputDesc->mOutput1 = mOutputs.valueFor(mPrimaryOutput);
+ dupOutputDesc->mOutput2 = mOutputs.valueFor(output);
+ dupOutputDesc->mSamplingRate = desc->mSamplingRate;
+ dupOutputDesc->mFormat = desc->mFormat;
+ dupOutputDesc->mChannelMask = desc->mChannelMask;
+ dupOutputDesc->mLatency = desc->mLatency;
+ addOutput(duplicatedOutput, dupOutputDesc);
+ applyStreamVolumes(duplicatedOutput, device, 0, true);
+ } else {
+ ALOGW("checkOutputsForDevice() could not open dup output for %d and %d",
+ mPrimaryOutput, output);
+ mpClientInterface->closeOutput(output);
+ mOutputs.removeItem(output);
+ output = 0;
+ }
+ }
+ }
+ if (output == 0) {
+ ALOGW("checkOutputsForDevice() could not open output for device %x", device);
+ delete desc;
+ profiles.removeAt(profile_index);
+ profile_index--;
+ } else {
+ outputs.add(output);
+ ALOGV("checkOutputsForDevice(): adding output %d", output);
+ }
+ }
+
+ if (profiles.isEmpty()) {
+ ALOGW("checkOutputsForDevice(): No output available for device %04x", device);
+ return BAD_VALUE;
+ }
+ } else {
+ // check if one opened output is not needed any more after disconnecting one device
+ for (size_t i = 0; i < mOutputs.size(); i++) {
+ desc = mOutputs.valueAt(i);
+ if (!desc->isDuplicated() &&
+ !(desc->mProfile->mSupportedDevices & mAvailableOutputDevices)) {
+ ALOGV("checkOutputsForDevice(): disconnecting adding output %d", mOutputs.keyAt(i));
+ outputs.add(mOutputs.keyAt(i));
+ }
+ }
+ for (size_t i = 0; i < mHwModules.size(); i++)
+ {
+ if (mHwModules[i]->mHandle == 0) {
+ continue;
+ }
+ for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++)
+ {
+ IOProfile *profile = mHwModules[i]->mOutputProfiles[j];
+ if ((profile->mSupportedDevices & device) &&
+ (profile->mFlags & AUDIO_OUTPUT_FLAG_DIRECT)) {
+ ALOGV("checkOutputsForDevice(): clearing direct output profile %d on module %d",
+ j, i);
+ if (profile->mSamplingRates[0] == 0) {
+ profile->mSamplingRates.clear();
+ profile->mSamplingRates.add(0);
+ }
+ if (profile->mFormats[0] == 0) {
+ profile->mFormats.clear();
+ profile->mFormats.add((audio_format_t)0);
+ }
+ if (profile->mChannelMasks[0] == 0) {
+ profile->mChannelMasks.clear();
+ profile->mChannelMasks.add((audio_channel_mask_t)0);
+ }
+ }
+ }
+ }
+ }
+ return NO_ERROR;
+}
+status_t AudioPolicyManager::startOutput(audio_io_handle_t output,
+ AudioSystem::stream_type stream,
+ int session)
{
ALOGV("startOutput() output %d, stream %d, session %d", output, stream, session);
ssize_t index = mOutputs.indexOfKey(output);
@@ -529,8 +929,14 @@
}
}
}
-
+#ifdef QCOM_FM_ENABLED
+ if(stream == AudioSystem::FM && output == getA2dpOutput()) {
setOutputDevice(output, AudioPolicyManagerBase::getNewDevice((output), true));
+ } else
+#endif
+ {
+ setOutputDevice(output, AudioPolicyManagerBase::getNewDevice((output), true));
+ }
// handle special case for sonification while in call
if (isInCall()) {
@@ -539,7 +945,7 @@
// apply volume rules for current stream and device if necessary
checkAndSetVolume(stream,
- mStreams[stream].getVolumeIndex((audio_devices_t)newDevice),
+ mStreams[stream].getVolumeIndex(newDevice),
output,
newDevice);
@@ -552,7 +958,6 @@
}
return NO_ERROR;
}
-
status_t AudioPolicyManager::stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream, int session)
{
ALOGV("stopOutput() output %d, stream %d, session %d", output, stream, session);
@@ -610,36 +1015,6 @@
}
}
-status_t AudioPolicyManager::stopInput(audio_io_handle_t input)
-{
- ALOGV("stopInput() input %d", input);
- uint32_t newDevice = NULL;
- ssize_t index = mInputs.indexOfKey(input);
- if (index < 0) {
- ALOGW("stopInput() unknow input %d", input);
- return BAD_VALUE;
- }
- AudioInputDescriptor *inputDesc = mInputs.valueAt(index);
-
- if (inputDesc->mRefCount == 0) {
- ALOGW("stopInput() input %d already stopped", input);
- return INVALID_OPERATION;
- } else {
- AudioParameter param = AudioParameter();
- param.addInt(String8(AudioParameter::keyRouting), 0);
- ALOGV("stopInput string to setParam %s\n", param.toString().string());
- mpClientInterface->setParameters(input, param.toString());
- inputDesc->mRefCount = 0;
-
- newDevice = AudioPolicyManagerBase::getNewDevice(mPrimaryOutput, false);
- param.addInt(String8(AudioParameter::keyRouting), (int)newDevice);
- mpClientInterface->setParameters(mPrimaryOutput, param.toString());
- return NO_ERROR;
- }
- return NO_ERROR;
-}
-
-
// ----------------------------------------------------------------------------
// AudioPolicyManager
// ----------------------------------------------------------------------------
@@ -702,7 +1077,6 @@
return muteWaitMs;
}
-
status_t AudioPolicyManager::checkAndSetVolume(int stream, int index, audio_io_handle_t output, audio_devices_t device, int delayMs, bool force)
{
// do not change actual stream volume if the stream is muted
@@ -724,11 +1098,11 @@
// We actually change the volume if:
// - the float value returned by computeVolume() changed
// - the force flag is set
- if (volume != mOutputs.valueFor(output)->mCurVolume[stream]
+ if (volume != mOutputs.valueFor(output)->mCurVolume[stream] ||
#ifdef QCOM_FM_ENABLED
- || (stream == AudioSystem::FM)
+ (stream == AudioSystem::FM) ||
#endif
- || force) {
+ force) {
mOutputs.valueFor(output)->mCurVolume[stream] = volume;
ALOGVV("checkAndSetVolume() for output %d stream %d, volume %f, delay %d", output, stream, volume, delayMs);
if (stream == AudioSystem::VOICE_CALL ||
@@ -764,129 +1138,128 @@
return NO_ERROR;
}
-void AudioPolicyManager::setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config)
+audio_io_handle_t AudioPolicyManager::getInput(int inputSource,
+ uint32_t samplingRate,
+ uint32_t format,
+ uint32_t channelMask,
+ AudioSystem::audio_in_acoustics acoustics)
{
- ALOGV("setForceUse() usage %d, config %d, mPhoneState %d", usage, config, mPhoneState);
+ audio_io_handle_t input = 0;
+ audio_devices_t device = getDeviceForInputSource(inputSource);
- bool forceVolumeReeval = false;
- switch(usage) {
- case AudioSystem::FOR_COMMUNICATION:
- if (config != AudioSystem::FORCE_SPEAKER && config != AudioSystem::FORCE_BT_SCO &&
- config != AudioSystem::FORCE_NONE) {
- ALOGW("setForceUse() invalid config %d for FOR_COMMUNICATION", config);
- return;
- }
- forceVolumeReeval = true;
- mForceUse[usage] = config;
+ ALOGV("getInput() inputSource %d, samplingRate %d, format %d, channelMask %x, acoustics %x",
+ inputSource, samplingRate, format, channelMask, acoustics);
+
+ if (device == AUDIO_DEVICE_NONE) {
+ ALOGW("getInput() could not find device for inputSource %d", inputSource);
+ return 0;
+ }
+
+ // adapt channel selection to input source
+ switch(inputSource) {
+ case AUDIO_SOURCE_VOICE_UPLINK:
+ channelMask = AudioSystem::CHANNEL_IN_VOICE_UPLINK;
break;
- case AudioSystem::FOR_MEDIA:
- if (config != AudioSystem::FORCE_HEADPHONES && config != AudioSystem::FORCE_BT_A2DP &&
- config != AudioSystem::FORCE_WIRED_ACCESSORY &&
- config != AudioSystem::FORCE_ANALOG_DOCK &&
- config != AudioSystem::FORCE_DIGITAL_DOCK && config != AudioSystem::FORCE_NONE &&
- config != AudioSystem::FORCE_NO_BT_A2DP &&
- config != AudioSystem::FORCE_SPEAKER) {
- ALOGW("setForceUse() invalid config %d for FOR_MEDIA", config);
- return;
- }
- mForceUse[usage] = config;
- {
- audio_devices_t device = getDeviceForStrategy(STRATEGY_MEDIA);
- setOutputDevice(mPrimaryOutput, device);
- }
+ case AUDIO_SOURCE_VOICE_DOWNLINK:
+ channelMask = AudioSystem::CHANNEL_IN_VOICE_DNLINK;
break;
- case AudioSystem::FOR_RECORD:
- if (config != AudioSystem::FORCE_BT_SCO && config != AudioSystem::FORCE_WIRED_ACCESSORY &&
- config != AudioSystem::FORCE_NONE) {
- ALOGW("setForceUse() invalid config %d for FOR_RECORD", config);
- return;
- }
- mForceUse[usage] = config;
- break;
- case AudioSystem::FOR_DOCK:
- if (config != AudioSystem::FORCE_NONE && config != AudioSystem::FORCE_BT_CAR_DOCK &&
- config != AudioSystem::FORCE_BT_DESK_DOCK &&
- config != AudioSystem::FORCE_WIRED_ACCESSORY &&
- config != AudioSystem::FORCE_ANALOG_DOCK &&
- config != AudioSystem::FORCE_DIGITAL_DOCK) {
- ALOGW("setForceUse() invalid config %d for FOR_DOCK", config);
- }
- forceVolumeReeval = true;
- mForceUse[usage] = config;
+ case AUDIO_SOURCE_VOICE_CALL:
+ channelMask = (AudioSystem::CHANNEL_IN_VOICE_UPLINK | AudioSystem::CHANNEL_IN_VOICE_DNLINK);
break;
default:
- ALOGW("setForceUse() invalid usage %d", usage);
break;
}
- // check for device and output changes triggered by new force usage
- checkA2dpSuspend();
- checkOutputForAllStrategies();
- //updateDeviceForStrategy();
- for (size_t i = 0; i < mOutputs.size(); i++) {
- audio_io_handle_t output = mOutputs.keyAt(i);
- audio_devices_t newDevice = getNewDevice(output, true /*fromCache*/);
- setOutputDevice(output, newDevice, (newDevice != 0));
- if (forceVolumeReeval && (newDevice != 0)) {
- applyStreamVolumes(output, newDevice, 0, true);
- }
+ IOProfile *profile = getInputProfile(device,
+ samplingRate,
+ format,
+ channelMask);
+ if (profile == NULL) {
+ ALOGW("getInput() could not find profile for device %04x, samplingRate %d, format %d,"
+ "channelMask %04x",
+ device, samplingRate, format, channelMask);
+ return 0;
}
- audio_io_handle_t activeInput = getActiveInput();
- if (activeInput != 0) {
- AudioInputDescriptor *inputDesc = mInputs.valueFor(activeInput);
- audio_devices_t newDevice = getDeviceForInputSource(inputDesc->mInputSource);
- if ((newDevice != 0) && (newDevice != inputDesc->mDevice)) {
- ALOGV("setForceUse() changing device from %x to %x for input %d",
- inputDesc->mDevice, newDevice, activeInput);
- inputDesc->mDevice = newDevice;
- AudioParameter param = AudioParameter();
- param.addInt(String8(AudioParameter::keyRouting), (int)newDevice);
- mpClientInterface->setParameters(activeInput, param.toString());
- }
+ if (profile->mModule->mHandle == 0) {
+ ALOGE("getInput(): HW module %s not opened", profile->mModule->mName);
+ return 0;
}
+
+ AudioInputDescriptor *inputDesc = new AudioInputDescriptor(profile);
+
+ inputDesc->mInputSource = inputSource;
+ inputDesc->mDevice = device;
+ inputDesc->mSamplingRate = samplingRate;
+ inputDesc->mFormat = (audio_format_t)format;
+ inputDesc->mChannelMask = (audio_channel_mask_t)channelMask;
+ inputDesc->mRefCount = 0;
+ input = mpClientInterface->openInput(profile->mModule->mHandle,
+ &inputDesc->mDevice,
+ &inputDesc->mSamplingRate,
+ &inputDesc->mFormat,
+ &inputDesc->mChannelMask);
+
+ // only accept input with the exact requested set of parameters
+ if (input == 0 ||
+ (samplingRate != inputDesc->mSamplingRate) ||
+ (format != inputDesc->mFormat) ||
+ (channelMask != inputDesc->mChannelMask)) {
+ ALOGV("getInput() failed opening input: samplingRate %d, format %d, channelMask %d",
+ samplingRate, format, channelMask);
+ if (input != 0) {
+ mpClientInterface->closeInput(input);
+ }
+ delete inputDesc;
+ return 0;
+ }
+ mInputs.add(input, inputDesc);
+ return input;
}
audio_devices_t AudioPolicyManager::getDeviceForInputSource(int inputSource)
{
- uint32_t device = 0;
+ uint32_t device = AUDIO_DEVICE_NONE;
switch(inputSource) {
case AUDIO_SOURCE_DEFAULT:
case AUDIO_SOURCE_MIC:
case AUDIO_SOURCE_VOICE_RECOGNITION:
if (mForceUse[AudioSystem::FOR_RECORD] == AudioSystem::FORCE_BT_SCO &&
- mAvailableInputDevices & AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
- device = AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET;
- } else if (mAvailableInputDevices & AudioSystem::DEVICE_IN_WIRED_HEADSET) {
- device = AudioSystem::DEVICE_IN_WIRED_HEADSET;
-#ifdef QCOM_ANC_HEADSET_ENABLED
- } else if (mAvailableInputDevices & AudioSystem::DEVICE_IN_ANC_HEADSET) {
- device = AudioSystem::DEVICE_IN_ANC_HEADSET;
-#endif
- } else if (mAvailableInputDevices & AudioSystem::DEVICE_IN_BUILTIN_MIC) {
- device = AudioSystem::DEVICE_IN_BUILTIN_MIC;
+ mAvailableInputDevices & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
+ device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
+ } else if (mAvailableInputDevices & AUDIO_DEVICE_IN_WIRED_HEADSET) {
+ device = AUDIO_DEVICE_IN_WIRED_HEADSET;
+ } else if (mAvailableInputDevices & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+ device = AUDIO_DEVICE_IN_BUILTIN_MIC;
}
break;
case AUDIO_SOURCE_VOICE_COMMUNICATION:
device = AudioSystem::DEVICE_IN_COMMUNICATION;
break;
+
case AUDIO_SOURCE_CAMCORDER:
- if (mAvailableInputDevices & AudioSystem::DEVICE_IN_BACK_MIC) {
- device = AudioSystem::DEVICE_IN_BACK_MIC;
- } else if (mAvailableInputDevices & AudioSystem::DEVICE_IN_BUILTIN_MIC) {
- device = AudioSystem::DEVICE_IN_BUILTIN_MIC;
+ if (mAvailableInputDevices & AUDIO_DEVICE_IN_BACK_MIC) {
+ device = AUDIO_DEVICE_IN_BACK_MIC;
+ } else if (mAvailableInputDevices & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+ device = AUDIO_DEVICE_IN_BUILTIN_MIC;
}
break;
case AUDIO_SOURCE_VOICE_UPLINK:
case AUDIO_SOURCE_VOICE_DOWNLINK:
case AUDIO_SOURCE_VOICE_CALL:
- if (mAvailableInputDevices & AudioSystem::DEVICE_IN_VOICE_CALL) {
- device = AudioSystem::DEVICE_IN_VOICE_CALL;
+ if (mAvailableInputDevices & AUDIO_DEVICE_IN_VOICE_CALL) {
+ device = AUDIO_DEVICE_IN_VOICE_CALL;
}
break;
+ case AUDIO_SOURCE_REMOTE_SUBMIX:
+ if (mAvailableInputDevices & AUDIO_DEVICE_IN_REMOTE_SUBMIX) {
+ device = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
+ }
+ break;
+
#ifdef QCOM_FM_ENABLED
- case AUDIO_SOURCE_FM_RX:
+ case AUDIO_SOURCE_FM_RX:
device = AudioSystem::DEVICE_IN_FM_RX;
break;
case AUDIO_SOURCE_FM_RX_A2DP:
@@ -898,9 +1271,8 @@
break;
}
ALOGV("getDeviceForInputSource()input source %d, device %08x", inputSource, device);
- return (audio_devices_t)device;
+ return device;
}
-
/*
Overwriting this function from base class to allow 2 acitve AudioRecord clients in case of FM.
One for FM A2DP playbck and other for FM recording.
@@ -914,6 +1286,18 @@
return BAD_VALUE;
}
AudioInputDescriptor *inputDesc = mInputs.valueAt(index);
+
+#ifdef AUDIO_POLICY_TEST
+ if (mTestInput == 0)
+#endif //AUDIO_POLICY_TEST
+ {
+ // refuse 2 active AudioRecord clients at the same time
+ if (getActiveInput() != 0) {
+ ALOGW("startInput() input %d failed: other input already started", input);
+ return INVALID_OPERATION;
+ }
+ }
+
AudioParameter param = AudioParameter();
param.addInt(String8(AudioParameter::keyRouting), (int)inputDesc->mDevice);
// use Voice Recognition mode or not for this input based on input source
@@ -925,15 +1309,16 @@
return NO_ERROR;
}
-//private function, no changes from AudioPolicyManagerBase
void AudioPolicyManager::handleNotificationRoutingForStream(AudioSystem::stream_type stream) {
switch(stream) {
case AudioSystem::MUSIC:
checkOutputForStrategy(STRATEGY_SONIFICATION_RESPECTFUL);
updateDevicesAndOutputs();
- break;
+ break;
default:
break;
}
-}
+}
+
+
}; // namespace android_audio_legacy
diff --git a/msm8660/AudioPolicyManager.h b/msm8660/AudioPolicyManager.h
index 5468a91..43316a4 100755
--- a/msm8660/AudioPolicyManager.h
+++ b/msm8660/AudioPolicyManager.h
@@ -1,6 +1,8 @@
/*
* Copyright (C) 2009 The Android Open Source Project
- * Copyright (C) 2010-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009, 2011-2013, The Linux Foundation. All rights reserved.
+ * Not a Contribution, Apache license notifications and license are retained
+ * for attribution purposes only.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,9 +17,10 @@
* limitations under the License.
*/
-
#include <stdint.h>
#include <sys/types.h>
+#include <cutils/config_utils.h>
+#include <cutils/misc.h>
#include <utils/Timers.h>
#include <utils/Errors.h>
#include <utils/KeyedVector.h>
@@ -36,9 +39,19 @@
virtual ~AudioPolicyManager() {}
// AudioPolicyInterface
- virtual status_t setDeviceConnectionState(AudioSystem::audio_devices device,
+ virtual status_t setDeviceConnectionState(audio_devices_t device,
AudioSystem::device_connection_state state,
const char *device_address);
+ virtual AudioSystem::device_connection_state getDeviceConnectionState(audio_devices_t device,
+ const char *device_address);
+ virtual audio_io_handle_t getInput(int inputSource,
+ uint32_t samplingRate,
+ uint32_t format,
+ uint32_t channels,
+ AudioSystem::audio_in_acoustics acoustics);
+
+ // indicates to the audio policy manager that the input starts being used.
+ virtual status_t startInput(audio_io_handle_t input);
// return appropriate device for streams handled by the specified strategy according to current
// phone state, connected devices...
@@ -50,24 +63,51 @@
// "future" device selection (fromCache == false) when called from a context
// where conditions are changing (setDeviceConnectionState(), setPhoneState()...) AND
// before updateDeviceForStrategy() is called.
- virtual audio_devices_t getDeviceForStrategy(routing_strategy strategy, bool fromCache = true);
virtual status_t startOutput(audio_io_handle_t output, AudioSystem::stream_type stream, int session = 0);
virtual status_t stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream, int session = 0);
virtual void setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config);
- // indicates to the audio policy manager that the input starts being used.
- virtual status_t startInput(audio_io_handle_t input);
protected:
+
+ virtual audio_devices_t getDeviceForStrategy(routing_strategy strategy, bool fromCache = true);
// change the route of the specified output
uint32_t setOutputDevice(audio_io_handle_t output, audio_devices_t device, bool force = false, int delayMs = 0);
+
+ // when a device is connected, checks if an open output can be routed
+ // to this device. If none is open, tries to open one of the available outputs.
+ // Returns an output suitable to this device or 0.
+ // when a device is disconnected, checks if an output is not used any more and
+ // returns its handle if any.
+ // transfers the audio tracks and effects from one output thread to another accordingly.
+ status_t checkOutputsForDevice(audio_devices_t device,
+ AudioSystem::device_connection_state state,
+ SortedVector<audio_io_handle_t>& outputs);
+
+ virtual AudioPolicyManagerBase::IOProfile* getProfileForDirectOutput(
+ audio_devices_t device,
+ uint32_t samplingRate,
+ uint32_t format,
+ uint32_t channelMask,
+ audio_output_flags_t flags);
+
+
+ bool isCompatibleProfile(AudioPolicyManagerBase::IOProfile *profile,
+ audio_devices_t device,
+ uint32_t samplingRate,
+ uint32_t format,
+ uint32_t channelMask,
+ audio_output_flags_t flags);
+
// check that volume change is permitted, compute and send new volume to audio hardware
status_t checkAndSetVolume(int stream, int index, audio_io_handle_t output, audio_devices_t device, int delayMs = 0, bool force = false);
// select input device corresponding to requested audio source
virtual audio_devices_t getDeviceForInputSource(int inputSource);
- // Mute or unmute the stream on the specified output
- status_t stopInput(audio_io_handle_t input);
+
+
private:
+ // updates device caching and output for streams that can influence the
+ // routing of notifications
void handleNotificationRoutingForStream(AudioSystem::stream_type stream);
};
-};
+}; //namespace