https://blog.csdn.net/zjli321/article/details/52424401
展开
如下图为android音频hal层所处的位置:

从上图可以看出,HAL层下面使用TiniAlsa(Android下一个简约的Alsa版本)。

HAL层分为两部分:

一部分为各种音频设备,每种音频设备由一个独立的库文件实现:如audio.a2dp.default.so(管理蓝牙a2dp音频),audio.usb.default.so(管理usb外接的音频),audio.primary.default.so(管理设备上的大部分音频)。

另一部分为厂家自己实现的音频策略,Android下提供了默认一套音频策略,当厂家有特殊的音频策略时,可以在这部分修改实现。

HAL层上面就是音频系统的核心AudioFlinger,这里实现了各种输入、输出音频流的管理,管理实时可用的音频通道,为各种音频流选择音频通道,实现多个音频流的混音等。

AudioFlinger在加载音频设备库文件时,从/system/lib/hw/下查找以audio开头的库,同时根据audio_policy.conf中定义的音频设备名(如a2dp、usb、primary)作为库的第二部分名称对于没有特别指定的,库的第三部分名称就是default,所以加载音频设备库的名称就可以确定了,如:audio.a2dp.default.so。每个音频库的实现接口都是一样的,这样就可以让AudioFlinger使用相同的接口调用不同音频设备。

android\external\bluetooth\bluedroid\audio_a2dp_hw\Audio_a2dp_hw.c
/* 音频open函数,用于确定音频输入输出流的实现接口,各种音频数据格式的设置获取接口 */
static int adev_open(const hw_module_t* module, const char* name,
                     hw_device_t** device)
{
    struct a2dp_audio_device *adev;
    int ret;

    INFO(" adev_open in A2dp_hw module");
    FNLOG();

    if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
    {
        ERROR("interface %s not matching [%s]", name, AUDIO_HARDWARE_INTERFACE);
        return -EINVAL;
    }

    adev = calloc(1, sizeof(struct a2dp_audio_device));

    if (!adev)
        return -ENOMEM;

    adev->device.common.tag = HARDWARE_DEVICE_TAG;
    adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
    adev->device.common.module = (struct hw_module_t *) module;
    adev->device.common.close = adev_close;

    adev->device.init_check = adev_init_check;
    adev->device.set_voice_volume = adev_set_voice_volume;
    adev->device.set_master_volume = adev_set_master_volume;
    adev->device.set_mode = adev_set_mode;
    adev->device.set_mic_mute = adev_set_mic_mute;
    adev->device.get_mic_mute = adev_get_mic_mute;
    adev->device.set_parameters = adev_set_parameters;
    adev->device.get_parameters = adev_get_parameters;
    adev->device.get_input_buffer_size = adev_get_input_buffer_size;
    adev->device.open_output_stream = adev_open_output_stream;
    adev->device.close_output_stream = adev_close_output_stream;
    adev->device.open_input_stream = adev_open_input_stream;
    adev->device.close_input_stream = adev_close_input_stream;
    adev->device.dump = adev_dump;

    adev->output = NULL;


    *device = &adev->device.common;

    return 0;
}

/* 音频模块open接口函数 */
static struct hw_module_methods_t hal_module_methods = {
    .open = adev_open,
};

/* 定义的音频模块 */
struct audio_module HAL_MODULE_INFO_SYM = {
    .common = {
        .tag = HARDWARE_MODULE_TAG,
        .version_major = 1,
        .version_minor = 0,
        .id = AUDIO_HARDWARE_MODULE_ID,
        .name = "A2DP Audio HW HAL",
        .author = "The Android Open Source Project",
        .methods = &hal_module_methods,
    },
};

