routing_strategy strategy = getStrategy((AudioSystem::stream_type)stream);
#ifdef WITH_A2DP
- if (mA2dpOutput != 0 && !a2dpUsedForSonification() && strategy == STRATEGY_SONIFICATION) {
+ if (mA2dpOutput != 0 && !a2dpUsedForSonification() &&
+ (strategy == STRATEGY_SONIFICATION || strategy == STRATEGY_ENFORCED_AUDIBLE)) {
setStrategyMute(STRATEGY_MEDIA, true, mA2dpOutput);
}
#endif
// necassary for a correct control of hardware output routing by startOutput() and stopOutput()
outputDesc->changeRefCount(stream, 1);
+ uint32_t prevDevice = outputDesc->mDevice;
setOutputDevice(output, getNewDevice(output));
// handle special case for sonification while in call
// apply volume rules for current stream and device if necessary
checkAndSetVolume(stream, mStreams[stream].mIndexCur, output, outputDesc->device());
+ // FIXME: need a delay to make sure that audio path switches to speaker before sound
+ // starts. Should be platform specific?
+ if (stream == AudioSystem::ENFORCED_AUDIBLE &&
+ prevDevice != outputDesc->mDevice) {
+ usleep(outputDesc->mLatency*4*1000);
+ }
+
return NO_ERROR;
}
#ifdef WITH_A2DP
if (mA2dpOutput != 0 && !a2dpUsedForSonification() &&
- strategy == STRATEGY_SONIFICATION) {
+ (strategy == STRATEGY_SONIFICATION || strategy == STRATEGY_ENFORCED_AUDIBLE)) {
setStrategyMute(STRATEGY_MEDIA,
false,
mA2dpOutput,
if (!a2dpUsedForSonification()) {
// mute music on A2DP output if a notification or ringtone is playing
uint32_t refCount = hwOutputDesc->strategyRefCount(STRATEGY_SONIFICATION);
+ refCount += hwOutputDesc->strategyRefCount(STRATEGY_ENFORCED_AUDIBLE);
for (uint32_t i = 0; i < refCount; i++) {
setStrategyMute(STRATEGY_MEDIA, true, mA2dpOutput);
}
if (!a2dpUsedForSonification()) {
// unmute music on A2DP output if a notification or ringtone is playing
uint32_t refCount = mOutputs.valueFor(mHardwareOutput)->strategyRefCount(STRATEGY_SONIFICATION);
+ refCount += mOutputs.valueFor(mHardwareOutput)->strategyRefCount(STRATEGY_ENFORCED_AUDIBLE);
for (uint32_t i = 0; i < refCount; i++) {
setStrategyMute(STRATEGY_MEDIA, false, mA2dpOutput);
}
void AudioPolicyManagerBase::checkOutputForAllStrategies()
{
+ checkOutputForStrategy(STRATEGY_ENFORCED_AUDIBLE);
checkOutputForStrategy(STRATEGY_PHONE);
checkOutputForStrategy(STRATEGY_SONIFICATION);
checkOutputForStrategy(STRATEGY_MEDIA);
AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output);
// check the following by order of priority to request a routing change if necessary:
- // 1: we are in call or the strategy phone is active on the hardware output:
+ // 1: the strategy enforced audible is active on the output:
+ // use device for strategy enforced audible
+ // 2: we are in call or the strategy phone is active on the output:
// use device for strategy phone
- // 2: the strategy sonification is active on the hardware output:
+ // 3: the strategy sonification is active on the output:
// use device for strategy sonification
- // 3: the strategy media is active on the hardware output:
+ // 4: the strategy media is active on the output:
// use device for strategy media
- // 4: the strategy DTMF is active on the hardware output:
+ // 5: the strategy DTMF is active on the output:
// use device for strategy DTMF
- if (isInCall() ||
- outputDesc->isUsedByStrategy(STRATEGY_PHONE)) {
+ if (outputDesc->isUsedByStrategy(STRATEGY_ENFORCED_AUDIBLE)) {
+ device = getDeviceForStrategy(STRATEGY_ENFORCED_AUDIBLE, fromCache);
+ } else if (isInCall() ||
+ outputDesc->isUsedByStrategy(STRATEGY_PHONE)) {
device = getDeviceForStrategy(STRATEGY_PHONE, fromCache);
} else if (outputDesc->isUsedByStrategy(STRATEGY_SONIFICATION)) {
device = getDeviceForStrategy(STRATEGY_SONIFICATION, fromCache);
case AudioSystem::RING:
case AudioSystem::NOTIFICATION:
case AudioSystem::ALARM:
- case AudioSystem::ENFORCED_AUDIBLE:
return STRATEGY_SONIFICATION;
case AudioSystem::DTMF:
return STRATEGY_DTMF;
case AudioSystem::TTS:
case AudioSystem::MUSIC:
return STRATEGY_MEDIA;
+ case AudioSystem::ENFORCED_AUDIBLE:
+ return STRATEGY_ENFORCED_AUDIBLE;
}
}
device = getDeviceForStrategy(STRATEGY_PHONE, false);
break;
}
+ // FALL THROUGH
+
+ case STRATEGY_ENFORCED_AUDIBLE:
+ // strategy STRATEGY_ENFORCED_AUDIBLE uses same routing policy as STRATEGY_SONIFICATION
+ // except when in call where it doesn't default to STRATEGY_PHONE behavior
+
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
if (device == 0) {
LOGE("getDeviceForStrategy() speaker device not found");
}
#ifdef WITH_A2DP
if ((mA2dpOutput != 0) && !mA2dpSuspended &&
- (strategy != STRATEGY_SONIFICATION || a2dpUsedForSonification())) {
+ (strategy == STRATEGY_MEDIA || a2dpUsedForSonification())) {
if (device2 == 0) {
device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP;
}
device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
}
- // device is DEVICE_OUT_SPEAKER if we come from case STRATEGY_SONIFICATION, 0 otherwise
+ // device is DEVICE_OUT_SPEAKER if we come from case STRATEGY_SONIFICATION or
+ // STRATEGY_ENFORCED_AUDIBLE, 0 otherwise
device |= device2;
if (device == 0) {
LOGE("getDeviceForStrategy() speaker device not found");
if (output == mHardwareOutput && AudioSystem::popCount(device) == 2) {
setStrategyMute(STRATEGY_MEDIA, true, output);
// wait for the PCM output buffers to empty before proceeding with the rest of the command
- usleep(outputDesc->mLatency*2*1000);
+ // FIXME: increased delay due to larger buffers used for low power audio mode.
+ // remove when low power audio is controlled by policy manager.
+ usleep(outputDesc->mLatency*8*1000);
}
// do the routing
sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET
sDefaultVolumeCurve, // DEVICE_CATEGORY_SPEAKER
sDefaultVolumeCurve // DEVICE_CATEGORY_EARPIECE
- }
+ },
+ { // STRATEGY_ENFORCED_AUDIBLE
+ sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET
+ sSpeakerSonificationVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+ sDefaultVolumeCurve // DEVICE_CATEGORY_EARPIECE
+ },
};
void AudioPolicyManagerBase::initializeVolumeCurves()