OSDN Git Service

powerbtnd: add poweroff.doubleclick feature
[android-x86/hardware-libhardware_legacy.git] / audio / AudioPolicyManagerBase.cpp
index 9164646..ac31ad4 100644 (file)
@@ -562,7 +562,8 @@ status_t AudioPolicyManagerBase::startOutput(audio_io_handle_t output,
     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
@@ -572,6 +573,7 @@ status_t AudioPolicyManagerBase::startOutput(audio_io_handle_t output,
     // 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
@@ -582,6 +584,13 @@ status_t AudioPolicyManagerBase::startOutput(audio_io_handle_t output,
     // 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;
 }
 
@@ -614,7 +623,7 @@ status_t AudioPolicyManagerBase::stopOutput(audio_io_handle_t output,
 
 #ifdef WITH_A2DP
         if (mA2dpOutput != 0 && !a2dpUsedForSonification() &&
-                strategy == STRATEGY_SONIFICATION) {
+                (strategy == STRATEGY_SONIFICATION || strategy == STRATEGY_ENFORCED_AUDIBLE)) {
             setStrategyMute(STRATEGY_MEDIA,
                             false,
                             mA2dpOutput,
@@ -861,29 +870,23 @@ status_t AudioPolicyManagerBase::registerEffect(effect_descriptor_t *desc,
         }
     }
 
-    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;
@@ -899,21 +902,16 @@ status_t AudioPolicyManagerBase::unregisterEffect(int id)
 
     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;
@@ -921,6 +919,46 @@ status_t AudioPolicyManagerBase::unregisterEffect(int id)
     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();
@@ -1334,6 +1372,7 @@ status_t AudioPolicyManagerBase::handleA2dpConnection(AudioSystem::audio_devices
     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);
         }
@@ -1365,6 +1404,7 @@ status_t AudioPolicyManagerBase::handleA2dpDisconnection(AudioSystem::audio_devi
     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);
         }
@@ -1463,6 +1503,7 @@ void AudioPolicyManagerBase::checkOutputForStrategy(routing_strategy strategy)
 
 void AudioPolicyManagerBase::checkOutputForAllStrategies()
 {
+    checkOutputForStrategy(STRATEGY_ENFORCED_AUDIBLE);
     checkOutputForStrategy(STRATEGY_PHONE);
     checkOutputForStrategy(STRATEGY_SONIFICATION);
     checkOutputForStrategy(STRATEGY_MEDIA);
@@ -1519,16 +1560,20 @@ uint32_t AudioPolicyManagerBase::getNewDevice(audio_io_handle_t output, bool fro
 
     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);
@@ -1570,7 +1615,6 @@ AudioPolicyManagerBase::routing_strategy AudioPolicyManagerBase::getStrategy(
     case AudioSystem::RING:
     case AudioSystem::NOTIFICATION:
     case AudioSystem::ALARM:
-    case AudioSystem::ENFORCED_AUDIBLE:
         return STRATEGY_SONIFICATION;
     case AudioSystem::DTMF:
         return STRATEGY_DTMF;
@@ -1582,6 +1626,8 @@ AudioPolicyManagerBase::routing_strategy AudioPolicyManagerBase::getStrategy(
     case AudioSystem::TTS:
     case AudioSystem::MUSIC:
         return STRATEGY_MEDIA;
+    case AudioSystem::ENFORCED_AUDIBLE:
+        return STRATEGY_ENFORCED_AUDIBLE;
     }
 }
 
@@ -1634,10 +1680,10 @@ uint32_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy strategy,
                 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;
@@ -1655,10 +1701,10 @@ uint32_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy strategy,
                 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;
@@ -1677,6 +1723,12 @@ uint32_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy strategy,
             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");
@@ -1691,7 +1743,7 @@ uint32_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy strategy,
         }
 #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;
             }
@@ -1704,10 +1756,10 @@ uint32_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy strategy,
         }
 #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;
@@ -1716,7 +1768,8 @@ uint32_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy strategy,
             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");
@@ -1774,7 +1827,9 @@ void AudioPolicyManagerBase::setOutputDevice(audio_io_handle_t output, uint32_t
     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
@@ -1839,68 +1894,155 @@ audio_io_handle_t AudioPolicyManagerBase::getActiveInput()
     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)
@@ -1916,7 +2058,8 @@ float AudioPolicyManagerBase::computeVolume(int stream, int index, audio_io_hand
     // 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;
     }
 
@@ -2279,6 +2422,8 @@ status_t AudioPolicyManagerBase::EffectDescriptor::dump(int fd)
     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;