Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dfd7409c authored by François Gaffie's avatar François Gaffie Committed by Jean-Michel Trivi
Browse files

Create StreamDescriptor and associated collection within common



Create StreamDescriptor and associated collection within common
common policy pillar elements.
It moves the code from managerdefault and creates helpers function within
the collection.
It also split the AudioGain in a common volume header and AudioGain class.

Change-Id: I1bb80e4219506f8c9042367085db328d317cb668
Signed-off-by: default avatarFrançois Gaffie <francois.gaffie@intel.com>
parent df372698
Loading
Loading
Loading
Loading
+137 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <system/audio.h>
#include <utils/Log.h>

class VolumeCurvePoint
{
public:
    int mIndex;
    float mDBAttenuation;
};

class Volume
{
public:
    /**
     * 4 points to define the volume attenuation curve, each characterized by the volume
     * index (from 0 to 100) at which they apply, and the attenuation in dB at that index.
     * we use 100 steps to avoid rounding errors when computing the volume in volIndexToAmpl()
     *
     * @todo shall become configurable
     */
    enum {
        VOLMIN = 0,
        VOLKNEE1 = 1,
        VOLKNEE2 = 2,
        VOLMAX = 3,

        VOLCNT = 4
    };

    /**
     * device categories used for volume curve management.
     */
    enum device_category {
        DEVICE_CATEGORY_HEADSET,
        DEVICE_CATEGORY_SPEAKER,
        DEVICE_CATEGORY_EARPIECE,
        DEVICE_CATEGORY_EXT_MEDIA,
        DEVICE_CATEGORY_CNT
    };

    /**
     * extract one device relevant for volume control from multiple device selection
     *
     * @param[in] device for which the volume category is associated
     *
     * @return subset of device required to limit the number of volume category per device
     */
    static audio_devices_t getDeviceForVolume(audio_devices_t device)
    {
        if (device == AUDIO_DEVICE_NONE) {
            // this happens when forcing a route update and no track is active on an output.
            // In this case the returned category is not important.
            device =  AUDIO_DEVICE_OUT_SPEAKER;
        } else if (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.
            //  - HDMI-CEC system audio mode only output: give priority to available item in order.
            if (device & AUDIO_DEVICE_OUT_SPEAKER) {
                device = AUDIO_DEVICE_OUT_SPEAKER;
            } else if (device & AUDIO_DEVICE_OUT_HDMI_ARC) {
                device = AUDIO_DEVICE_OUT_HDMI_ARC;
            } else if (device & AUDIO_DEVICE_OUT_AUX_LINE) {
                device = AUDIO_DEVICE_OUT_AUX_LINE;
            } else if (device & AUDIO_DEVICE_OUT_SPDIF) {
                device = AUDIO_DEVICE_OUT_SPDIF;
            } else {
                device = (audio_devices_t)(device & AUDIO_DEVICE_OUT_ALL_A2DP);
            }
        }

        /*SPEAKER_SAFE is an alias of SPEAKER for purposes of volume control*/
        if (device == AUDIO_DEVICE_OUT_SPEAKER_SAFE)
            device = AUDIO_DEVICE_OUT_SPEAKER;

        ALOGW_IF(popcount(device) != 1,
                 "getDeviceForVolume() invalid device combination: %08x",
                 device);

        return device;
    }

