Android源码分析--AudioPolicyEngine设备路由(01)

  手机里有很多设备,比如外放,听筒,耳机,蓝牙,还可以分很多很细的设备,比如内置麦克风,耳机麦克风。在写程序的时候上层很少去管理这么多复杂的设备,Android都是通过底层AudioPolicyEngine进行自动切换控制的。比如插入耳机的时候,上层可能会收到广播,提醒耳机已经插入,但是程序并不需要将声音切换到耳机,在AudioPolicyEngine里面实现这样的功能切换。

  要介绍这个比较大的框架,需要一定的C++和Android源码经验才可以理解。但是我尽量尝试自己也是站在一个初学者的角度去分析源码,也可以从之前工作中碰到的问题出发进行分析,因为只有解决实际的问题,分析代码才会有意义。这个也是对自己两年Android Audio工作的总结。

 首先来看Android源码定义多少设备,因为google被墙的原因,自己去下载代码比较困难,公司的代码有很多修改,很多地方可能会误导大家。所以我推荐使用网页的形式,http://androidxref.com/,可以使用这个网站进行源码查看。后面的分析都是基于Android 8.0.0_r4 分支,Android 6.0之后底层的改动不大。

 查看/system/media/audio/include/system/audio-base.h文件,

8.0之前的定义在/system/media/audio/include/system/audio.h中,通过enum枚举很多设备。

