Android Audio 框架简读 <2>

接着上一篇AudioPolicyService代码,目录:

E:\liuzhibao\android\android\frameworks\av\services\audioflinger

直接看代码:主要看构造函数内:

// ----------------------------------------------------------------------------

AudioPolicyService::AudioPolicyService()
    : BnAudioPolicyService() , mpAudioPolicyDev(NULL) , mpAudioPolicy(NULL)
{
    char value[PROPERTY_VALUE_MAX];
    const struct hw_module_t *module;
    int forced_val;
    int rc;

    Mutex::Autolock _l(mLock);

    // start tone playback thread
    mTonePlaybackThread = new AudioCommandThread(String8(""));
    // start audio commands thread
    mAudioCommandThread = new AudioCommandThread(String8("ApmCommand"));

    /* instantiate the audio policy manager */
    rc = hw_get_module(AUDIO_POLICY_HARDWARE_MODULE_ID, &module);
    if (rc)
        return;

    rc = audio_policy_dev_open(module, &mpAudioPolicyDev);
    ALOGE_IF(rc, "couldn't open audio policy device (%s)", strerror(-rc));
    if (rc)
        return;

    rc = mpAudioPolicyDev->create_audio_policy(mpAudioPolicyDev, &aps_ops, this,
                                               &mpAudioPolicy);
    ALOGE_IF(rc, "couldn't create audio policy (%s)", strerror(-rc));
    if (rc)
        return;

    rc = mpAudioPolicy->init_check(mpAudioPolicy);
    ALOGE_IF(rc, "couldn't init_check the audio policy (%s)", strerror(-rc));
    if (rc)
        return;

    ALOGI("Loaded audio policy from %s (%s)", module->name, module->id);

    // load audio pre processing modules
    if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
        loadPreProcessorConfig(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
    } else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) {
        loadPreProcessorConfig(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
    }
}


其中:

// start tone playback thread
    mTonePlaybackThread = new AudioCommandThread(String8(""));
    // start audio commands thread
    mAudioCommandThread = new AudioCommandThread(String8("ApmCommand"));
这里面的AudioCommandThread : 所有的命令(音量控制,输入、输出的切换等)最终都会在该线程中排队执行.

下面有一个对应HAL的结构体:

const struct hw_module_t *module;

对应一共是三个:

struct hw_module_t;
struct hw_module_methods_t;
struct hw_device_t;

对应开发的需要调整,比如,如果是一个led灯的控制,可以改如下:

struct led_module_t;
struct led_module_methods_t;
struct led_device_t;

这几个结构体的定义是在hardware.h中,有兴趣的,也必须要要看这几个结构体的作用,因为library层全部要用,不看懂完全都不知道这三个家伙是干什么的,也可以查看网上面关于HAL开发文章,还是比较简单的,主要是它有一套规则,定义方式基本上是死的.如果自己需要改的话,可以调整:

struct *_module_t;
struct *_module_methods_t;
struct *_device_t;

*改成你的设备名称,如上面的led等控制,这样library库层就可以直接使用调用了,这个library库层的开发和linux的设备使用开发基本上是一样的,打开设备,控制设备,读写设备.具体可以详读:Android深度探索这本书.

继续看代码

rc = hw_get_module(AUDIO_POLICY_HARDWARE_MODULE_ID, &module);

打开设备:

rc = audio_policy_dev_open(module, &mpAudioPolicyDev);
    ALOGE_IF(rc, "couldn't open audio policy device (%s)", strerror(-rc));
    if (rc)
        return;

上面还好,最重要的一句话:

rc = mpAudioPolicyDev->create_audio_policy(mpAudioPolicyDev, &aps_ops, this,
                                               &mpAudioPolicy);

其中:

struct audio_policy_device *mpAudioPolicyDev;


audio_policy这是一个类似虚拟设备,它在linux并没有驱动节点,但是它又是类似一个linux驱动节点:程序可以查看Audio_policy.cpp,你会发现生成的audio_policy.default.so文件:

想上个图片,可以用adb 到/system/lib/hw下面看到有audio_policy.default.so这个东东了

typedef struct audio_policy_module {
    struct hw_module_t common;
} audio_policy_module_t;

struct audio_policy_device {
    struct hw_device_t common;

    int (*create_audio_policy)(const struct audio_policy_device *device,
                               struct audio_policy_service_ops *aps_ops,
                               void *service,
                               struct audio_policy **ap);

    int (*destroy_audio_policy)(const struct audio_policy_device *device,
                                struct audio_policy *ap);
};

