Andriod 音频框架学习#1

1. 音频系统的启动

AudioFlinger和AudioPolicyService两大音频服务都是在android系统启动时就启动的。
当linux kenerl启动完成后,会启动android的init进程(system/core/init.c):

restorecon("/dev");
restorecon("/dev/socket");
restorecon("/dev/__properties__");
restorecon_recursive("/sys");

is_charger = !strcmp(bootmode, "charger");

INFO("property init\n");
property_load_boot_defaults();

INFO("reading config file\n");
init_parse_config_file("/init.rc");

init.rc文件(system/core/rootdir/init.rc)中保存了许多系统启动时需要启动的服务。其中就有多媒体服务mediaserver的启动:

service media /system/bin/mediaserver
    class main
    user media
    group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm
    ioprio rt 4

关于init.rc的进一步了解,参考如下几篇文章:
https://blog.csdn.net/andrewblog/article/details/17122303
https://blog.csdn.net/zhonglunshun/article/details/78615980

mediaserver在frameworks/av/media/mediaserver/main_mediaserver.cpp中定义:

sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
ALOGI("ServiceManager: %p", sm.get());
AudioFlinger::instantiate();
MediaPlayerService::instantiate();
CameraService::instantiate();
AudioPolicyService::instantiate();
SoundTriggerHwService::instantiate();
registerExtensions();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();

AudioFlinger和AudioPolicyService(frameworks/av/services/audioflinger/) 在此处被先后实例化,但是在AudioPolicyService.cpp和AudioFlinger.cpp中并未找到实例化函数instantiate,那么该函数必然位于两者的共同父类中:

class AudioFlinger :
    public BinderService<AudioFlinger>,
    public BnAudioFlinger
{
    friend class BinderService<AudioFlinger>;   // for AudioFlinger()
    ...
}
class AudioPolicyService :
    public BinderService<AudioPolicyService>, 
    public BnAudioPolicyService,
    public IBinder::DeathRecipient
{           
    friend class BinderService<AudioPolicyService>;
       ...
}

在frameworks/native/include/binder/BinderService.h中,我们找到了instantiate:

template<typename SERVICE>
class BinderService
{
public:
    static status_t publish(bool allowIsolated = false) {
        sp<IServiceManager> sm(defaultServiceManager());
        return sm->addService(
                String16(SERVICE::getServiceName()),
                new SERVICE(), allowIsolated);
    }

    static void publishAndJoinThreadPool(bool allowIsolated = false) {
        publish(allowIsolated);
        joinThreadPool();
    }

    static void instantiate() { publish(); }

    static status_t shutdown() { return NO_ERROR; }

private:
    static void joinThreadPool() {
        sp<ProcessState> ps(ProcessState::self());
        ps->startThreadPool();
        ps->giveThreadPoolName();
        IPCThreadState::self()->joinThreadPool();
    }
};

在publish函数中,SERVICE::getServiceName()调用了AudioFlinger类的静态成员函数getServiceName()获取AudioFlinger的服务名称,new SERVICE()则将AudioFlinger类实例化,addService向服务管理器注册AudioFlinger的实例。AudioFlinger服务启动后,其他进程可以通过ServiceManager来获取其代理对象IAudioFlinger通过IAudioFlinge可以向 AudioFlinger 发出各种服务请求,从而完成自己的音频业务。AudioPolicyService同理。

注意这里sm指向defaultServiceManager()返回的对象,defaultServiceManager()返回的是"IServiceManager对象",获取"IServiceManager对象"的目的是和"ServiceManager进程"进行通信,详细信息参考:https://blog.csdn.net/vichie2008/article/details/51889913

1.1 AudioFlinger的启动

接下来是AudioFlinger(frameworks/av/services/audioflinger/AudioFlinger.cpp)类的构造函数的初始化工作:

AudioFlinger::AudioFlinger()
    : BnAudioFlinger(),
      mPrimaryHardwareDev(NULL),
      mAudioHwDevs(NULL),
      mHardwareStatus(AUDIO_HW_IDLE),
      mMasterVolume(1.0f),
      mMasterMute(false),
      mNextUniqueId(1),
      mMode(AUDIO_MODE_INVALID),
      mBtNrecIsOff(false),
      mIsLowRamDevice(true),
      mIsDeviceTypeKnown(false),
      mGlobalEffectEnableTime(0),
      mPrimaryOutputSampleRate(0)
{
    getpid_cached = getpid();
    char value[PROPERTY_VALUE_MAX];
    bool doLog = (property_get("ro.test_harness", value, "0") > 0) && (atoi(value) == 1);
    if (doLog) {
        mLogMemoryDealer = new MemoryDealer(kLogMemorySize, "LogWriters", MemoryHeapBase::READ_ONLY);
    }

#ifdef TEE_SINK
    (void) property_get("ro.debuggable", value, "0");
    int debuggable = atoi(value);
    int teeEnabled = 0;
    if (debuggable) {
        (void) property_get("af.tee", value, "0");
        teeEnabled = atoi(value);
    }
    // FIXME symbolic constants here
    if (teeEnabled & 1) {
        mTeeSinkInputEnabled = true;
    }
    if (teeEnabled & 2) {
        mTeeSinkOutputEnabled = true;
    }
    if (teeEnabled & 4) {
        mTeeSinkTrackEnabled = true;
    }
#endif
}

接下来是调用AudioFlinger::onFirstRef():

void AudioFlinger::onFirstRef()
{
    int rc = 0;

    Mutex::Autolock _l(mLock);

    /* TODO: move all this work into an Init() function */
    char val_str[PROPERTY_VALUE_MAX] = { 0 };
    if (property_get("ro.audio.flinger_standbytime_ms", val_str, NULL) >= 0) {
        uint32_t int_val;
        if (1 == sscanf(val_str, "%u", &int_val)) {
            mStandbyTimeInNsecs = milliseconds(int_val);
            ALOGI("Using %u mSec as standby time.", int_val);
        } else {
            mStandbyTimeInNsecs = kDefaultStandbyTimeInNsecs;
            ALOGI("Using default %u mSec as standby time.",
                    (uint32_t)(mStandbyTimeInNsecs / 1000000));
        }
    }

    mPatchPanel = new PatchPanel(this);

    mMode = AUDIO_MODE_NORMAL;
}

属性ro.audio.flinger_standbytime_ms为用户调整standby时间提供了一个接口,早期版本中这个时间值是固定的。接下来创建PatchPanel,一个Audio Patch用来表示一个或多个source端到一个或多个sink端,相关介绍在: https://blog.csdn.net/yzhang8703/article/details/47660803

关于会调用到函数onFirstRef的原因,BnAudioFlinger是由RefBase层层继承而来的,并且IServiceManager::addService的第二个参数实际上是一个强指针引用(constsp&),此时会调用incStrong函数,该函数在第一次调用时会调用onFirstRef()。详细信息参考: https://www.cnblogs.com/zhaoshuai1215/p/3432963.html

1.2 AudioPolicyService的启动

接下来看AudioPolicyService(frameworks/av/services/audiopolicy/AudioPolicyService.cpp)类的初始化:

AudioPolicyService::AudioPolicyService()
    : BnAudioPolicyService(), mpAudioPolicyDev(NULL), mpAudioPolicy(NULL),
      mAudioPolicyManager(NULL), mAudioPolicyClient(NULL), mPhoneState(AUDIO_MODE_INVALID)
{
}

接着看AudioPolicyService::onFirstRef():

void AudioPolicyService::onFirstRef()
{
    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("ApmTone"), this);
        // start audio commands thread
        mAudioCommandThread = new AudioCommandThread(String8("ApmAudio"), this);
        // start output activity command thread
        mOutputCommandThread = new AudioCommandThread(String8("ApmOutput"), this);