    /**
     * returns the category the device belongs to with regard to volume curve management
     *
     * @param[in] device to check upon the category to whom it belongs to.
     *
     * @return device category.
     */
    static device_category getDeviceCategory(audio_devices_t device)
    {
        switch(getDeviceForVolume(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_LINE:
        case AUDIO_DEVICE_OUT_AUX_DIGITAL:
            /*USB?  Remote submix?*/
            return DEVICE_CATEGORY_EXT_MEDIA;
        case AUDIO_DEVICE_OUT_SPEAKER:
        case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT:
        case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:
        case AUDIO_DEVICE_OUT_USB_ACCESSORY:
        case AUDIO_DEVICE_OUT_USB_DEVICE:
        case AUDIO_DEVICE_OUT_REMOTE_SUBMIX:
        default:
            return DEVICE_CATEGORY_SPEAKER;
        }
    }

};
+1 −0
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
    src/DeviceDescriptor.cpp \
    src/AudioGain.cpp \
    src/StreamDescriptor.cpp \
    src/HwModule.cpp \
    src/IOProfile.cpp \
    src/AudioPort.cpp \
+17 −62
Original line number Diff line number Diff line
@@ -16,70 +16,43 @@

#pragma once

#include <Volume.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <system/audio.h>
#include <utils/KeyedVector.h>

namespace android {

class VolumeCurvePoint
{
public:
    int mIndex;
    float mDBAttenuation;
};

class StreamDescriptor;

class ApmGains
{
public :
    // 4 points to define the volume attenuation curve, each characterized by the volume
    // index (from 0 to 100) at which they apply, and the attenuation in dB at that index.
    // we use 100 steps to avoid rounding errors when computing the volume in volIndexToAmpl()
    enum { VOLMIN = 0, VOLKNEE1 = 1, VOLKNEE2 = 2, VOLMAX = 3, VOLCNT = 4};

    // device categories used for volume curve management.
    enum device_category {
        DEVICE_CATEGORY_HEADSET,
        DEVICE_CATEGORY_SPEAKER,
        DEVICE_CATEGORY_EARPIECE,
        DEVICE_CATEGORY_EXT_MEDIA,
        DEVICE_CATEGORY_CNT
    };

    // returns the category the device belongs to with regard to volume curve management
    static ApmGains::device_category getDeviceCategory(audio_devices_t device);

    // extract one device relevant for volume control from multiple device selection
    static audio_devices_t getDeviceForVolume(audio_devices_t device);

    static float volIndexToAmpl(audio_devices_t device, const StreamDescriptor& streamDesc,
                    int indexInUi);

    // default volume curve
    static const VolumeCurvePoint sDefaultVolumeCurve[ApmGains::VOLCNT];
    static const VolumeCurvePoint sDefaultVolumeCurve[Volume::VOLCNT];
    // default volume curve for media strategy
    static const VolumeCurvePoint sDefaultMediaVolumeCurve[ApmGains::VOLCNT];
    static const VolumeCurvePoint sDefaultMediaVolumeCurve[Volume::VOLCNT];
    // volume curve for non-media audio on ext media outputs (HDMI, Line, etc)
    static const VolumeCurvePoint sExtMediaSystemVolumeCurve[ApmGains::VOLCNT];
    static const VolumeCurvePoint sExtMediaSystemVolumeCurve[Volume::VOLCNT];
    // volume curve for media strategy on speakers
    static const VolumeCurvePoint sSpeakerMediaVolumeCurve[ApmGains::VOLCNT];
    static const VolumeCurvePoint sSpeakerMediaVolumeCurveDrc[ApmGains::VOLCNT];
    static const VolumeCurvePoint sSpeakerMediaVolumeCurve[Volume::VOLCNT];
    static const VolumeCurvePoint sSpeakerMediaVolumeCurveDrc[Volume::VOLCNT];
    // volume curve for sonification strategy on speakers
    static const VolumeCurvePoint sSpeakerSonificationVolumeCurve[ApmGains::VOLCNT];
    static const VolumeCurvePoint sSpeakerSonificationVolumeCurveDrc[ApmGains::VOLCNT];
    static const VolumeCurvePoint sDefaultSystemVolumeCurve[ApmGains::VOLCNT];
    static const VolumeCurvePoint sDefaultSystemVolumeCurveDrc[ApmGains::VOLCNT];
    static const VolumeCurvePoint sHeadsetSystemVolumeCurve[ApmGains::VOLCNT];
    static const VolumeCurvePoint sDefaultVoiceVolumeCurve[ApmGains::VOLCNT];
    static const VolumeCurvePoint sSpeakerVoiceVolumeCurve[ApmGains::VOLCNT];
    static const VolumeCurvePoint sLinearVolumeCurve[ApmGains::VOLCNT];
    static const VolumeCurvePoint sSilentVolumeCurve[ApmGains::VOLCNT];
    static const VolumeCurvePoint sFullScaleVolumeCurve[ApmGains::VOLCNT];
    static const VolumeCurvePoint sSpeakerSonificationVolumeCurve[Volume::VOLCNT];
    static const VolumeCurvePoint sSpeakerSonificationVolumeCurveDrc[Volume::VOLCNT];
    static const VolumeCurvePoint sDefaultSystemVolumeCurve[Volume::VOLCNT];
    static const VolumeCurvePoint sDefaultSystemVolumeCurveDrc[Volume::VOLCNT];
    static const VolumeCurvePoint sHeadsetSystemVolumeCurve[Volume::VOLCNT];
    static const VolumeCurvePoint sDefaultVoiceVolumeCurve[Volume::VOLCNT];
    static const VolumeCurvePoint sSpeakerVoiceVolumeCurve[Volume::VOLCNT];
    static const VolumeCurvePoint sLinearVolumeCurve[Volume::VOLCNT];
    static const VolumeCurvePoint sSilentVolumeCurve[Volume::VOLCNT];
    static const VolumeCurvePoint sFullScaleVolumeCurve[Volume::VOLCNT];
    // default volume curves per stream and device category. See initializeVolumeCurves()
    static const VolumeCurvePoint *sVolumeProfiles[AUDIO_STREAM_CNT][ApmGains::DEVICE_CATEGORY_CNT];
    static const VolumeCurvePoint *sVolumeProfiles[AUDIO_STREAM_CNT][Volume::DEVICE_CATEGORY_CNT];
};


@@ -98,22 +71,4 @@ public:
    bool              mUseInChannelMask;
};


// stream descriptor used for volume control
class StreamDescriptor
{
public:
    StreamDescriptor();

