热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

深入解析AndroidAudio系统中的mpAudioPolicy->get_input

在分析Android的Audio系统时,我们对mpAudioPolicy->get_input进行了详细探讨,发现其背后涉及的机制相当复杂。本文将详细介绍这一过程及其背后的实现细节。

在分析Android的Audio系统时,我们对mpAudioPolicy->get_input进行了详细探讨,发现其背后涉及的机制相当复杂。本文将详细介绍这一过程及其背后的实现细节。

首先,调用mpAudioPolicy->get_input方法,该方法是在mpAudioPolicyDev->create_audio_policy(mpAudioPolicyDev, &aps_ops, this, &mpAudioPolicy)中赋值的。这里涉及到几个关键结构体:

  • struct audio_policy_device *mpAudioPolicyDev;
  • struct audio_policy *mpAudioPolicy;

mpAudioPolicyDev的赋值是在audio_policy_dev_open函数中完成的,该函数定义如下:

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

接下来需要找到module的来源。Android的AudioPolicy接口继承关系如下:

  • AudioPolicyInterface
  • AudioPolicyManagerBase
  • AudioPolicyManagerDefault

AudioPolicyManagerDefault编译成audio_policy.default.so,该库依赖于静态库libaudiopolicy_legacy.a,后者由AudioPolicyManagerBase.cppAudioPolicyCompatClient.cppaudio_policy_hal.cpp生成。

通过hw_get_module_by_class函数加载HAL模块,具体加载的模块包括audio_policy.stub.soaudio_policy.default.soaudio_policy.msm8960.so。模拟器中加载的是audio_policy.default.so

hw_get_module(AUDIO_POLICY_HARDWARE_MODULE_ID, &module)获取到的module类型为hw_module_t。接着调用module->methods->open(module, AUDIO_POLICY_INTERFACE, (hw_device_t**)device),将hw_device_t类型转换成audio_policy_device返回给mpAudioPolicyDev

audio_policy_hal.cpp中,module->methods->open将调用legacy_ap_dev_open函数。最终,mpAudioPolicyDev将成为legacy_ap_dev_open函数的最后一个参数hw_device_t** device

通过以下代码:

dev->device.create_audio_policy = create_legacy_ap;
*device = &dev->device.common;

知道mpAudioPolicy将成为create_legacy_ap的最后一个参数struct audio_policy **ap。再通过以下代码:

lap->policy.get_input = ap_get_input;
*ap = &lap->policy;

知道mpAudioPolicy->get_input(...)最终将调用ap_get_input函数。

ap_get_input函数的内容如下:

struct legacy_audio_policy *lap = to_lap(pol);
return lap->apm->getInput((int) inputSource, sampling_rate, (int) format, channelMask, (AudioSystem::audio_in_acoustics)acoustics);

其中,lap->apmcreate_legacy_ap中的以下语句创建:

lap->apm = createAudioPolicyManager(lap->service_client);

因此,apm实际上是new AudioPolicyManagerDefault(lap->service_client)对象,而lap->service_client = new AudioPolicyCompatClient(aps_ops, service)。这里的参数是本cpp中调用create_audio_policy(mpAudioPolicyDev, &aps_ops, this, &mpAudioPolicy)中传入的aps_opsthis参数。

最终,mpAudioPolicy->get_input将调用hardware/libhardware_legacy/audio/AudioPolicyManagerBase.cpp中的getInput函数。在AudioPolicyManagerBase中,会调用AudioPolicyCompatClientopenInput方法,根据audio_policy.conf文件的配置信息选择合适的音频设备,并确定audio_module_handle_t的值。

openInput中,通过本cpp传入的aps_ops回调本cpp中的aps_open_input_on_module,后者调用AudioFlingeropenInput方法。AudioFlingeropenInput会产生一个唯一整数作为audio_io_handle_t,并根据选定的音频设备的audio_module_handle_tmAudioHwDevs中查找对应的设备的AudioHwDevice对象inHwDev

找到inHwDev设备后,调用该设备的HAL中的open_input_stream方法,即audio_hw.c中的adev_open_input_stream。在adev_open_input_stream中构造HAL层的自定义类型stream_in(如stub_stream_in),并在stream_in中植入自己定义的HAL层函数,然后把该stream_in返回给AudioFlinger