#ifdef USE_LEGACY_AUDIO_POLICY
        ALOGI("AudioPolicyService CSTOR in legacy mode");

        /* 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);
#else
        ALOGI("AudioPolicyService CSTOR in new mode");

        mAudioPolicyClient = new AudioPolicyClient(this);
        mAudioPolicyManager = createAudioPolicyManager(mAudioPolicyClient);
#endif
    }
    // load audio processing modules
    sp<AudioPolicyEffects>audioPolicyEffects = new AudioPolicyEffects();
    {
        Mutex::Autolock _l(mLock);
        mAudioPolicyEffects = audioPolicyEffects;
    }
}                                   
1.2.1 创建AudioCommandThread线程

在AudioPolicyService对象构造过程中,分别创建了ApmTone、ApmAudio、ApmOutput三个AudioCommandThread线程:

1、 ApmTone用于播放tone音;

2、 ApmAudio用于执行audio命令;

3、ApmOutput用于执行输出命令;

在第一次强引用AudioCommandThread线程对象时,AudioCommandThread的onFirstRef函数被回调,于是启动线程:

void AudioPolicyService::AudioCommandThread::onFirstRef()
{
    run(mName.string(), ANDROID_PRIORITY_AUDIO);
}

这里采用异步方式来执行audio command,当需要执行上表中的命令时,首先将命令投递到AudioCommandThread的mAudioCommands命令向量表中,然后通过mWaitWorkCV.signal()唤醒AudioCommandThread线程,被唤醒的AudioCommandThread线程执行完command后,又通过mWaitWorkCV.waitRelative(mLock, waitTime)睡眠等待命令到来。

另外,三个AudioCommandThread执行的命令包括以下几个:

  enum {
            START_TONE,
            STOP_TONE,
            SET_VOLUME,
            SET_PARAMETERS,
            SET_VOICE_VOLUME,
            STOP_OUTPUT,
            RELEASE_OUTPUT,
            CREATE_AUDIO_PATCH,
            RELEASE_AUDIO_PATCH,
            UPDATE_AUDIOPORT_LIST,
            UPDATE_AUDIOPATCH_LIST,
            SET_AUDIOPORT_CONFIG,
        };
1.2.2 加载audio_policy_module模块

搜索“hardware.h”得到其位置在hardware/libhardware/include/hardware/hardware.h,进一步搜索“hardware.c/hardware.cpp”找到了hardware/libhardware/hardware.c。在hardware.c发现了hw_get_module函数:

int hw_get_module(const char *id, const struct hw_module_t **module)
{
    return hw_get_module_by_class(id, NULL, module);
}
int hw_get_module_by_class(const char *class_id, const char *inst,
                           const struct hw_module_t **module)
{
    int i;
    char prop[PATH_MAX];
    char path[PATH_MAX];
    char name[PATH_MAX];
    char prop_name[PATH_MAX];

    if (inst)
        snprintf(name, PATH_MAX, "%s.%s", class_id, inst);
    else
        strlcpy(name, class_id, PATH_MAX);

    /*
     * Here we rely on the fact that calling dlopen multiple times on
     * the same .so will simply increment a refcount (and not load
     * a new copy of the library).
     * We also assume that dlopen() is thread-safe.
     */

    /* First try a property specific to the class and possibly instance */
    snprintf(prop_name, sizeof(prop_name), "ro.hardware.%s", name);
    if (property_get(prop_name, prop, NULL) > 0) {
        if (hw_module_exists(path, sizeof(path), name, prop) == 0) {
            goto found;
        }
    }

    /* Loop through the configuration variants looking for a module */
    for (i=0 ; i<HAL_VARIANT_KEYS_COUNT; i++) {
        if (property_get(variant_keys[i], prop, NULL) == 0) {
            continue;
        }
        if (hw_module_exists(path, sizeof(path), name, prop) == 0) {
            goto found;
        }
    }

    /* Nothing found, try the default */
    if (hw_module_exists(path, sizeof(path), name, "default") == 0) {
        goto found;
    }

    return -ENOENT;

found:
    /* load the module, if this fails, we're doomed, and we should not try
     * to load a different variant. */
    return load(class_id, path, module);
}

接下来在/libhardware/include/hardware/audio_policy.h中找到了:

#define AUDIO_POLICY_HARDWARE_MODULE_ID "audio_policy"

因此,hw_get_module_by_class的第一个参数class_id = “audio_policy”

   if (inst)
        snprintf(name, PATH_MAX, "%s.%s", class_id, inst);
    else
        strlcpy(name, class_id, PATH_MAX);

此处inst == NULL; 所以name = “audio_policy”;

 snprintf(prop_name, sizeof(prop_name), "ro.hardware.%s", name);
    if (property_get(prop_name, prop, NULL) > 0) {
        if (hw_module_exists(path, sizeof(path), name, prop) == 0) {
            goto found;
        }
    }

判断“ro.hardware.audio_policy"是否存在,如果存在则加载,若不存在跳到下一步:

  /* Loop through the configuration variants looking for a module */
    for (i=0 ; i<HAL_VARIANT_KEYS_COUNT; i++) {
        if (property_get(variant_keys[i], prop, NULL) == 0) {
            continue;
        }
        if (hw_module_exists(path, sizeof(path), name, prop) == 0) {
            goto found;
        }
    }

