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 (mTotalEffectsCpuLoad + desc->cpuLoad > getMaxEffectsCpuLoad()) {
- LOGW("registerEffect() CPU Load limit exceeded for Fx %s, CPU %f MIPS",
- desc->name, (float)desc->cpuLoad/10);
- return INVALID_OPERATION;
- }
if (mTotalEffectsMemory + desc->memoryUsage > getMaxEffectsMemory()) {
LOGW("registerEffect() memory limit exceeded for Fx %s, Memory %d KB",
desc->name, desc->memoryUsage);
return INVALID_OPERATION;
}
- mTotalEffectsCpuLoad += desc->cpuLoad;
mTotalEffectsMemory += desc->memoryUsage;
LOGV("registerEffect() effect %s, io %d, strategy %d session %d id %d",
desc->name, io, strategy, session, id);
-
- LOGV("registerEffect() CPU %d, memory %d", desc->cpuLoad, desc->memoryUsage);
- LOGV(" total CPU %d, total memory %d", mTotalEffectsCpuLoad, mTotalEffectsMemory);
+ LOGV("registerEffect() memory %d, total memory %d", desc->memoryUsage, mTotalEffectsMemory);
EffectDescriptor *pDesc = new EffectDescriptor();
memcpy (&pDesc->mDesc, desc, sizeof(effect_descriptor_t));
pDesc->mIo = io;
pDesc->mStrategy = (routing_strategy)strategy;
pDesc->mSession = session;
+ pDesc->mEnabled = false;
+
mEffects.add(id, pDesc);
return NO_ERROR;
EffectDescriptor *pDesc = mEffects.valueAt(index);
- if (mTotalEffectsCpuLoad < pDesc->mDesc.cpuLoad) {
- LOGW("unregisterEffect() CPU load %d too high for total %d",
- pDesc->mDesc.cpuLoad, mTotalEffectsCpuLoad);
- pDesc->mDesc.cpuLoad = mTotalEffectsCpuLoad;
- }
- mTotalEffectsCpuLoad -= pDesc->mDesc.cpuLoad;
+ setEffectEnabled(pDesc, false);
+
if (mTotalEffectsMemory < pDesc->mDesc.memoryUsage) {
LOGW("unregisterEffect() memory %d too big for total %d",
pDesc->mDesc.memoryUsage, mTotalEffectsMemory);
pDesc->mDesc.memoryUsage = mTotalEffectsMemory;
}
mTotalEffectsMemory -= pDesc->mDesc.memoryUsage;
- LOGV("unregisterEffect() effect %s, ID %d, CPU %d, memory %d",
- pDesc->mDesc.name, id, pDesc->mDesc.cpuLoad, pDesc->mDesc.memoryUsage);
- LOGV(" total CPU %d, total memory %d", mTotalEffectsCpuLoad, mTotalEffectsMemory);
+ LOGV("unregisterEffect() effect %s, ID %d, memory %d total memory %d",
+ pDesc->mDesc.name, id, pDesc->mDesc.memoryUsage, mTotalEffectsMemory);
mEffects.removeItem(id);
delete pDesc;
return NO_ERROR;
}
+status_t AudioPolicyManagerBase::setEffectEnabled(int id, bool enabled)
+{
+ ssize_t index = mEffects.indexOfKey(id);
+ if (index < 0) {
+ LOGW("unregisterEffect() unknown effect ID %d", id);
+ return INVALID_OPERATION;
+ }
+
+ return setEffectEnabled(mEffects.valueAt(index), enabled);
+}
+
+status_t AudioPolicyManagerBase::setEffectEnabled(EffectDescriptor *pDesc, bool enabled)
+{
+ if (enabled == pDesc->mEnabled) {
+ LOGV("setEffectEnabled(%s) effect already %s",
+ enabled?"true":"false", enabled?"enabled":"disabled");
+ return INVALID_OPERATION;
+ }
+
+ if (enabled) {
+ if (mTotalEffectsCpuLoad + pDesc->mDesc.cpuLoad > getMaxEffectsCpuLoad()) {
+ LOGW("setEffectEnabled(true) CPU Load limit exceeded for Fx %s, CPU %f MIPS",
+ pDesc->mDesc.name, (float)pDesc->mDesc.cpuLoad/10);
+ return INVALID_OPERATION;
+ }
+ mTotalEffectsCpuLoad += pDesc->mDesc.cpuLoad;
+ LOGV("setEffectEnabled(true) total CPU %d", mTotalEffectsCpuLoad);
+ } else {
+ if (mTotalEffectsCpuLoad < pDesc->mDesc.cpuLoad) {
+ LOGW("setEffectEnabled(false) CPU load %d too high for total %d",
+ pDesc->mDesc.cpuLoad, mTotalEffectsCpuLoad);
+ pDesc->mDesc.cpuLoad = mTotalEffectsCpuLoad;
+ }
+ mTotalEffectsCpuLoad -= pDesc->mDesc.cpuLoad;
+ LOGV("setEffectEnabled(false) total CPU %d", mTotalEffectsCpuLoad);
+ }
+ pDesc->mEnabled = enabled;
+ return NO_ERROR;
+}
+
bool AudioPolicyManagerBase::isStreamActive(int stream, uint32_t inPastMs) const
{
nsecs_t sysTime = systemTime();
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;
}
}
if (device) break;
}
#endif
- device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL;
- 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;
if (device) break;
}
#endif
- device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL;
- 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;
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;
}
}
#endif
if (device2 == 0) {
- device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL;
+ device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET;
}
if (device2 == 0) {
- device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET;
+ device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL;
}
if (device2 == 0) {
device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET;
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
return 0;
}
+
+AudioPolicyManagerBase::device_category AudioPolicyManagerBase::getDeviceCategory(uint32_t device)
+{
+ if (device == 0) {
+ // this happens when forcing a route update and no track is active on an output.
+ // In this case the returned category is not important.
+ return DEVICE_CATEGORY_SPEAKER;
+ }
+
+ if (AudioSystem::popCount(device) > 1) {
+ // Multiple device selection is either:
+ // - speaker + one other device: give priority to speaker in this case.
+ // - one A2DP device + another device: happens with duplicated output. In this case
+ // retain the device on the A2DP output as the other must not correspond to an active
+ // selection if not the speaker.
+ if (device & AUDIO_DEVICE_OUT_SPEAKER)
+ return DEVICE_CATEGORY_SPEAKER;
+
+ device &= AUDIO_DEVICE_OUT_ALL_A2DP;
+ }
+
+ LOGW_IF(AudioSystem::popCount(device) != 1,
+ "getDeviceCategory() invalid device combination: %08x",
+ device);
+
+ switch(device) {
+ case AUDIO_DEVICE_OUT_EARPIECE:
+ return DEVICE_CATEGORY_EARPIECE;
+ case AUDIO_DEVICE_OUT_WIRED_HEADSET:
+ case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
+ case AUDIO_DEVICE_OUT_BLUETOOTH_SCO:
+ case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET:
+ case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
+ case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
+ return DEVICE_CATEGORY_HEADSET;
+ case AUDIO_DEVICE_OUT_SPEAKER:
+ case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT:
+ case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:
+ default:
+ return DEVICE_CATEGORY_SPEAKER;
+ }
+}
+
float AudioPolicyManagerBase::volIndexToAmpl(uint32_t device, const StreamDescriptor& streamDesc,
- int indexInUi) {
+ int indexInUi)
+{
+ device_category deviceCategory = getDeviceCategory(device);
+ const VolumeCurvePoint *curve = streamDesc.mVolumeCurve[deviceCategory];
+
// the volume index in the UI is relative to the min and max volume indices for this stream type
- int nbSteps = 1 + streamDesc.mVolIndex[StreamDescriptor::VOLMAX] -
- streamDesc.mVolIndex[StreamDescriptor::VOLMIN];
+ int nbSteps = 1 + curve[VOLMAX].mIndex -
+ curve[VOLMIN].mIndex;
int volIdx = (nbSteps * (indexInUi - streamDesc.mIndexMin)) /
(streamDesc.mIndexMax - streamDesc.mIndexMin);
// find what part of the curve this index volume belongs to, or if it's out of bounds
int segment = 0;
- if (volIdx < streamDesc.mVolIndex[StreamDescriptor::VOLMIN]) { // out of bounds
+ if (volIdx < curve[VOLMIN].mIndex) { // out of bounds
return 0.0f;
- } else if (volIdx < streamDesc.mVolIndex[StreamDescriptor::VOLKNEE1]) {
+ } else if (volIdx < curve[VOLKNEE1].mIndex) {
segment = 0;
- } else if (volIdx < streamDesc.mVolIndex[StreamDescriptor::VOLKNEE2]) {
+ } else if (volIdx < curve[VOLKNEE2].mIndex) {
segment = 1;
- } else if (volIdx <= streamDesc.mVolIndex[StreamDescriptor::VOLMAX]) {
+ } else if (volIdx <= curve[VOLMAX].mIndex) {
segment = 2;
} else { // out of bounds
return 1.0f;
}
// linear interpolation in the attenuation table in dB
- float decibels = streamDesc.mVolDbAtt[segment] +
- ((float)(volIdx - streamDesc.mVolIndex[segment])) *
- ( (streamDesc.mVolDbAtt[segment+1] - streamDesc.mVolDbAtt[segment]) /
- ((float)(streamDesc.mVolIndex[segment+1] - streamDesc.mVolIndex[segment])) );
+ float decibels = curve[segment].mDBAttenuation +
+ ((float)(volIdx - curve[segment].mIndex)) *
+ ( (curve[segment+1].mDBAttenuation -
+ curve[segment].mDBAttenuation) /
+ ((float)(curve[segment+1].mIndex -
+ curve[segment].mIndex)) );
float amplification = exp( decibels * 0.115129f); // exp( dB * ln(10) / 20 )
LOGV("VOLUME vol index=[%d %d %d], dB=[%.1f %.1f %.1f] ampl=%.5f",
- streamDesc.mVolIndex[segment], volIdx, streamDesc.mVolIndex[segment+1],
- streamDesc.mVolDbAtt[segment], decibels, streamDesc.mVolDbAtt[segment+1],
+ curve[segment].mIndex, volIdx,
+ curve[segment+1].mIndex,
+ curve[segment].mDBAttenuation,
+ decibels,
+ curve[segment+1].mDBAttenuation,
amplification);
return amplification;
}
-void AudioPolicyManagerBase::initializeVolumeCurves() {
- // initialize the volume curves to a (-49.5 - 0 dB) attenuation in 0.5dB steps
- for (int i=0 ; i< AudioSystem::NUM_STREAM_TYPES ; i++) {
- mStreams[i].mVolIndex[StreamDescriptor::VOLMIN] = 1;
- mStreams[i].mVolDbAtt[StreamDescriptor::VOLMIN] = -49.5f;
- mStreams[i].mVolIndex[StreamDescriptor::VOLKNEE1] = 33;
- mStreams[i].mVolDbAtt[StreamDescriptor::VOLKNEE1] = -33.5f;
- mStreams[i].mVolIndex[StreamDescriptor::VOLKNEE2] = 66;
- mStreams[i].mVolDbAtt[StreamDescriptor::VOLKNEE2] = -17.0f;
- // here we use 100 steps to avoid rounding errors
- // when computing the volume in volIndexToAmpl()
- mStreams[i].mVolIndex[StreamDescriptor::VOLMAX] = 100;
- mStreams[i].mVolDbAtt[StreamDescriptor::VOLMAX] = 0.0f;
- }
-
- // Modification for music: more attenuation for lower volumes, finer steps at high volumes
- mStreams[AudioSystem::MUSIC].mVolIndex[StreamDescriptor::VOLMIN] = 1;
- mStreams[AudioSystem::MUSIC].mVolDbAtt[StreamDescriptor::VOLMIN] = -58.0f;
- mStreams[AudioSystem::MUSIC].mVolIndex[StreamDescriptor::VOLKNEE1] = 20;
- mStreams[AudioSystem::MUSIC].mVolDbAtt[StreamDescriptor::VOLKNEE1] = -40.0f;
- mStreams[AudioSystem::MUSIC].mVolIndex[StreamDescriptor::VOLKNEE2] = 60;
- mStreams[AudioSystem::MUSIC].mVolDbAtt[StreamDescriptor::VOLKNEE2] = -17.0f;
- mStreams[AudioSystem::MUSIC].mVolIndex[StreamDescriptor::VOLMAX] = 100;
- mStreams[AudioSystem::MUSIC].mVolDbAtt[StreamDescriptor::VOLMAX] = 0.0f;
+const AudioPolicyManagerBase::VolumeCurvePoint
+ AudioPolicyManagerBase::sDefaultVolumeCurve[AudioPolicyManagerBase::VOLCNT] = {
+ {1, -49.5f}, {33, -33.5f}, {66, -17.0f}, {100, 0.0f}
+};
+
+const AudioPolicyManagerBase::VolumeCurvePoint
+ AudioPolicyManagerBase::sDefaultMediaVolumeCurve[AudioPolicyManagerBase::VOLCNT] = {
+ {1, -58.0f}, {20, -40.0f}, {60, -17.0f}, {100, 0.0f}
+};
+
+const AudioPolicyManagerBase::VolumeCurvePoint
+ AudioPolicyManagerBase::sSpeakerMediaVolumeCurve[AudioPolicyManagerBase::VOLCNT] = {
+ {1, -56.0f}, {20, -34.0f}, {60, -11.0f}, {100, 0.0f}
+};
+
+const AudioPolicyManagerBase::VolumeCurvePoint
+ AudioPolicyManagerBase::sSpeakerSonificationVolumeCurve[AudioPolicyManagerBase::VOLCNT] = {
+ {1, -29.7f}, {33, -20.1f}, {66, -10.2f}, {100, 0.0f}
+};
+
+
+const AudioPolicyManagerBase::VolumeCurvePoint
+ *AudioPolicyManagerBase::sVolumeProfiles[AudioPolicyManagerBase::NUM_STRATEGIES]
+ [AudioPolicyManagerBase::DEVICE_CATEGORY_CNT] = {
+ { // STRATEGY_MEDIA
+ sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_HEADSET
+ sSpeakerMediaVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+ sDefaultMediaVolumeCurve // DEVICE_CATEGORY_EARPIECE
+ },
+ { // STRATEGY_PHONE
+ sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET
+ sDefaultVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+ sDefaultVolumeCurve // DEVICE_CATEGORY_EARPIECE
+ },
+ { // STRATEGY_SONIFICATION
+ sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET
+ sSpeakerSonificationVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+ sDefaultVolumeCurve // DEVICE_CATEGORY_EARPIECE
+ },
+ { // STRATEGY_DTMF
+ 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()
+{
+ for (int i = 0; i < AudioSystem::NUM_STREAM_TYPES; i++) {
+ for (int j = 0; j < DEVICE_CATEGORY_CNT; j++) {
+ mStreams[i].mVolumeCurve[j] =
+ sVolumeProfiles[getStrategy((AudioSystem::stream_type)i)][j];
+ }
+ }
}
float AudioPolicyManagerBase::computeVolume(int stream, int index, audio_io_handle_t output, uint32_t device)
// if volume is not 0 (not muted), force media volume to max on digital output
if (stream == AudioSystem::MUSIC &&
index != mStreams[stream].mIndexMin &&
- device == AudioSystem::DEVICE_OUT_AUX_DIGITAL) {
+ (device == AudioSystem::DEVICE_OUT_AUX_DIGITAL ||
+ device == AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)) {
return 1.0;
}
result.append(buffer);
snprintf(buffer, SIZE, " Name: %s\n", mDesc.name);
result.append(buffer);
+ snprintf(buffer, SIZE, " %s\n", mEnabled ? "Enabled" : "Disabled");
+ result.append(buffer);
write(fd, result.string(), result.size());
return NO_ERROR;