    int getVolumeIndex(audio_devices_t device);
    void dump(int fd);

    int mIndexMin;      // min volume index
    int mIndexMax;      // max volume index
    KeyedVector<audio_devices_t, int> mIndexCur;   // current volume index per device
    bool mCanBeMuted;   // true is the stream can be muted

    const VolumeCurvePoint *mVolumeCurve[ApmGains::DEVICE_CATEGORY_CNT];
};

}; // namespace android
+85 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <Volume.h>
#include <utils/KeyedVector.h>
#include <utils/StrongPointer.h>
#include <utils/SortedVector.h>
#include <hardware/audio.h>

namespace android {

// stream descriptor used for volume control
class StreamDescriptor
{
public:
    StreamDescriptor();

    int getVolumeIndex(audio_devices_t device) const;
    bool canBeMuted() const { return mCanBeMuted; }
    void clearCurrentVolumeIndex();
    void addCurrentVolumeIndex(audio_devices_t device, int index);
    int getVolumeIndexMin() const { return mIndexMin; }
    int getVolumeIndexMax() const { return mIndexMax; }
    void setVolumeIndexMin(int volIndexMin);
    void setVolumeIndexMax(int volIndexMax);

    void dump(int fd) const;

    void setVolumeCurvePoint(Volume::device_category deviceCategory, const VolumeCurvePoint *point);
    const VolumeCurvePoint *getVolumeCurvePoint(Volume::device_category deviceCategory) const
    {
        return mVolumeCurve[deviceCategory];
    }

private:
    const VolumeCurvePoint *mVolumeCurve[Volume::DEVICE_CATEGORY_CNT];
    KeyedVector<audio_devices_t, int> mIndexCur; /**< current volume index per device. */
    int mIndexMin; /**< min volume index. */
    int mIndexMax; /**< max volume index. */
    bool mCanBeMuted; /**< true is the stream can be muted. */
};

/**
 * stream descriptors collection for volume control
 */
class StreamDescriptorCollection : public DefaultKeyedVector<audio_stream_type_t, StreamDescriptor>
{
public:
    StreamDescriptorCollection();

    void clearCurrentVolumeIndex(audio_stream_type_t stream);
    void addCurrentVolumeIndex(audio_stream_type_t stream, audio_devices_t device, int index);

    bool canBeMuted(audio_stream_type_t stream);

    status_t dump(int fd) const;

    void setVolumeCurvePoint(audio_stream_type_t stream,
                             Volume::device_category deviceCategory,
                             const VolumeCurvePoint *point);