enum {
    AUDIO_DEVICE_NONE = 0u, // 0x0
    AUDIO_DEVICE_BIT_IN = 2147483648u, // 0x80000000
    AUDIO_DEVICE_BIT_DEFAULT = 1073741824u, // 0x40000000
    AUDIO_DEVICE_OUT_EARPIECE = 1u, // 0x1
    AUDIO_DEVICE_OUT_SPEAKER = 2u, // 0x2
    AUDIO_DEVICE_OUT_WIRED_HEADSET = 4u, // 0x4
    AUDIO_DEVICE_OUT_WIRED_HEADPHONE = 8u, // 0x8
    AUDIO_DEVICE_OUT_BLUETOOTH_SCO = 16u, // 0x10
    AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 32u, // 0x20
    AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 64u, // 0x40
    AUDIO_DEVICE_OUT_BLUETOOTH_A2DP = 128u, // 0x80
    AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 256u, // 0x100
    AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 512u, // 0x200
    AUDIO_DEVICE_OUT_AUX_DIGITAL = 1024u, // 0x400
    AUDIO_DEVICE_OUT_HDMI = 1024u, // OUT_AUX_DIGITAL
    AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET = 2048u, // 0x800
    AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET = 4096u, // 0x1000
    AUDIO_DEVICE_OUT_USB_ACCESSORY = 8192u, // 0x2000
    AUDIO_DEVICE_OUT_USB_DEVICE = 16384u, // 0x4000
    AUDIO_DEVICE_OUT_REMOTE_SUBMIX = 32768u, // 0x8000
    AUDIO_DEVICE_OUT_TELEPHONY_TX = 65536u, // 0x10000
    AUDIO_DEVICE_OUT_LINE = 131072u, // 0x20000
    AUDIO_DEVICE_OUT_HDMI_ARC = 262144u, // 0x40000
    AUDIO_DEVICE_OUT_SPDIF = 524288u, // 0x80000
    AUDIO_DEVICE_OUT_FM = 1048576u, // 0x100000
    AUDIO_DEVICE_OUT_AUX_LINE = 2097152u, // 0x200000
    AUDIO_DEVICE_OUT_SPEAKER_SAFE = 4194304u, // 0x400000
    AUDIO_DEVICE_OUT_IP = 8388608u, // 0x800000
    AUDIO_DEVICE_OUT_BUS = 16777216u, // 0x1000000
    AUDIO_DEVICE_OUT_PROXY = 33554432u, // 0x2000000
    AUDIO_DEVICE_OUT_USB_HEADSET = 67108864u, // 0x4000000
    AUDIO_DEVICE_OUT_FM_HEADSET = 268435456u, //0x10000000,
    AUDIO_DEVICE_OUT_FM_SPEAKER = 536870912u, //0x20000000,
    AUDIO_DEVICE_OUT_DEFAULT = 1073741824u, // BIT_DEFAULT
    AUDIO_DEVICE_OUT_ALL = 2013265919u, // (((((((((((((((((((((((((((OUT_EARPIECE | OUT_SPEAKER) | OUT_WIRED_HEADSET) | OUT_WIRED_HEADPHONE) | OUT_BLUETOOTH_SCO) | OUT_BLUETOOTH_SCO_HEADSET) | OUT_BLUETOOTH_SCO_CARKIT) | OUT_BLUETOOTH_A2DP) | OUT_BLUETOOTH_A2DP_HEADPHONES) | OUT_BLUETOOTH_A2DP_SPEAKER) | OUT_HDMI) | OUT_ANLG_DOCK_HEADSET) | OUT_DGTL_DOCK_HEADSET) | OUT_USB_ACCESSORY) | OUT_USB_DEVICE) | OUT_REMOTE_SUBMIX) | OUT_TELEPHONY_TX) | OUT_LINE) | OUT_HDMI_ARC) | OUT_SPDIF) | OUT_FM) | OUT_AUX_LINE) | OUT_SPEAKER_SAFE) | OUT_IP) | OUT_BUS) | OUT_PROXY) | OUT_USB_HEADSET) | OUT_DEFAULT | OUT_FM_HEADSET | OUT_FM_SPEAKER)
    AUDIO_DEVICE_OUT_ALL_A2DP = 896u, // ((OUT_BLUETOOTH_A2DP | OUT_BLUETOOTH_A2DP_HEADPHONES) | OUT_BLUETOOTH_A2DP_SPEAKER)
    AUDIO_DEVICE_OUT_ALL_SCO = 112u, // ((OUT_BLUETOOTH_SCO | OUT_BLUETOOTH_SCO_HEADSET) | OUT_BLUETOOTH_SCO_CARKIT)
    AUDIO_DEVICE_OUT_ALL_USB = 67133440u, // ((OUT_USB_ACCESSORY | OUT_USB_DEVICE) | OUT_USB_HEADSET)
    AUDIO_DEVICE_OUT_ALL_FM = 805306368u, // (OUT_FM_HEADSET | OUT_FM_SPEAKER)
    AUDIO_DEVICE_IN_COMMUNICATION = 2147483649u, // (BIT_IN | 0x1)
    AUDIO_DEVICE_IN_AMBIENT = 2147483650u, // (BIT_IN | 0x2)
    AUDIO_DEVICE_IN_BUILTIN_MIC = 2147483652u, // (BIT_IN | 0x4)
    AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET = 2147483656u, // (BIT_IN | 0x8)
    AUDIO_DEVICE_IN_WIRED_HEADSET = 2147483664u, // (BIT_IN | 0x10)
    AUDIO_DEVICE_IN_AUX_DIGITAL = 2147483680u, // (BIT_IN | 0x20)
    AUDIO_DEVICE_IN_HDMI = 2147483680u, // IN_AUX_DIGITAL
    AUDIO_DEVICE_IN_VOICE_CALL = 2147483712u, // (BIT_IN | 0x40)
    AUDIO_DEVICE_IN_TELEPHONY_RX = 2147483712u, // IN_VOICE_CALL
    AUDIO_DEVICE_IN_BACK_MIC = 2147483776u, // (BIT_IN | 0x80)
    AUDIO_DEVICE_IN_REMOTE_SUBMIX = 2147483904u, // (BIT_IN | 0x100)
    AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET = 2147484160u, // (BIT_IN | 0x200)
    AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET = 2147484672u, // (BIT_IN | 0x400)
    AUDIO_DEVICE_IN_USB_ACCESSORY = 2147485696u, // (BIT_IN | 0x800)
    AUDIO_DEVICE_IN_USB_DEVICE = 2147487744u, // (BIT_IN | 0x1000)
    AUDIO_DEVICE_IN_FM_TUNER = 2147491840u, // (BIT_IN | 0x2000)
    AUDIO_DEVICE_IN_TV_TUNER = 2147500032u, // (BIT_IN | 0x4000)
    AUDIO_DEVICE_IN_LINE = 2147516416u, // (BIT_IN | 0x8000)
    AUDIO_DEVICE_IN_SPDIF = 2147549184u, // (BIT_IN | 0x10000)
    AUDIO_DEVICE_IN_BLUETOOTH_A2DP = 2147614720u, // (BIT_IN | 0x20000)
    AUDIO_DEVICE_IN_LOOPBACK = 2147745792u, // (BIT_IN | 0x40000)
    AUDIO_DEVICE_IN_IP = 2148007936u, // (BIT_IN | 0x80000)
    AUDIO_DEVICE_IN_BUS = 2148532224u, // (BIT_IN | 0x100000)
    AUDIO_DEVICE_IN_PROXY = 2164260864u, // (BIT_IN | 0x1000000)
    AUDIO_DEVICE_IN_USB_HEADSET = 2181038080u, // (BIT_IN | 0x2000000)
    AUDIO_DEVICE_IN_DEFAULT = 3221225472u, // (BIT_IN | BIT_DEFAULT)
    AUDIO_DEVICE_IN_ALL = 3273654271u, // (((((((((((((((((((((((IN_COMMUNICATION | IN_AMBIENT) | IN_BUILTIN_MIC) | IN_BLUETOOTH_SCO_HEADSET) | IN_WIRED_HEADSET) | IN_HDMI) | IN_TELEPHONY_RX) | IN_BACK_MIC) | IN_REMOTE_SUBMIX) | IN_ANLG_DOCK_HEADSET) | IN_DGTL_DOCK_HEADSET) | IN_USB_ACCESSORY) | IN_USB_DEVICE) | IN_FM_TUNER) | IN_TV_TUNER) | IN_LINE) | IN_SPDIF) | IN_BLUETOOTH_A2DP) | IN_LOOPBACK) | IN_IP) | IN_BUS) | IN_PROXY) | IN_USB_HEADSET) | IN_DEFAULT)
    AUDIO_DEVICE_IN_ALL_SCO = 2147483656u, // IN_BLUETOOTH_SCO_HEADSET
    AUDIO_DEVICE_IN_ALL_USB = 2181044224u, // ((IN_USB_ACCESSORY | IN_USB_DEVICE) | IN_USB_HEADSET)
};