看了上面的就知道了它也是个类似HAL访问驱动节点的,不过它是虚拟的.

那么上面那个create_audio_policy(...)就要查看HAL层的Audio_policy.c文件

static int legacy_ap_dev_open(const hw_module_t* module, const char* name,
                                    hw_device_t** device)
{
    struct legacy_ap_device *dev;

    if (strcmp(name, AUDIO_POLICY_INTERFACE) != 0)
        return -EINVAL;

    dev = (struct legacy_ap_device *)calloc(1, sizeof(*dev));
    if (!dev)
        return -ENOMEM;

    dev->device.common.tag = HARDWARE_DEVICE_TAG;
    dev->device.common.version = 0;
    dev->device.common.module = const_cast<hw_module_t*>(module);
    dev->device.common.close = legacy_ap_dev_close;
    dev->device.create_audio_policy = create_legacy_ap;
    dev->device.destroy_audio_policy = destroy_legacy_ap;

    *device = &dev->device.common;

    return 0;
}

上面的一看create_audio_policy实际上调用的是create_legacy_ap函数,感觉这个HAL不是去体验linux层的驱动节点,而是做了一下转手,那么该函数:

static int create_legacy_ap(const struct audio_policy_device *device,
                            struct audio_policy_service_ops *aps_ops,
                            void *service,
                            struct audio_policy **ap)

函数里面程序有点多,截取其中一段关心的:

lap->aps_ops = aps_ops;
    lap->service_client =
        new AudioPolicyCompatClient(aps_ops, service);
    if (!lap->service_client) {
        ret = -ENOMEM;
        goto err_new_compat_client;
    }

    lap->apm = createAudioPolicyManager(lap->service_client);
    if (!lap->apm) {
        ret = -ENOMEM;
        goto err_create_apm;
    }

    *ap = &lap->policy;


一看上面的AudioPolicyCompatClient,AudioPolicyManager创建,感觉绕了这么一大圈,从HAL层又有点绕上来了.

继续看AudioPolicyManager这个类,先看它的头文件AudioPolicyManager.h,原来它又是继承了AudioPolicyManagerBase这个类的:

class AudioPolicyManager: public AudioPolicyManagerBase

看一下它的构造函数,想所有的人都非常关注,上面既然是个虚拟设备,那总的调用实际设备吧,那么这里面就开始了:

mA2dpDeviceAddress = String8("");
    mScoDeviceAddress = String8("");
    mUsbCardAndDevice = String8("");

    if (loadAudioPolicyConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE) != NO_ERROR) {
        if (loadAudioPolicyConfig(AUDIO_POLICY_CONFIG_FILE) != NO_ERROR) {
            ALOGE("could not load audio policy configuration file, setting defaults");
            defaultAudioPolicyConfig();
        }
    }


其中上面那个AudioPolicyConfig配置参数:Audio_policy_conf.h文件中

#define AUDIO_POLICY_CONFIG_FILE "/system/etc/audio_policy.conf"
#define AUDIO_POLICY_VENDOR_CONFIG_FILE "/vendor/etc/audio_policy.conf"

这就是很多网友提到的audio设备配置.就是在这里面进行加载.conf文件大致内容:

# Global configuration section: lists input and output devices always present on the device
# as well as the output device selected by default.
# Devices are designated by a string that corresponds to the enum in audio.h

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 hardware module section: contains descriptors for all audio hw modules present on the
# device. Each hw module node is named after the corresponding hw module library base name.
# For instance, "primary" corresponds to audio.primary.<device>.so.
# The "primary" module is mandatory and must include at least one output with
# AUDIO_OUTPUT_FLAG_PRIMARY flag.
# Each module descriptor contains one or more output profile descriptors and zero or more
# input profile descriptors. Each profile lists all the parameters supported by a given output
# or input stream category.
# The "channel_masks", "formats", "devices" and "flags" are specified using strings corresponding
# to enums in audio.h and audio_policy.h. They are concatenated by use of "|" without space or "\n".