    const VolumeCurvePoint *getVolumeCurvePoint(audio_stream_type_t stream,
                                                Volume::device_category deviceCategory) const;

    void setVolumeIndexMin(audio_stream_type_t stream,int volIndexMin);
    void setVolumeIndexMax(audio_stream_type_t stream,int volIndexMax);

};

}; // namespace android
+27 −131
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#endif

#include "AudioGain.h"
#include "StreamDescriptor.h"
#include <utils/Log.h>
#include <utils/String8.h>

@@ -33,38 +34,38 @@
namespace android {

const VolumeCurvePoint
ApmGains::sDefaultVolumeCurve[ApmGains::VOLCNT] = {
ApmGains::sDefaultVolumeCurve[Volume::VOLCNT] = {
    {1, -49.5f}, {33, -33.5f}, {66, -17.0f}, {100, 0.0f}
};


const VolumeCurvePoint
ApmGains::sDefaultMediaVolumeCurve[ApmGains::VOLCNT] = {
ApmGains::sDefaultMediaVolumeCurve[Volume::VOLCNT] = {
    {1, -58.0f}, {20, -40.0f}, {60, -17.0f}, {100, 0.0f}
};

const VolumeCurvePoint
ApmGains::sExtMediaSystemVolumeCurve[ApmGains::VOLCNT] = {
ApmGains::sExtMediaSystemVolumeCurve[Volume::VOLCNT] = {
    {1, -58.0f}, {20, -40.0f}, {60, -21.0f}, {100, -10.0f}
};

const VolumeCurvePoint
ApmGains::sSpeakerMediaVolumeCurve[ApmGains::VOLCNT] = {
ApmGains::sSpeakerMediaVolumeCurve[Volume::VOLCNT] = {
    {1, -56.0f}, {20, -34.0f}, {60, -11.0f}, {100, 0.0f}
};

const VolumeCurvePoint
ApmGains::sSpeakerMediaVolumeCurveDrc[ApmGains::VOLCNT] = {
ApmGains::sSpeakerMediaVolumeCurveDrc[Volume::VOLCNT] = {
    {1, -55.0f}, {20, -43.0f}, {86, -12.0f}, {100, 0.0f}
};

const VolumeCurvePoint
ApmGains::sSpeakerSonificationVolumeCurve[ApmGains::VOLCNT] = {
ApmGains::sSpeakerSonificationVolumeCurve[Volume::VOLCNT] = {
    {1, -29.7f}, {33, -20.1f}, {66, -10.2f}, {100, 0.0f}
};

const VolumeCurvePoint
ApmGains::sSpeakerSonificationVolumeCurveDrc[ApmGains::VOLCNT] = {
ApmGains::sSpeakerSonificationVolumeCurveDrc[Volume::VOLCNT] = {
    {1, -35.7f}, {33, -26.1f}, {66, -13.2f}, {100, 0.0f}
};

@@ -74,47 +75,47 @@ ApmGains::sSpeakerSonificationVolumeCurveDrc[ApmGains::VOLCNT] = {
// The range is constrained between -24dB and -6dB over speaker and -30dB and -18dB over headset.

const VolumeCurvePoint
ApmGains::sDefaultSystemVolumeCurve[ApmGains::VOLCNT] = {
ApmGains::sDefaultSystemVolumeCurve[Volume::VOLCNT] = {
    {1, -24.0f}, {33, -18.0f}, {66, -12.0f}, {100, -6.0f}
};

const VolumeCurvePoint
ApmGains::sDefaultSystemVolumeCurveDrc[ApmGains::VOLCNT] = {
ApmGains::sDefaultSystemVolumeCurveDrc[Volume::VOLCNT] = {
    {1, -34.0f}, {33, -24.0f}, {66, -15.0f}, {100, -6.0f}
};

const VolumeCurvePoint
ApmGains::sHeadsetSystemVolumeCurve[ApmGains::VOLCNT] = {
ApmGains::sHeadsetSystemVolumeCurve[Volume::VOLCNT] = {
    {1, -30.0f}, {33, -26.0f}, {66, -22.0f}, {100, -18.0f}
};

const VolumeCurvePoint
ApmGains::sDefaultVoiceVolumeCurve[ApmGains::VOLCNT] = {
ApmGains::sDefaultVoiceVolumeCurve[Volume::VOLCNT] = {
    {0, -42.0f}, {33, -28.0f}, {66, -14.0f}, {100, 0.0f}
};

const VolumeCurvePoint
ApmGains::sSpeakerVoiceVolumeCurve[ApmGains::VOLCNT] = {
ApmGains::sSpeakerVoiceVolumeCurve[Volume::VOLCNT] = {
    {0, -24.0f}, {33, -16.0f}, {66, -8.0f}, {100, 0.0f}
};

const VolumeCurvePoint
ApmGains::sLinearVolumeCurve[ApmGains::VOLCNT] = {
ApmGains::sLinearVolumeCurve[Volume::VOLCNT] = {
    {0, -96.0f}, {33, -68.0f}, {66, -34.0f}, {100, 0.0f}
};

const VolumeCurvePoint
ApmGains::sSilentVolumeCurve[ApmGains::VOLCNT] = {
ApmGains::sSilentVolumeCurve[Volume::VOLCNT] = {
    {0, -96.0f}, {1, -96.0f}, {2, -96.0f}, {100, -96.0f}
};

const VolumeCurvePoint
ApmGains::sFullScaleVolumeCurve[ApmGains::VOLCNT] = {
ApmGains::sFullScaleVolumeCurve[Volume::VOLCNT] = {
    {0, 0.0f}, {1, 0.0f}, {2, 0.0f}, {100, 0.0f}
};

const VolumeCurvePoint *ApmGains::sVolumeProfiles[AUDIO_STREAM_CNT]
                                                  [ApmGains::DEVICE_CATEGORY_CNT] = {
                                                  [Volume::DEVICE_CATEGORY_CNT] = {
    { // AUDIO_STREAM_VOICE_CALL
        ApmGains::sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_HEADSET
        ApmGains::sSpeakerVoiceVolumeCurve, // DEVICE_CATEGORY_SPEAKER
@@ -196,94 +197,28 @@ const VolumeCurvePoint *ApmGains::sVolumeProfiles[AUDIO_STREAM_CNT]
    },
};

//static
audio_devices_t ApmGains::getDeviceForVolume(audio_devices_t device)
{
    if (device == AUDIO_DEVICE_NONE) {
        // this happens when forcing a route update and no track is active on an output.
        // In this case the returned category is not important.
        device =  AUDIO_DEVICE_OUT_SPEAKER;
    } else if (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.
        //  - HDMI-CEC system audio mode only output: give priority to available item in order.
        if (device & AUDIO_DEVICE_OUT_SPEAKER) {
            device = AUDIO_DEVICE_OUT_SPEAKER;
        } else if (device & AUDIO_DEVICE_OUT_HDMI_ARC) {
            device = AUDIO_DEVICE_OUT_HDMI_ARC;
        } else if (device & AUDIO_DEVICE_OUT_AUX_LINE) {
            device = AUDIO_DEVICE_OUT_AUX_LINE;
        } else if (device & AUDIO_DEVICE_OUT_SPDIF) {
            device = AUDIO_DEVICE_OUT_SPDIF;
        } else {
            device = (audio_devices_t)(device & AUDIO_DEVICE_OUT_ALL_A2DP);
        }
    }

    /*SPEAKER_SAFE is an alias of SPEAKER for purposes of volume control*/
    if (device == AUDIO_DEVICE_OUT_SPEAKER_SAFE)
        device = AUDIO_DEVICE_OUT_SPEAKER;

    ALOGW_IF(popcount(device) != 1,
            "getDeviceForVolume() invalid device combination: %08x",
            device);

    return device;
}

//static
ApmGains::device_category ApmGains::getDeviceCategory(audio_devices_t device)
{
    switch(getDeviceForVolume(device)) {
        case AUDIO_DEVICE_OUT_EARPIECE:
            return ApmGains::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 ApmGains::DEVICE_CATEGORY_HEADSET;
        case AUDIO_DEVICE_OUT_LINE:
        case AUDIO_DEVICE_OUT_AUX_DIGITAL:
        /*USB?  Remote submix?*/
            return ApmGains::DEVICE_CATEGORY_EXT_MEDIA;
        case AUDIO_DEVICE_OUT_SPEAKER:
        case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT:
        case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:
        case AUDIO_DEVICE_OUT_USB_ACCESSORY:
        case AUDIO_DEVICE_OUT_USB_DEVICE:
        case AUDIO_DEVICE_OUT_REMOTE_SUBMIX:
        default:
            return ApmGains::DEVICE_CATEGORY_SPEAKER;
    }
}

//static
float ApmGains::volIndexToAmpl(audio_devices_t device, const StreamDescriptor& streamDesc,
        int indexInUi)
{
    ApmGains::device_category deviceCategory = ApmGains::getDeviceCategory(device);
    const VolumeCurvePoint *curve = streamDesc.mVolumeCurve[deviceCategory];
    Volume::device_category deviceCategory = Volume::getDeviceCategory(device);
    const VolumeCurvePoint *curve = streamDesc.getVolumeCurvePoint(deviceCategory);

    // the volume index in the UI is relative to the min and max volume indices for this stream type
    int nbSteps = 1 + curve[ApmGains::VOLMAX].mIndex -
            curve[ApmGains::VOLMIN].mIndex;
    int volIdx = (nbSteps * (indexInUi - streamDesc.mIndexMin)) /
            (streamDesc.mIndexMax - streamDesc.mIndexMin);
    int nbSteps = 1 + curve[Volume::VOLMAX].mIndex -
            curve[Volume::VOLMIN].mIndex;
    int volIdx = (nbSteps * (indexInUi - streamDesc.getVolumeIndexMin())) /
            (streamDesc.getVolumeIndexMax() - streamDesc.getVolumeIndexMin());

    // find what part of the curve this index volume belongs to, or if it's out of bounds
    int segment = 0;
    if (volIdx < curve[ApmGains::VOLMIN].mIndex) {         // out of bounds
    if (volIdx < curve[Volume::VOLMIN].mIndex) {         // out of bounds
        return 0.0f;
    } else if (volIdx < curve[ApmGains::VOLKNEE1].mIndex) {
    } else if (volIdx < curve[Volume::VOLKNEE1].mIndex) {
        segment = 0;
    } else if (volIdx < curve[ApmGains::VOLKNEE2].mIndex) {
    } else if (volIdx < curve[Volume::VOLKNEE2].mIndex) {
        segment = 1;
    } else if (volIdx <= curve[ApmGains::VOLMAX].mIndex) {
    } else if (volIdx <= curve[Volume::VOLMAX].mIndex) {
        segment = 2;
    } else {                                                               // out of bounds
        return 1.0f;
@@ -406,43 +341,4 @@ void AudioGain::dump(int fd, int spaces, int index) const
    write(fd, result.string(), result.size());
}


// --- StreamDescriptor class implementation

StreamDescriptor::StreamDescriptor()
    :   mIndexMin(0), mIndexMax(1), mCanBeMuted(true)
{
    mIndexCur.add(AUDIO_DEVICE_OUT_DEFAULT, 0);
}

int StreamDescriptor::getVolumeIndex(audio_devices_t device)
{
    device = ApmGains::getDeviceForVolume(device);
    // there is always a valid entry for AUDIO_DEVICE_OUT_DEFAULT
    if (mIndexCur.indexOfKey(device) < 0) {
        device = AUDIO_DEVICE_OUT_DEFAULT;
    }
    return mIndexCur.valueFor(device);
}

void StreamDescriptor::dump(int fd)
{
    const size_t SIZE = 256;
    char buffer[SIZE];
    String8 result;

    snprintf(buffer, SIZE, "%s         %02d         %02d         ",
             mCanBeMuted ? "true " : "false", mIndexMin, mIndexMax);
    result.append(buffer);
    for (size_t i = 0; i < mIndexCur.size(); i++) {
        snprintf(buffer, SIZE, "%04x : %02d, ",
                 mIndexCur.keyAt(i),
                 mIndexCur.valueAt(i));
        result.append(buffer);
    }
    result.append("\n");

    write(fd, result.string(), result.size());
}

}; // namespace android
Loading