这里有很多真实存在的物理设备也有很多虚拟设备,重点关注的输出设备有:

AUDIO_DEVICE_OUT_EARPIECE 听筒,在手机的正上方。

AUDIO_DEVICE_OUT_SPEAKER 外放,也可以翻译成喇叭,播放媒体声音用得。

AUDIO_DEVICE_OUT_WIRED_HEADSET 带麦克风的有线耳机。

AUDIO_DEVICE_OUT_WIRED_HEADPHONE 和上面区别,不带麦克风的耳机。

AUDIO_DEVICE_OUT_BLUETOOTH_SCO 蓝牙集成,通常只蓝牙设备。

重点关注的输入设备有:

AUDIO_DEVICE_IN_BUILTIN_MIC 内置麦克风设备,用于录音。

AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET 蓝牙耳机集成。

AUDIO_DEVICE_IN_WIRED_HEADSET 有线耳机输入设备。

AUDIO_DEVICE_IN_BACK_MIC 后置麦克风,也可以称作副麦克风。

  这么多设备当然需要专用的音频管理,这块包含很多的内容。因为Android不仅仅是用在手机上,像类似的对讲机,智能手表,车载设备很多的物体形态很现在的手机有不同,所以有时候需要定制。下面开始实际分析源码,有时候可以加Log进行调试,通过Log更好地验证源码说明的正确性。源码分析是个比较枯燥的过程,因为不像写App那样可以实际看到效果,很多抽象的东西需要去不断地揣摩才能理解。

Engine.cpp和Engine.h文件是管理设备切换的,所以重点看着两个文件。不希望贴太多的代码,又没法不贴代码,所以有不懂地方还请查阅相关源码。

/frameworks/av/services/audiopolicy/enginedefault/src/Engine.h

class Engine
{
private:
    class ManagerInterfaceImpl : public AudioPolicyManagerInterface
    {
    public:
        explicit ManagerInterfaceImpl(Engine *policyEngine)
            : mPolicyEngine(policyEngine) {}
        virtual audio_device_t getDeviceForStrategy(routing_strategy strategy) const
        {
            return mPolicyEngine->getDeviceForStrategy(strategy);
        }
        ...
    private:
        Engine *mPolicyEngine;
    } mManagerInterface;
private:
    audio_device_t getDeviceForStrategy(routing_strategy strategy) const;
    ...
    audio_mode_t mPhoneState;   /** current phone stat. */
    /** current forced use configuration. */
    audio_policy_forced_cfg_t mForceUse[AUDIO_POLICY_FORCE_USE_CNT];
    AudioPlicyManagerObserver *mApmObserver;
}