audio_hw_modules {
  primary {
    outputs {
      primary {
        sampling_rates 44100
        channel_masks AUDIO_CHANNEL_OUT_STEREO
        formats AUDIO_FORMAT_PCM_16_BIT
        devices AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET|AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|AUDIO_DEVICE_OUT_AUX_DIGITAL|AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET|AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET|AUDIO_DEVICE_OUT_ALL_SCO
        flags AUDIO_OUTPUT_FLAG_PRIMARY
      }
      hdmi {
        sampling_rates dynamic
        channel_masks dynamic
        formats AUDIO_FORMAT_PCM_16_BIT
        devices AUDIO_DEVICE_OUT_AUX_DIGITAL
        flags AUDIO_OUTPUT_FLAG_DIRECT
      }
      bt {
        sampling_rates 8000 
        channel_masks AUDIO_CHANNEL_OUT_MONO
        formats AUDIO_FORMAT_PCM_16_BIT
        devices AUDIO_DEVICE_OUT_ALL_SCO
        flags AUDIO_OUTPUT_FLAG_DIRECT
      }
      usb {
        sampling_rates 44100
        channel_masks AUDIO_CHANNEL_OUT_STEREO
        formats AUDIO_FORMAT_PCM_16_BIT
        devices AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET|AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET
        flags AUDIO_OUTPUT_FLAG_DIRECT
      }
    }
    inputs {
      primary {
        sampling_rates 8000|11025|16000|22050|24000|32000|44100|48000
        channel_masks AUDIO_CHANNEL_IN_MONO|AUDIO_CHANNEL_IN_STEREO
        formats AUDIO_FORMAT_PCM_16_BIT
        devices AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET|AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_WIRED_HEADSET|AUDIO_DEVICE_IN_USB_DEVICE|AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET|AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET
      }
    }
  }
  a2dp {
    outputs {
      a2dp {
        sampling_rates 44100
        channel_masks AUDIO_CHANNEL_OUT_STEREO
        formats AUDIO_FORMAT_PCM_16_BIT
        devices AUDIO_DEVICE_OUT_ALL_A2DP
      }
    }
  }
  r_submix {
    outputs {
      submix {
        sampling_rates 44100|48000
        channel_masks AUDIO_CHANNEL_OUT_STEREO
        formats AUDIO_FORMAT_PCM_16_BIT
        devices AUDIO_DEVICE_OUT_REMOTE_SUBMIX
      }
    }
    inputs {
      submix {
        sampling_rates 44100|48000
        channel_masks AUDIO_CHANNEL_IN_STEREO
        formats AUDIO_FORMAT_PCM_16_BIT
        devices AUDIO_DEVICE_IN_REMOTE_SUBMIX
      }
    }
  }
 usb {
    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
      }
    }
  }
}

回到前面的代码AudioPolicyManagerBase,下面就是加载所有的设备,并且打开它们各自的流:

// open all output streams needed to access attached devices
    for (size_t i = 0; i < mHwModules.size(); i++) {
        mHwModules[i]->mHandle = mpClientInterface->loadHwModule(mHwModules[i]->mName);
        if (mHwModules[i]->mHandle == 0) {
            ALOGW("could not open HW module %s", mHwModules[i]->mName);
            continue;
        }
        // open all output streams needed to access attached devices
        for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++)
        {
            const IOProfile *outProfile = mHwModules[i]->mOutputProfiles[j];

            if (outProfile->mSupportedDevices & mAttachedOutputDevices && !(outProfile->mFlags & AUDIO_OUTPUT_FLAG_DIRECT)) {
                AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor(outProfile);
                outputDesc->mDevice = (audio_devices_t)(mDefaultOutputDevice &
                                                            outProfile->mSupportedDevices);
                audio_io_handle_t output = mpClientInterface->openOutput(
                                                outProfile->mModule->mHandle,
                                                &outputDesc->mDevice,
                                                &outputDesc->mSamplingRate,
                                                &outputDesc->mFormat,
                                                &outputDesc->mChannelMask,
                                                &outputDesc->mLatency,
                                                outputDesc->mFlags);


打开所有的设备,并且等待对应的数据流进行处理,那么还需要提供一个策略方式,不可能一个数据过来了,所有的output设备都去播放,那speaker,receiver,蓝牙(如果连上)都会同时播放出声音,那不是很混乱.

这里提供了一个策略:算是默认的.

updateDevicesAndOutputs();


... ...

走完上面一路下来,重要需要注意的是上面那个虚拟设备的地方,绕了一个大弯,因为一般情况下,我们遇到下面结构体以后,都会认为要去linux的驱动设备节点了:

struct hw_module_t;
struct hw_module_methods_t;
struct hw_device_t;
但是上面很显然没有.

Binder呢??

这个在Android Audio起着非常重要的作用,但是没有太多好说的,因为Audio就是用binder的机制:主要的感觉是在数据memory的分配,释放,以及对象的"复制",这个复制不知道准不准确啊.下次看看.














你可能感兴趣的:(Android Audio 框架简读 <2>)