AudioFlinger使用HAL返回的stream_in以及前面找出的设备的AudioHwDevice构造AF中的AudioStreamIn类型对象input,然后创建一个新的RecordThread线程,并将该线程以前面传入的audio_io_handle_t做索引存入mRecordThreads中,返回audio_io_handle_t,即audio_io_handle_t是在AudioFlinger中找出对应线程的索引。


推荐阅读
  • 使用 Azure Service Principal 和 Microsoft Graph API 获取 AAD 用户列表
    本文介绍了一段通用代码示例,该代码不仅能够操作 Azure Active Directory (AAD),还可以通过 Azure Service Principal 的授权访问和管理 Azure 订阅资源。Azure 的架构可以分为两个层级:AAD 和 Subscription。 ... [详细]
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • 深入解析JVM垃圾收集器
    本文基于《深入理解Java虚拟机:JVM高级特性与最佳实践》第二版,详细探讨了JVM中不同类型的垃圾收集器及其工作原理。通过介绍各种垃圾收集器的特性和应用场景,帮助读者更好地理解和优化JVM内存管理。 ... [详细]
  • 深入解析Spring Cloud Ribbon负载均衡机制
    本文详细介绍了Spring Cloud中的Ribbon组件如何实现服务调用的负载均衡。通过分析其工作原理、源码结构及配置方式,帮助读者理解Ribbon在分布式系统中的重要作用。 ... [详细]
  • 本文深入探讨了 Java 中的 Serializable 接口,解释了其实现机制、用途及注意事项,帮助开发者更好地理解和使用序列化功能。 ... [详细]
  • Python自动化处理:从Word文档提取内容并生成带水印的PDF
    本文介绍如何利用Python实现从特定网站下载Word文档,去除水印并添加自定义水印,最终将文档转换为PDF格式。该方法适用于批量处理和自动化需求。 ... [详细]
  • XNA 3.0 游戏编程:从 XML 文件加载数据
    本文介绍如何在 XNA 3.0 游戏项目中从 XML 文件加载数据。我们将探讨如何将 XML 数据序列化为二进制文件,并通过内容管道加载到游戏中。此外,还会涉及自定义类型读取器和写入器的实现。 ... [详细]
  • 本文深入探讨了Linux系统中网卡绑定(bonding)的七种工作模式。网卡绑定技术通过将多个物理网卡组合成一个逻辑网卡,实现网络冗余、带宽聚合和负载均衡,在生产环境中广泛应用。文章详细介绍了每种模式的特点、适用场景及配置方法。 ... [详细]
  • 本文详细探讨了在Android 8.0设备上使用ChinaCock的TCCBarcodeScanner进行扫码时出现的应用闪退问题,并提供了解决方案。通过调整配置文件,可以有效避免这一问题。 ... [详细]
  • 本文详细解析了Python中的os和sys模块,介绍了它们的功能、常用方法及其在实际编程中的应用。 ... [详细]
  • 本文详细介绍如何使用Samba软件配置CIFS文件共享服务,涵盖安装、配置、权限管理及多用户挂载等关键步骤。通过具体示例和命令行操作,帮助读者快速搭建并优化Samba服务器。 ... [详细]
  • 在维护公司项目时,发现按下手机的某个物理按键后会激活相应的服务,并在屏幕上模拟点击特定坐标点。本文详细介绍了如何使用ADB Shell Input命令来模拟各种输入事件,包括滑动、按键和点击等。 ... [详细]
  • Hadoop入门与核心组件详解
    本文详细介绍了Hadoop的基础知识及其核心组件,包括HDFS、MapReduce和YARN。通过本文,读者可以全面了解Hadoop的生态系统及应用场景。 ... [详细]
  • 本文介绍了一款用于自动化部署 Linux 服务的 Bash 脚本。该脚本不仅涵盖了基本的文件复制和目录创建,还处理了系统服务的配置和启动,确保在多种 Linux 发行版上都能顺利运行。 ... [详细]
  • MySQL 数据库迁移指南:从本地到远程及磁盘间迁移
    本文详细介绍了如何在不同场景下进行 MySQL 数据库的迁移,包括从一个硬盘迁移到另一个硬盘、从一台计算机迁移到另一台计算机,以及解决迁移过程中可能遇到的问题。 ... [详细]
author-avatar
阆中猫猫覀_648
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有