在音频设备库的实现代码里,没有看到该音频设备库支持哪些音频输入、输出设备,音频设备支持的输入、输出设备不是在代码里面写死的,而是通过audio_policy.conf文件进行配置的。如下面的一份配置文件。
1
audio_hw_modules {
  primary {   /* 主音频配置文件 */
    global_configuration {
      attached_output_devices AUDIO_DEVICE_OUT_SPEAKER
      default_output_device AUDIO_DEVICE_OUT_SPEAKER
      attached_input_devices AUDIO_DEVICE_IN_BUILTIN_MIC
      audio_hal_version 3.0
    }
    devices {
      speaker {
        type AUDIO_DEVICE_OUT_SPEAKER
        gains {
          gain_1 {
            mode AUDIO_GAIN_MODE_JOINT
            min_value_mB -8400
            max_value_mB 4000
            default_value_mB 0
            step_value_mB 100
          }
        }
      }
    }
    outputs {
      primary {
        sampling_rates 48000
        channel_masks AUDIO_CHANNEL_OUT_STEREO
        formats AUDIO_FORMAT_PCM_16_BIT
        devices AUDIO_DEVICE_OUT_EARPIECE|AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|AUDIO_DEVICE_OUT_AUX_DIGITAL|AUDIO_DEVICE_OUT_ALL_SCO
        flags AUDIO_OUTPUT_FLAG_PRIMARY
      }
    }
    inputs {
      primary {
        sampling_rates 8000|16000
        channel_masks AUDIO_CHANNEL_IN_MONO
        formats AUDIO_FORMAT_PCM_16_BIT
        devices AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_ALL_SCO 
      }
    }
  }

  a2dp {   /* a2dp音频配置文件 */
    global_configuration {
      attached_output_devices AUDIO_DEVICE_OUT_BLUETOOTH_A2DP
      audio_hal_version 2.0
    }  
    outputs {
      a2dp {
        sampling_rates 44100
        channel_masks AUDIO_CHANNEL_OUT_STEREO
        formats AUDIO_FORMAT_PCM_16_BIT
        devices AUDIO_DEVICE_OUT_BLUETOOTH_A2DP|AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES|AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER
      }
    }
  }

  usb {   /* usb音频配置文件 */
    global_configuration {
      attached_output_devices AUDIO_DEVICE_OUT_USB_ACCESSORY
      audio_hal_version 2.0
    }  
    outputs {
      usb_accessory {
        sampling_rates 44100
        channel_masks AUDIO_CHANNEL_OUT_STEREO
        formats AUDIO_FORMAT_PCM_16_BIT
        devices AUDIO_DEVICE_OUT_USB_ACCESSORY
      }
      usb_device {
        sampling_rates 44100
        channel_masks AUDIO_CHANNEL_OUT_STEREO
        formats AUDIO_FORMAT_PCM_16_BIT
        devices AUDIO_DEVICE_OUT_USB_DEVICE
      }
    }
  }
}

可以看到对于a2dp来说,只支持音频输出,不支持音频输入,所以只有outputs device,没有inputs device,而对于主音频设备、就有inputs device。然后在device中就会配置该音频设备支持的输入、输出音频,如a2dp的输出音频就支持:AUDIO_DEVICE_OUT_BLUETOOTH_A2DP|AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES|AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER。支持的输入音频设备定义也类似,如主音频中inputs device中的定义。
Android下各种音频输入、输出设备定义如下:

android/system/core/include/system/audio.h

enum {
    AUDIO_DEVICE_NONE                          = 0x0,
    /* reserved bits */
    AUDIO_DEVICE_BIT_IN                        = 0x80000000,
    AUDIO_DEVICE_BIT_DEFAULT                   = 0x40000000,
    /* output devices */
    AUDIO_DEVICE_OUT_EARPIECE                  = 0x1,
    AUDIO_DEVICE_OUT_SPEAKER                   = 0x2,
    AUDIO_DEVICE_OUT_WIRED_HEADSET             = 0x4,
    AUDIO_DEVICE_OUT_WIRED_HEADPHONE           = 0x8,
    AUDIO_DEVICE_OUT_BLUETOOTH_SCO             = 0x10,
    AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET     = 0x20,
    AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT      = 0x40,
    AUDIO_DEVICE_OUT_BLUETOOTH_A2DP            = 0x80,
    AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100,
    AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER    = 0x200,
    AUDIO_DEVICE_OUT_AUX_DIGITAL               = 0x400,
    AUDIO_DEVICE_OUT_HDMI                      = AUDIO_DEVICE_OUT_AUX_DIGITAL,
    /* uses an analog connection (multiplexed over the USB connector pins for instance) */
    AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET         = 0x800,
    AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET         = 0x1000,
    /* USB accessory mode: your Android device is a USB device and the dock is a USB host */
    AUDIO_DEVICE_OUT_USB_ACCESSORY             = 0x2000,
    /* USB host mode: your Android device is a USB host and the dock is a USB device */
    AUDIO_DEVICE_OUT_USB_DEVICE                = 0x4000,
    AUDIO_DEVICE_OUT_REMOTE_SUBMIX             = 0x8000,
    /* Telephony voice TX path */
    AUDIO_DEVICE_OUT_TELEPHONY_TX              = 0x10000,
    /* Analog jack with line impedance detected */
    AUDIO_DEVICE_OUT_LINE                      = 0x20000,
    /* HDMI Audio Return Channel */
    AUDIO_DEVICE_OUT_HDMI_ARC                  = 0x40000,
    /* S/PDIF out */
    AUDIO_DEVICE_OUT_SPDIF                     = 0x80000,
    /* FM transmitter out */
    AUDIO_DEVICE_OUT_FM                        = 0x100000,
    /* Line out for av devices */
    AUDIO_DEVICE_OUT_AUX_LINE                  = 0x200000,
    /* limited-output speaker device for acoustic safety */
    AUDIO_DEVICE_OUT_SPEAKER_SAFE              = 0x400000,
    AUDIO_DEVICE_OUT_DEFAULT                   = AUDIO_DEVICE_BIT_DEFAULT,
    AUDIO_DEVICE_OUT_ALL      = (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_OUT_BLUETOOTH_SCO_HEADSET |
                                 AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT |
                                 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP |
                                 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
                                 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER |
                                 AUDIO_DEVICE_OUT_HDMI |
                                 AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET |
                                 AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET |
                                 AUDIO_DEVICE_OUT_USB_ACCESSORY |
                                 AUDIO_DEVICE_OUT_USB_DEVICE |
                                 AUDIO_DEVICE_OUT_REMOTE_SUBMIX |
                                 AUDIO_DEVICE_OUT_TELEPHONY_TX |
                                 AUDIO_DEVICE_OUT_LINE |
                                 AUDIO_DEVICE_OUT_HDMI_ARC |
                                 AUDIO_DEVICE_OUT_SPDIF |
                                 AUDIO_DEVICE_OUT_FM |
                                 AUDIO_DEVICE_OUT_AUX_LINE |
                                 AUDIO_DEVICE_OUT_SPEAKER_SAFE |
                                 AUDIO_DEVICE_OUT_DEFAULT),
    AUDIO_DEVICE_OUT_ALL_A2DP = (AUDIO_DEVICE_OUT_BLUETOOTH_A2DP |
                                 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
                                 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER),
    AUDIO_DEVICE_OUT_ALL_SCO  = (AUDIO_DEVICE_OUT_BLUETOOTH_SCO |
                                 AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
                                 AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT),
    AUDIO_DEVICE_OUT_ALL_USB  = (AUDIO_DEVICE_OUT_USB_ACCESSORY |
                                 AUDIO_DEVICE_OUT_USB_DEVICE),