这是简化版的Engine的定义,需要弄清楚Engine, ManagerInterfaceImpl, AudioPolicyManagerInterface三个类之间的关系。

/frameworks/av/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h

#pragma once

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

namespace android {

/**
 * This interface is dedicated to the policy manager that a Policy Engine shall implement.
 */
class AudioPolicyManagerInterface
{
public:
    /**
     * Checks if the engine was correctly initialized.
     *
     * @return NO_ERROR if initialization has been done correctly, error code otherwise..
     */
    virtual status_t initCheck() = 0;

    /**
     * Sets the Manager observer that allows the engine to retrieve information on collection
     * of devices, streams, HwModules, ...
     *
     * @param[in] observer handle on the manager.
     */
    virtual void setObserver(AudioPolicyManagerObserver *observer) = 0;

    /**
     * Get the input device selected for a given input source.
     *
     * @param[in] inputSource to get the selected input device associated to
     *
     * @return selected input device for the given input source, may be none if error.
     */
    virtual audio_devices_t getDeviceForInputSource(audio_source_t inputSource) const = 0;

    /**
     * Get the output device associated to a given strategy.
     *
     * @param[in] stream type for which the selected ouput device is requested.
     *
     * @return selected ouput device for the given strategy, may be none if error.
     */
    virtual audio_devices_t getDeviceForStrategy(routing_strategy stategy) const = 0;

    /**
     * Get the strategy selected for a given stream type.
     *
     * @param[in] stream: for which the selected strategy followed by is requested.
     *
     * @return strategy to be followed.
     */
    virtual routing_strategy getStrategyForStream(audio_stream_type_t stream) = 0;

    /**
     * Get the strategy selected for a given usage.
     *
     * @param[in] usage to get the selected strategy followed by.
     *
     * @return strategy to be followed.
     */
    virtual routing_strategy getStrategyForUsage(audio_usage_t usage) = 0;

    /**
     * Set the Telephony Mode.
     *
     * @param[in] mode: Android Phone state (normal, ringtone, csv, in communication)
     *
     * @return NO_ERROR if Telephony Mode set correctly, error code otherwise.
     */
    virtual status_t setPhoneState(audio_mode_t mode) = 0;

    /**
     * Get the telephony Mode
     *
     * @return the current telephony mode
     */
    virtual audio_mode_t getPhoneState() const = 0;

    /**
     * Set Force Use config for a given usage.
     *
     * @param[in] usage for which a configuration shall be forced.
     * @param[in] config wished to be forced for the given usage.
     *
     * @return NO_ERROR if the Force Use config was set correctly, error code otherwise (e.g. config
     * not allowed a given usage...)
     */
    virtual status_t setForceUse(audio_policy_force_use_t usage,
                                 audio_policy_forced_cfg_t config) = 0;

    /**
     * Get Force Use config for a given usage.
     *
     * @param[in] usage for which a configuration shall be forced.
     *
     * @return config wished to be forced for the given usage.
     */
    virtual audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage) const = 0;

    /**
     * Set the connection state of device(s).
     *
     * @param[in] devDesc for which the state has changed.
     * @param[in] state of availability of this(these) device(s).
     *
     * @return NO_ERROR if devices criterion updated correctly, error code otherwise.
     */
    virtual status_t setDeviceConnectionState(const android::sp devDesc,
                                              audio_policy_dev_state_t state) = 0;

protected:
    virtual ~AudioPolicyManagerInterface() {}
};

}; // namespace android

  这个类的每个函数都很重要,后面会重点结合实现讲几个重要的方法,这里可以直接通过英语注释就能获取到它们的作用,Android代码还是写得挺不错的。ManagerInterfaceImpl继承AudioPolicyManagerInterface类,相当于Java中的接口,同时也在Engine类里面申明ManagerInterfaceImpl变量。

  Engine类里面有个public泛型方法

    template 
    RequestedInterface *queryInterface();
