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

Commit 91b7a7b5 authored by Jean-Michel Trivi's avatar Jean-Michel Trivi Committed by Android (Google) Code Review
Browse files

Merge "Create StreamDescriptor and associated collection within common"

parents d0fd7e82 dfd7409c
Loading
Loading
Loading
Loading
+137 −0
Original line number Original line 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 Original line Diff line number Diff line
@@ -5,6 +5,7 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
LOCAL_SRC_FILES:= \
    src/DeviceDescriptor.cpp \
    src/DeviceDescriptor.cpp \
    src/AudioGain.cpp \
    src/AudioGain.cpp \
    src/StreamDescriptor.cpp \
    src/HwModule.cpp \
    src/HwModule.cpp \
    src/IOProfile.cpp \
    src/IOProfile.cpp \
    src/AudioPort.cpp \
    src/AudioPort.cpp \
+17 −62
Original line number Original line Diff line number Diff line
@@ -16,70 +16,43 @@


#pragma once
#pragma once


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


namespace android {
namespace android {


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

class StreamDescriptor;
class StreamDescriptor;


class ApmGains
class ApmGains
{
{
public :
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,
    static float volIndexToAmpl(audio_devices_t device, const StreamDescriptor& streamDesc,
                    int indexInUi);
                    int indexInUi);


    // default volume curve
    // default volume curve
    static const VolumeCurvePoint sDefaultVolumeCurve[ApmGains::VOLCNT];
    static const VolumeCurvePoint sDefaultVolumeCurve[Volume::VOLCNT];
    // default volume curve for media strategy
    // 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)
    // 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
    // volume curve for media strategy on speakers
    static const VolumeCurvePoint sSpeakerMediaVolumeCurve[ApmGains::VOLCNT];
    static const VolumeCurvePoint sSpeakerMediaVolumeCurve[Volume::VOLCNT];
    static const VolumeCurvePoint sSpeakerMediaVolumeCurveDrc[ApmGains::VOLCNT];
    static const VolumeCurvePoint sSpeakerMediaVolumeCurveDrc[Volume::VOLCNT];
    // volume curve for sonification strategy on speakers
    // volume curve for sonification strategy on speakers
    static const VolumeCurvePoint sSpeakerSonificationVolumeCurve[ApmGains::VOLCNT];
    static const VolumeCurvePoint sSpeakerSonificationVolumeCurve[Volume::VOLCNT];
    static const VolumeCurvePoint sSpeakerSonificationVolumeCurveDrc[ApmGains::VOLCNT];
    static const VolumeCurvePoint sSpeakerSonificationVolumeCurveDrc[Volume::VOLCNT];
    static const VolumeCurvePoint sDefaultSystemVolumeCurve[ApmGains::VOLCNT];
    static const VolumeCurvePoint sDefaultSystemVolumeCurve[Volume::VOLCNT];
    static const VolumeCurvePoint sDefaultSystemVolumeCurveDrc[ApmGains::VOLCNT];
    static const VolumeCurvePoint sDefaultSystemVolumeCurveDrc[Volume::VOLCNT];
    static const VolumeCurvePoint sHeadsetSystemVolumeCurve[ApmGains::VOLCNT];
    static const VolumeCurvePoint sHeadsetSystemVolumeCurve[Volume::VOLCNT];
    static const VolumeCurvePoint sDefaultVoiceVolumeCurve[ApmGains::VOLCNT];
    static const VolumeCurvePoint sDefaultVoiceVolumeCurve[Volume::VOLCNT];
    static const VolumeCurvePoint sSpeakerVoiceVolumeCurve[ApmGains::VOLCNT];
    static const VolumeCurvePoint sSpeakerVoiceVolumeCurve[Volume::VOLCNT];
    static const VolumeCurvePoint sLinearVolumeCurve[ApmGains::VOLCNT];
    static const VolumeCurvePoint sLinearVolumeCurve[Volume::VOLCNT];
    static const VolumeCurvePoint sSilentVolumeCurve[ApmGains::VOLCNT];
    static const VolumeCurvePoint sSilentVolumeCurve[Volume::VOLCNT];
    static const VolumeCurvePoint sFullScaleVolumeCurve[ApmGains::VOLCNT];
    static const VolumeCurvePoint sFullScaleVolumeCurve[Volume::VOLCNT];
    // default volume curves per stream and device category. See initializeVolumeCurves()
    // 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;
    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
}; // namespace android
+85 −0
Original line number Original line 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 Original line Diff line number Diff line
@@ -25,6 +25,7 @@
#endif
#endif


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


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


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




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


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


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


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


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


const VolumeCurvePoint
const VolumeCurvePoint
ApmGains::sSpeakerSonificationVolumeCurveDrc[ApmGains::VOLCNT] = {
ApmGains::sSpeakerSonificationVolumeCurveDrc[Volume::VOLCNT] = {
    {1, -35.7f}, {33, -26.1f}, {66, -13.2f}, {100, 0.0f}
    {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.
// The range is constrained between -24dB and -6dB over speaker and -30dB and -18dB over headset.


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


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


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


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


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


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


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


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


const VolumeCurvePoint *ApmGains::sVolumeProfiles[AUDIO_STREAM_CNT]
const VolumeCurvePoint *ApmGains::sVolumeProfiles[AUDIO_STREAM_CNT]
                                                  [ApmGains::DEVICE_CATEGORY_CNT] = {
                                                  [Volume::DEVICE_CATEGORY_CNT] = {
    { // AUDIO_STREAM_VOICE_CALL
    { // AUDIO_STREAM_VOICE_CALL
        ApmGains::sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_HEADSET
        ApmGains::sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_HEADSET
        ApmGains::sSpeakerVoiceVolumeCurve, // DEVICE_CATEGORY_SPEAKER
        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
//static
float ApmGains::volIndexToAmpl(audio_devices_t device, const StreamDescriptor& streamDesc,
float ApmGains::volIndexToAmpl(audio_devices_t device, const StreamDescriptor& streamDesc,
        int indexInUi)
        int indexInUi)
{
{
    ApmGains::device_category deviceCategory = ApmGains::getDeviceCategory(device);
    Volume::device_category deviceCategory = Volume::getDeviceCategory(device);
    const VolumeCurvePoint *curve = streamDesc.mVolumeCurve[deviceCategory];
    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
    // 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 -
    int nbSteps = 1 + curve[Volume::VOLMAX].mIndex -
            curve[ApmGains::VOLMIN].mIndex;
            curve[Volume::VOLMIN].mIndex;
    int volIdx = (nbSteps * (indexInUi - streamDesc.mIndexMin)) /
    int volIdx = (nbSteps * (indexInUi - streamDesc.getVolumeIndexMin())) /
            (streamDesc.mIndexMax - streamDesc.mIndexMin);
            (streamDesc.getVolumeIndexMax() - streamDesc.getVolumeIndexMin());


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