    /* input devices */
    AUDIO_DEVICE_IN_COMMUNICATION         = AUDIO_DEVICE_BIT_IN | 0x1,
    AUDIO_DEVICE_IN_AMBIENT               = AUDIO_DEVICE_BIT_IN | 0x2,
    AUDIO_DEVICE_IN_BUILTIN_MIC           = AUDIO_DEVICE_BIT_IN | 0x4,
    AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET = AUDIO_DEVICE_BIT_IN | 0x8,
    AUDIO_DEVICE_IN_WIRED_HEADSET         = AUDIO_DEVICE_BIT_IN | 0x10,
    AUDIO_DEVICE_IN_AUX_DIGITAL           = AUDIO_DEVICE_BIT_IN | 0x20,
    AUDIO_DEVICE_IN_HDMI                  = AUDIO_DEVICE_IN_AUX_DIGITAL,
    /* Telephony voice RX path */
    AUDIO_DEVICE_IN_VOICE_CALL            = AUDIO_DEVICE_BIT_IN | 0x40,
    AUDIO_DEVICE_IN_TELEPHONY_RX          = AUDIO_DEVICE_IN_VOICE_CALL,
    AUDIO_DEVICE_IN_BACK_MIC              = AUDIO_DEVICE_BIT_IN | 0x80,
    AUDIO_DEVICE_IN_REMOTE_SUBMIX         = AUDIO_DEVICE_BIT_IN | 0x100,
    AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET     = AUDIO_DEVICE_BIT_IN | 0x200,
    AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET     = AUDIO_DEVICE_BIT_IN | 0x400,
    AUDIO_DEVICE_IN_USB_ACCESSORY         = AUDIO_DEVICE_BIT_IN | 0x800,
    AUDIO_DEVICE_IN_USB_DEVICE            = AUDIO_DEVICE_BIT_IN | 0x1000,
    /* FM tuner input */
    AUDIO_DEVICE_IN_FM_TUNER              = AUDIO_DEVICE_BIT_IN | 0x2000,
    /* TV tuner input */
    AUDIO_DEVICE_IN_TV_TUNER              = AUDIO_DEVICE_BIT_IN | 0x4000,
    /* Analog jack with line impedance detected */
    AUDIO_DEVICE_IN_LINE                  = AUDIO_DEVICE_BIT_IN | 0x8000,
    /* S/PDIF in */
    AUDIO_DEVICE_IN_SPDIF                 = AUDIO_DEVICE_BIT_IN | 0x10000,
    AUDIO_DEVICE_IN_BLUETOOTH_A2DP        = AUDIO_DEVICE_BIT_IN | 0x20000,
    AUDIO_DEVICE_IN_LOOPBACK              = AUDIO_DEVICE_BIT_IN | 0x40000,
    AUDIO_DEVICE_IN_DEFAULT               = AUDIO_DEVICE_BIT_IN | AUDIO_DEVICE_BIT_DEFAULT,