这个方法就是查询接口,返回接口的指针,实现在Engine.cpp文件中。

/frameworks/av/services/audiopolicy/enginedefault/src/Engine.cpp

template <>
AudioPolicyManagerInterface *Engine::queryInterface()
{
    return &mManagerInterface;
}
可以看到直接返回的是在Engine类定义的变量的地址。具体这个变量的作用,从函数的意思来看就是获取接口,如果后面碰到需要用到的时候再来讲解。理解这种写法需要C++基础知识,比如内部类,泛型,向上转换,纯虚函数等。另外类似下面的

    /* Copy facilities are put private to disable copy. */
    Engine(const Engine &object);
    Engine &operator=(const Engine &object);
为什么申明为private类型就可以禁止拷贝和赋值,这也是需要C++知识,只要理解C++才能理解这样的写法,后面不再赘述类似的问题,因为很多类都需要赋值运算符重载和拷贝构造函数。

Engine类的第二个变量

audio_mode_t mPhoneState;
audio_mode_t也是枚举类型

typedef enum {
    AUDIO_MODE_INVALID = -2, // (-2)
    AUDIO_MODE_CURRENT = -1, // (-1)
    AUDIO_MODE_NORMAL = 0,
    AUDIO_MODE_RINGTONE = 1,
    AUDIO_MODE_IN_CALL = 2,
    AUDIO_MODE_IN_COMMUNICATION = 3,
    AUDIO_MODE_CNT = 4,
    AUDIO_MODE_MAX = 3, // (CNT - 1)
} audio_mode_t;
这些变量表示电话的状态,AUDIO_MODE_IN_CALL表示电话正在接通中,AUDIO_MODE_IN_COMMUNICATION应该表示类似微信语音的通话,AUDIO_MODE_NOMAL表示没有电话接通。因为手机一个非常重要的功能就是接打电话,而且优先级非常高,所以有必要专门设置变量来记录它们的状态,然后根据相应的状态进行设备选择。

有两个函数

    status_t setPhoneState(audio_mode_t mode);
    audio_mode_t getPhoneState() const
    {
        return mPhoneState;
    }

通常Java里面也是这样的写法,get和set配套使用,头文件中已经定义好getPhoneState函数,这后面的const防止这个函数修改类的变量,如果有修改的话会编译错误。

Engine类的第三个变量

audio_policy_forced_cfg_t mForceUse[AUDIO_POLICY_FORCE_USE_CNT];
这个变量很有作用,通常这个变量是会在上层提供相关的强制切换设备接口。比如接通电话声音都是从听筒出来的,电话接通之后如果用户想要切换到外放,只要点击手机界面上提供的按钮就可以。还有类似的小厂商要求插入耳机播放音乐的时候声音可以切换到外放播放,底层的实现形式也是这个函数,具体的上层的接口会在后面的章节中提到。
audio_policy_force_cfg_t可以看到在下面文件中定义成为枚举类型

/system/media/audio/include/system/audio_policy.h

/* device categories used for audio_policy->set_force_use()
 * These must match the values in AudioSystem.java
 */
typedef enum {
    AUDIO_POLICY_FORCE_NONE,
    AUDIO_POLICY_FORCE_SPEAKER,
    AUDIO_POLICY_FORCE_HEADPHONES,
    AUDIO_POLICY_FORCE_BT_SCO,
    AUDIO_POLICY_FORCE_BT_A2DP,
    AUDIO_POLICY_FORCE_WIRED_ACCESSORY,
    AUDIO_POLICY_FORCE_BT_CAR_DOCK,
    AUDIO_POLICY_FORCE_BT_DESK_DOCK,
    AUDIO_POLICY_FORCE_ANALOG_DOCK,
    AUDIO_POLICY_FORCE_DIGITAL_DOCK,
    AUDIO_POLICY_FORCE_NO_BT_A2DP, /* A2DP sink is not preferred to speaker or wired HS */
    AUDIO_POLICY_FORCE_SYSTEM_ENFORCED,
    AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED,
    AUDIO_POLICY_FORCE_ENCODED_SURROUND_NEVER,
    AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS,

    AUDIO_POLICY_FORCE_CFG_CNT,
    AUDIO_POLICY_FORCE_CFG_MAX = AUDIO_POLICY_FORCE_CFG_CNT - 1,

    AUDIO_POLICY_FORCE_DEFAULT = AUDIO_POLICY_FORCE_NONE,
} audio_policy_forced_cfg_t;

