第7章 Android的Audio系统
本章介绍Android的音频系统内容,主要是音频的输入/输出环节,不涉及编解码的内容(音频系统从驱动程序、本地框架到Java框架都具有内容)。本章介绍Audio系统各个层次的内容、Audio硬件抽象层的实现。
在学习本章的过程中,读者应重点关注以下内容:
Audio系统结构(知识性内容)
在Java中调用Audio系统的方式(知识性内容)
Audio系统本地代码的接口(开发要点)
Audio硬件抽象层的实现(开发要点)
7.1 Audio系统综述
Audio系统在Android中负责音频方面的数据流传输和控制功能,也负责音频设备的管理。这个部分作为Android的Audio系统的输入/输出层次,一般负责播放PCM声音输出和从外部获取PCM声音,以及管理声音设备和设置。
Audio系统主要分成如下几个层次:
(1)media库提供的Audio系统本地部分接口;
(2)AudioFlinger作为Audio系统的中间层;
(3)Audio的硬件抽象层提供底层支持;
(4)Audio接口通过JNI和Java框架提供给上层。
Audio系统的各个层次接口主要提供了两方面功能:放音(Track)和录音(Recorder)。
Android的Audio系统结构如图7-1所示。

Android系统的代码分布情况如下所示:
(1)Audio的Java部分
代码路径:frameworks/base/media/java/android/media
与Audio相关的Java包是android.media,主要包含AudioManager和Audio系统的几个类。
(2)Audio的JNI部分
代码路径:frameworks/base/core/jni
生成库libandroid_runtime.so,Audio的JNI是其中的一个部分。
(3)Audio的框架部分
头文件路径:frameworks/base/include/media/
源代码路径:frameworks/base/media/libmedia/
Audio本地框架是media库的一部分,本部分内容被编译成库libmedia.so,提供Audio部分的接口(包括基于Binder的IPC机制)。
(4)Audio Flinger
代码路径:frameworks/base/libs/audioflinger
这部分内容被编译成库libaudioflinger.so,它是Audio系统的本地服务部分。
(5)Audio的硬件抽象层接口
头文件路径:hardware/libhardware_legacy/include/hardware/
Audio硬件抽象层的实现在各个系统中可能是不同的,需要使用代码去继承相应的类并实现它们,作为Android系统本地框架层和驱动程序接口。7.2 Audio系统和上层接口
在Android中,Audio系统自上而下由Java的Audio类、Audio本地框架类、AudioFlinger和Audio的硬件抽象层几个部分组成。
7.2.1 Audio系统的各个层次
Audio系统的各层次情况如下所示。
Audio本地框架类是libmedia.so的一个部分,这些Audio接口对上层提供接口,由下层的本地代码去实现。
AudioFlinger继承libmeida中的接口,提供实现库libaudiofilnger.so。这部分内容没有自己的对外头文件,上层调用的只是libmedia本部分的接口,但实际调用的内容是libaudioflinger.so。
Audio使用JNI和Java对上层提供接口,JNI部分通过调用libmedia库提供的接口来实现。
Audio的硬件抽象层提供到硬件的接口,供AudioFlinger调用。Audio的硬件抽象层实际上是各个平台开发过程中需要主要关注和独立完成的部分。
提示:Android的Audio系统不涉及编解码环节,只是负责上层系统和底层Audio硬件的交互,一般以PCM作为输入/输出格式。
在Android的Audio系统中,无论上层还是下层,都使用一个管理类和输出输入两个类来表示整个Audio系统,输出输入两个类负责数据通道。在各个层次之间具有对应关系,如表7-1所示所示。
|
Audio管理环节 |
Audio输出 |
Audio输入 |
|
Java层 |
android.media. AudioSystem |
android.media AudioTrack |
android.media. AudioRecorder |
|
本地框架层 |
AudioSystem |
AudioTrack |
AudioRecorder |
|
AudioFlinger |
IAudioFlinger |
IAudioTrack |
IAudioRecorder |
|
硬件抽象层 |
AudioHardwareInterface |
AudioStreamOut |
AudioStreamIn |
7.2.2 media库中的Audio框架部分
Android的Audio系统的核心框架在media库中提供,对上面主要实现AudioSystem、AudioTrack和AudioRecorder三个类。
提供了IAudioFlinger类接口,在这个类中,可以获得IAudioTrack和IAudioRecorder两个接口,分别用于声音的播 放和录制。AudioTrack和AudioRecorder分别通过调用IAudioTrack和IAudioRecorder来实现。
Audio系统的头文件在frameworks/base/include/media/目录中,主要的头文件如下:
AudioSystem.h:media库的Audio部分对上层的总管接口;
IAudioFlinger.h:需要下层实现的总管接口;
AudioTrack.h:放音部分对上接口;
IAudioTrack.h:放音部分需要下层实现的接口;
AudioRecorder.h:录音部分对上接口;
IAudioRecorder.h:录音部分需要下层实现的接口。
IAudioFlinger.h、IAudioTrack.h和IAudioRecorder.h这三个接口通过下层的继承来实现(即 AudioFlinger)。AudioFlinger.h、AudioTrack.h和AudioRecorder.h是对上层提供的接口,它们既供本 地程序调用(例如声音的播放器、录制器等),也可以通过JNI向Java层提供接口。
meida库中Audio部分的结构如图7-2所示。
从功能上看,AudioSystem负责的是Audio系统的综合管理功能,而AudioTrack和AudioRecorder分别负责音频数据的输出和输入,即播放和录制。
AudioSystem.h中主要定义了一些枚举值和set/get等一系列接口,如下所示:- 1. class AudioSystem
-
2. {
-
3. public:
-
4. enum stream_type { // Audio 流的类型
-
5. SYSTEM = 1,
-
6. RING = 2,
-
7. MUSIC = 3,
-
8. ALARM = 4,
-
9. NOTIFICATION = 5,
-
10. BLUETOOTH_SCO = 6,
-
11. ENFORCED_AUDIBLE = 7,
-
12. NUM_STREAM_TYPES
-
13. };
-
14. enum audio_output_type { // Audio数据输出类型
-
15. // …… 省略部分内容 };
-
16. enum audio_format { // Audio数据格式
-
17. FORMAT_DEFAULT = 0,
-
18. PCM_16_BIT,
-
19. PCM_8_BIT,
-
20. INVALID_FORMAT
-
21. };
-
22. enum audio_mode { // Audio模式
-
23. // …… 省略部分内容 };
-
24. enum audio_routes { // Audio 路径类型
-
25. ROUTE_EARPIECE = (1 << 0),
-
26. ROUTE_SPEAKER = (1 << 1),
-
27. ROUTE_BLUETOOTH_SCO = (1 << 2),
-
28. ROUTE_HEADSET = (1 << 3),
-
29. ROUTE_BLUETOOTH_A2DP = (1 << 4),
-
30. ROUTE_ALL = -1UL,
-
31. };
-
32. // …… 省略部分内容
-
33. static status_t setMasterVolume(float value);
-
34. static status_t setMasterMute(bool mute);
-
35. static status_t getMasterVolume(float* volume);
-
36. static status_t getMasterMute(bool* mute);
-
37. static status_t setStreamVolume(int stream, float value);
-
38. static status_t setStreamMute(int stream, bool mute);
-
39. static status_t getStreamVolume(int stream, float* volume);
-
40. static status_t getStreamMute(int stream, bool* mute);
-
41. static status_t setMode(int mode);
-
42. static status_t getMode(int* mode);
-
43. static status_t setRouting(int mode,
-
uint32_t routes, uint32_t mask);
-
44. static status_t getRouting(int mode, uint32_t* routes);
-
45. // …… 省略部分内容
- 46. };
在Audio系统的几个枚举值中,audio_routes是由单独的位来表示的,而不是由顺序的枚举值表示,因此这个值在使用过程中可以使用" 或"的方式。例如,表示声音可以既从耳机(EARPIECE)输出,也从扬声器(SPEAKER)输出,这样是否能实现,由下层提供支持。在这个类 中,set/get等接口控制的也是相关的内容,例如Audio声音的大小、Audio的模式、路径等。
AudioTrack是Audio输出环节的类,其中最重要的接口是write(),主要的函数如下所示。
- 1. class AudioTrack
-
2. {
-
3. typedef void (*callback_t)(int event,
-
void* user, void *info);
-
4. AudioTrack( int streamType,
-
5. uint32_t sampleRate = 0, // 音频的采样律
-
6. int format = 0, //
-
音频的格式(例如8位或者16位的PCM)
-
7. int channelCount = 0, // 音频的通道数
-
8. int frameCount = 0, // 音频的帧数
-
9. uint32_t flags = 0,
-
10. callback_t cbf = 0,
-
11. void* user = 0,
-
12. int notificationFrames = 0);
-
13. void start();
-
14. void stop();
-
15. void flush();
-
16. void pause();
-
17. void mute(bool);
-
18. ssize_t write(const void* buffer, size_t size);
-
19. // …… 省略部分内容
- 20. }
AudioRecord是Audio输入环节的类,其中最重要的接口为read(),主要的函数如下所示。
- 1. class AudioRecord
-
2. {
-
3. public:
-
4. AudioRecord(int streamType,
-
5. uint32_t sampleRate = 0, // 音频的采样律
-
6. int format = 0, //
-
音频的格式(例如8位或者16位的PCM)
-
7. int channelCount = 0, // 音频的通道数
-
8. int frameCount = 0, // 音频的帧数
-
9. uint32_t flags = 0,
-
10. callback_t cbf = 0,
-
11. void* user = 0,
-
12. int notificationFrames = 0);
-
13. status_t start();
-
14. status_t stop();
-
15. ssize_t read(void* buffer, size_t size);
-
16. // …… 省略部分内容
- 17. }
AudioTrack和AudioRecord的read/write函数的参数都是内存的指 针及其大小,内存中的内容一般表示的是Audio的原始数据(PCM数据)。这两个类还涉及Auido数据格式、通道数、帧数目等参数,可以在建立时指 定,也可以在建立之后使用set()函数进行设置。
在libmedia库中提供的只是一个Audio系统框架,AudioSystem、 AudioTrack和AudioRecord分别调用下层的IAudioFlinger、IAudioTrack和IAudioRecord来实现。另 外的一个接口是IAudioFlingerClient,它作为向IAudioFlinger中注册的监听器,相当于使用回调函数获取 IAudioFlinger运行时信息。