    AUDIO_DEVICE_IN_ALL     = (AUDIO_DEVICE_IN_COMMUNICATION |
                               AUDIO_DEVICE_IN_AMBIENT |
                               AUDIO_DEVICE_IN_BUILTIN_MIC |
                               AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET |
                               AUDIO_DEVICE_IN_WIRED_HEADSET |
                               AUDIO_DEVICE_IN_HDMI |
                               AUDIO_DEVICE_IN_TELEPHONY_RX |
                               AUDIO_DEVICE_IN_BACK_MIC |
                               AUDIO_DEVICE_IN_REMOTE_SUBMIX |
                               AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET |
                               AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET |
                               AUDIO_DEVICE_IN_USB_ACCESSORY |
                               AUDIO_DEVICE_IN_USB_DEVICE |
                               AUDIO_DEVICE_IN_FM_TUNER |
                               AUDIO_DEVICE_IN_TV_TUNER |
                               AUDIO_DEVICE_IN_LINE |
                               AUDIO_DEVICE_IN_SPDIF |
                               AUDIO_DEVICE_IN_BLUETOOTH_A2DP |
                               AUDIO_DEVICE_IN_LOOPBACK |
                               AUDIO_DEVICE_IN_DEFAULT),
    AUDIO_DEVICE_IN_ALL_SCO = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,
    AUDIO_DEVICE_IN_ALL_USB  = (AUDIO_DEVICE_IN_USB_ACCESSORY |
                                AUDIO_DEVICE_IN_USB_DEVICE),
};

这样,有了音频设备库及音频配置文件,就可以确定各个音频设备支持哪些输入、输出音频了。这样当上层需要输出一个声音时,就可以根据策略层选择的输出音频设备,选择该输出音频设备对应音频设备库接口。
现在再看一下主音频设备,在主音频设备支持音频输出中,既有AUDIO_DEVICE_OUT_SPEAKER(喇叭),又有AUDIO_DEVICE_OUT_WIRED_HEADSET  (有线耳机)AUDIO_DEVICE_OUT_ALL_SCO(蓝牙通话PCM),而在音频设备库中只有一个adev_open_output_stream接口,这时,就需要在adev_open_output_stream中根据实际的音频输出设备进行不同的操作了。
如下面一个例子代码:

static int adev_open_output_stream(struct audio_hw_device *dev,
                                   audio_io_handle_t handle,
                                   audio_devices_t devices,
                                   audio_output_flags_t flags,
                                   struct audio_config *config,
                                   struct audio_stream_out **stream_out,
                                   const char *address __unused)
{
    struct audio_device *adev = (struct audio_device *)dev;
    struct stream_out *out;
    int i, ret;

    ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
          __func__, config->sample_rate, config->channel_mask, devices, flags);
    *stream_out = NULL;
    out = (struct stream_out *)calloc(1, sizeof(struct stream_out));

    if (devices == AUDIO_DEVICE_NONE)
        devices = AUDIO_DEVICE_OUT_SPEAKER;

    out->flags = flags;
    out->devices = devices;
    out->dev = adev;
    out->format = config->format;
    out->sample_rate = config->sample_rate;
    out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
    out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
    out->handle = handle;

    /* Init use case and pcm_config */
if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
   /* AUDIO_DEVICE_OUT_SPEAKER(喇叭输出时处理)  */
       /*  省略代码 */
} else if (out->devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
/* AUDIO_DEVICE_OUT_WIRED_HEADSET (有线耳机输出时处理)  */
       /*  省略代码 */
} else  if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
   /* AUDIO_DEVICE_OUT_ALL_SCO (蓝牙PCM输出时处理)  */
       /*  省略代码 */
    } else {
       /*  省略代码 */
    }
————————————————
 

更多相关文章

  1. Android下的一个音乐播放工具类
  2. Android读写XML(下)——创建XML文档
  3. Android中使用log4j输出log内容到sd卡
  4. Android应用开发学习笔记之播放音频
  5. Android通过OpenSL ES播放音频套路详解
  6. 简单实现Android(安卓)AudioReccord录音方式
  7. Android读写XML(下)——创建XML文档
  8. Android(安卓)音频系统(二)之 AudioFlinger
  9. Android实现播放音频

随机推荐

  1. Android(安卓)Studio 编写jni 实例
  2. gradle之 (application 目录下 gradle 和
  3. Android(安卓)BroadcastReceiver详解
  4. 搭建android开发环境所需的工具,以及相应
  5. Android(安卓)ApiDemos示例解析(42):App->
  6. Android下自启动的实现
  7. unity开发android游戏(一)搭建Unity安卓开
  8. android 编程注意事项
  9. android 如何得到SD卡的目录
  10. Android(安卓)OTA升级新旧版本任意升级