/* usages used for audio_policy->set_force_use()
 * These must match the values in AudioSystem.java
 */
typedef enum {
    AUDIO_POLICY_FORCE_FOR_COMMUNICATION,
    AUDIO_POLICY_FORCE_FOR_MEDIA,
    AUDIO_POLICY_FORCE_FOR_RECORD,
    AUDIO_POLICY_FORCE_FOR_DOCK,
    AUDIO_POLICY_FORCE_FOR_SYSTEM,
    AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO,
    AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND,

    AUDIO_POLICY_FORCE_USE_CNT,
    AUDIO_POLICY_FORCE_USE_MAX = AUDIO_POLICY_FORCE_USE_CNT - 1,
} audio_policy_force_use_t;
这里的Usage和Device不是一一对应的,为什么要切换设备需要定义一个Usage呢?这样可以应对更多不同的场景,同样这个变量也有set和get函数与之相对应,数组的下表表示Usage,数组的值表示强制切换的设备。

    audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage) const
    {
        return mForceUse[usage];
    }
详细来看下面这个函数的实现

status_t Engine::setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config)
{
    switch(usage) {
    case AUDIO_POLICY_FORCE_FOR_COMMUNICATION:
        if (config != AUDIO_POLICY_FORCE_SPEAKER && config != AUDIO_POLICY_FORCE_BT_SCO &&
            config != AUDIO_POLICY_FORCE_NONE) {
            ALOGW("setForceUse() invalid config %d for FOR_COMMUNICATION", config);
            return BAD_VALUE;
        }
        mForceUse[usage] = config;
        break;
    case AUDIO_POLICY_FORCE_FOR_MEDIA:
        if (config != AUDIO_POLICY_FORCE_HEADPHONES && config != AUDIO_POLICY_FORCE_BT_A2DP &&
            config != AUDIO_POLICY_FORCE_WIRED_ACCESSORY &&
            config != AUDIO_POLICY_FORCE_ANALOG_DOCK &&
            config != AUDIO_POLICY_FORCE_DIGITAL_DOCK && config != AUDIO_POLICY_FORCE_NONE &&
            config != AUDIO_POLICY_FORCE_NO_BT_A2DP && config != AUDIO_POLICY_FORCE_SPEAKER ) {
            ALOGW("setForceUse() invalid config %d for FOR_MEDIA", config);
            return BAD_VALUE;
        }
        mForceUse[usage] = config;
        break;
    case AUDIO_POLICY_FORCE_FOR_RECORD:
        if (config != AUDIO_POLICY_FORCE_BT_SCO && config != AUDIO_POLICY_FORCE_WIRED_ACCESSORY &&
            config != AUDIO_POLICY_FORCE_NONE) {
            ALOGW("setForceUse() invalid config %d for FOR_RECORD", config);
            return BAD_VALUE;
        }
        mForceUse[usage] = config;
        break;
    case AUDIO_POLICY_FORCE_FOR_DOCK:
        if (config != AUDIO_POLICY_FORCE_NONE && config != AUDIO_POLICY_FORCE_BT_CAR_DOCK &&
            config != AUDIO_POLICY_FORCE_BT_DESK_DOCK &&
            config != AUDIO_POLICY_FORCE_WIRED_ACCESSORY &&
            config != AUDIO_POLICY_FORCE_ANALOG_DOCK &&
            config != AUDIO_POLICY_FORCE_DIGITAL_DOCK) {
            ALOGW("setForceUse() invalid config %d for FOR_DOCK", config);
        }
        mForceUse[usage] = config;
        break;
    case AUDIO_POLICY_FORCE_FOR_SYSTEM:
        if (config != AUDIO_POLICY_FORCE_NONE &&
            config != AUDIO_POLICY_FORCE_SYSTEM_ENFORCED) {
            ALOGW("setForceUse() invalid config %d for FOR_SYSTEM", config);
        }
        mForceUse[usage] = config;
        break;
    case AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO:
        if (config != AUDIO_POLICY_FORCE_NONE &&
            config != AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED) {
            ALOGW("setForceUse() invalid config %d for HDMI_SYSTEM_AUDIO", config);
        }
        mForceUse[usage] = config;
        break;
    case AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND:
        if (config != AUDIO_POLICY_FORCE_NONE &&
                config != AUDIO_POLICY_FORCE_ENCODED_SURROUND_NEVER &&
                config != AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS) {
            ALOGW("setForceUse() invalid config %d for ENCODED_SURROUND", config);
            return BAD_VALUE;
        }
        mForceUse[usage] = config;
        break;
    default:
        ALOGW("setForceUse() invalid usage %d", usage);
        break; // TODO return BAD_VALUE?
    }
    return NO_ERROR;
}