在配置变量中查找,属性值(audio_policy.prop.so)是否存在,配置的变量如下:

static const char *variant_keys[] = {
    "ro.hardware",  /* This goes first so that it can pick up a different
                       file on the emulator. */
    "ro.product.board",
    "ro.board.platform",
    "ro.arch"
};

如果不存在,则将prop=default。查看audio_policy.defaule.so库是否存在:

/* Nothing found, try the default */
    if (hw_module_exists(path, sizeof(path), name, "default") == 0) {
        goto found;
    }

如果存在,则加载audio_policy.defaule.so。

/* load the module, if this fails, we're doomed, and we should not try
     * to load a different variant. */
    return load(class_id, path, module);

更详细的介绍参考:https://blog.csdn.net/u014135607/article/details/79840130
hw_get_module函数加载audio_policy.default.so库得到audio_policy_module模块。

1.2.3 打开audio_policy_device设备
rc = audio_policy_dev_open(module, &mpAudioPolicyDev);
        ALOGE_IF(rc, "couldn't open audio policy device (%s)", strerror(-rc));
if (rc) {
		return;
}

audio_policy_dev_open函数可以在/libhardware/include/hardware/audio_policy.h中找到:

/** convenience API for opening and closing a supported device */

static inline int audio_policy_dev_open(const hw_module_t* module,
                                    struct audio_policy_device** device)
{
    return module->methods->open(module, AUDIO_POLICY_INTERFACE,
                                 (hw_device_t**)device);
}

这里使用hw_module_t的方法打开设备,hw_module_t结构体的定义可以在(/hardware/libhardware/include/hardware/hardware.h)中找到:

typedef struct hw_module_t {
uint32_t tag;
uint16_t module_api_version;
/** Identifier of module */
 const char *id;

 /** Name of this module */
 const char *name;

 /** Author/owner/implementor of the module */
 const char *author;

 /** Modules methods */
 struct hw_module_methods_t* methods;

 /** module's dso */
 void* dso;
 } hw_module_t;

hw_module_methods_t的定义也在这里,我们找到了指向打开设备方法的指针:

typedef struct hw_module_methods_t {
    /** Open a specific device */
    int (*open)(const struct hw_module_t* module, const char* id,
            struct hw_device_t** device);

} hw_module_methods_t;

有两个文件实现了结构体hw_module_methods_t中open方法,分别是:/hardware/libhardware/modules/audio/audio_policy.c和/hardware/libhardware_legacy/audio/audio_policy_hal.cpp。

static struct hw_module_methods_t default_ap_module_methods = {
    .open = default_ap_dev_open,
};
static struct hw_module_methods_t legacy_ap_module_methods = {
        .open = legacy_ap_dev_open
};

考虑到宏定义#ifdef USE_LEGACY_AUDIO_POLICY,hw_module_methods_t的实现应该在audio_policy_hal.cpp中。

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;
}

在函数legacy_ap_dev_open中我们也找到了结构体hw_device_t(/hardware/libhardware/include/hardware/hardware.h)中close方法和结构体audio_policy_device(/libhardware/include/hardware/audio_policy.h )中create_audio_policy和destroy_audio_policy方法的实现:

 typedef struct hw_device_t {
	/** tag must be initialized to HARDWARE_DEVICE_TAG */
	 uint32_t tag;
	 uint32_t version;
	 /** reference to the module this device belongs to */
	 struct hw_module_t* module;
	 uint64_t reserved[12];
	 /** Close this device */
	 int (*close)(struct hw_device_t* device);
} hw_device_t;
struct audio_policy_device {
    /**
     * Common methods of the audio policy device.  This *must* be the first member of
     * audio_policy_device as users of this structure will cast a hw_device_t to
     * audio_policy_device pointer in contexts where it's known the hw_device_t references an
     * 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);
};

另外需要注意的是/libhardware/include/hardware/audio_policy.h文件的真实文件名应当是audio_policy_interface.h,需要和/system/core/include/system/audio_policy.h区分开来。该文件包含了一些从 /frameworks/base/include/media/AudioSystem.h转移过来的枚举值。

1.2.4创建audio_policy对象

首先来看/libhardware/include/hardware/audio_policy.h定义的三个结构体:
audio_policy, audio_policy_service_ops和audio_policy_device

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值