可以看到这个函数的实现并不复杂,switch中的case就是上面定义的audio_policy_force_use_t的值,这里并不需要弄清楚每个值的含义,常见的比如AUDIO_POLICY_FORCE_FOR_MEDIA,如果进入这个case,就会对config参数进行判断,如果与那些强制设备一个也不相等就会返回错误值,如果符合其中的一个就会对数组进行赋值。

Engine类的最后一个变量

AudioPolicyManagerObserver *mApmObserver;
这个类比较抽象,现在可以不用涉及到它,下面是它的解释

/**
 * This interface is an observer that the manager shall implement to allows e.g. the engine
 * to access to policy pillars elements (like output / input descritors collections,
 * HwModule collections, AudioMix, ...
 */
下面通过Engine这个函数简单地复习C++类的基本写法。

构造器和解析器

    Engine();
    virtual ~Engine();
它们的实现,mManagerInterface传递this指针进行初始化还是比较晦涩的,为什么传递this指针我也不清楚,其它的初始化很容易明白,通过遍历数组初始化为AUDIO_POLICY_FORCE_NONE。

Engine::Engine()
    : mManagerInterface(this),
      mPhoneState(AUDIO_MODE_NORMAL),
      mApmObserver(NULL)
{
    for (int i = 0; i < AUDIO_POLICY_FORCE_USE_CNT; i++) {
        mForceUse[i] = AUDIO_POLICY_FORCE_NONE;
    }
}
函数的写法

void Engine::setObserver(AudioPolicyManagerObserver *observer)
{
    ALOG_ASSERT(observer != NULL, "Invalid Audio Policy Manager observer");
    mApmObserver = observer;
}

status_t Engine::initCheck()
{
    return (mApmObserver != NULL) ?  NO_ERROR : NO_INIT;
}
整体上看来比较清晰,第一个函数设置AudioPolicyManagerObserver,第二个函数初始化检查,如果不为空,就返回正确值,如果为空就会返回没有初始化。

inline函数

    inline bool isInCall() const
    {
        return is_state_in_call(mPhoneState);
    }
检查是否是电话电话状态,下面是is_state_in_call实现

/**
 * Check if the state given correspond to an in call state.
 * @TODO find a better name for widely call state
 *
 * @param[in] state to consider
 *
 * @return true if given state represents a device in a telephony or VoIP call
 */
static inline bool is_state_in_call(int state)
{
    return (state == AUDIO_MODE_IN_CALL) || (state == AUDIO_MODE_IN_COMMUNICATION);
}
总结:

  这里主要介绍三个Engine.cpp, Engine.h, AudioPolicyManagerInterface.h文件,可以从这些文件中看到Android C++的基本写法,和常规的类的写法是差不多的。

下篇:

  接下来的文章要介绍剩下的没有介绍的几个非常重要的函数。

    routing_strategy getStrategyForStream(audio_stream_type_t stream);
    routing_strategy getStrategyForUsage(audio_usage_t usage);
    audio_devices_t getDeviceForStrategy(routing_strategy strategy) const;
    audio_devices_t getDeviceForStrategyInt(routing_strategy strategy,
                                            DeviceVector availableOutputDevices,
                                            DeviceVector availableInputDevices,
                                         const SwAudioOutputCollection &outputs) const;
    audio_devices_t getDeviceForInputSource(audio_source_t inputSource) const;

还有一个非常重要的函数,在Engine中没有实现,而是在AudioPolicyManager类中实现的。

        virtual status_t setDeviceConnectionState(const sp /*devDesc*/,
                                                  audio_policy_dev_state_t /*state*/)
        {
            return NO_ERROR;
        }




你可能感兴趣的:(Android源码)