Android Audio System 架构初探:Java层
2016-01-23 09:52
447 查看
1 Java层
1.1 AudioManager
AudioManager是Framework向App提供的接口,可以认为是audioService的一个Wrapper类。它内部的功能实现函数的一般描述如下:public void setStreamMute(int streamType,
boolean state)
{
IAudioServiceservice = getService();
try {
service.setStreamMute(streamType, state, mICallBack);
} catch
(RemoteException e)
{
Log.e(TAG,
"Dead object in setStreamMute", e);
}
}
而getService拿到的就是AudioService
private static IAudioService getService()
{
if (sService
!= null)
{
return sService;
}
IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
sService = IAudioService.Stub.asInterface(b);
return sService;
}
Android把系统的音频按功能分成不同的Stream,并暴露给上层App。Framework的AudioPolicyManager就是根据流进行Policy管理的。比如STREAM_NOTIFICATION的流在STREAM_MUSIC流Active的时候也可以中断它,等等。另外厂商也可以定制自己的流,比如Android本身不支持FM,那某些厂商需要添加FM的功能,为了方便管理,就可以添加一个FM流,比如叫STREAM_FM。
STREAM_VOICE_CALL | |
STREAM_SYSTEM | |
STREAM_RING | |
STREAM_MUSIC | |
STREAM_ALARM | |
STREAM_NOTIFICATION | |
STREAM_BLUETOOTH_SCO | |
STREAM_SYSTEM_ENFORCED | |
STREAM_DTMF | |
STREAM_TTS |
1.2 AudioService
图表 2 AudioService的Binder Server属性
IAudioService.Stub定义于IAudioService.aidl,后者编译时可生成IAudioService.java。AudioManager利用IAudioService.Stub获得AudioService的Bp,从而可以跨进程的使用AudioService的服务。
privatestatic IAudioService getService(){
IBinder b =ServiceManager.getService(Context.AUDIO_SERVICE);
sService =IAudioService.Stub.asInterface(b);
return sService;
}
AudioService服务由SystemServer创建,并且拥有一个自己的线程,这个线程一直利用mAudioHandler处理收到的消息。所以不耗时的事情是SystemServer做的,而耗时的事情是AudioService线程做的。
AudioService通过对AudioSystem.java进行函数调用与Native 系统进行通信。
AudioService启动的时候,会从数据库里读取上次记下来的音量,ringer mode,vibrator mode等,然后设置下去。
/** @hide */
public AudioService(Context context)
{
......
updateStreamVolumeAlias(false
/*updateVolumes*/);
readPersistedSettings();
setRingerModeInt(getRingerModeInternal(),
false);
......
}
Mute管理
AudioService有很多client,setStreamMute是每个client都可以去mute一个流,采用计数方式,每个APP有一个自己的全局变量count,mute后count++,unmute后count--。而AudioService会把所有client对应的count值相加,若值为0,则认为此流unmute,否则此流还是mute。
而client在死的时候,会unmute自己mute过的流。
因为一个client无法unmute其他client mute过的流,因此若一个client mute了一个流而没有unmute,则别的进程是无法unmute一个流的。这样有可能造成系统静音。
1.3 AudioSystem
图表3AudioSystem和AudioFlinger以及AudioPolicyService的双向通信机制
AudioSystem.java就是AudioSystem.cpp的一层封装,它通过native方法调用到Framework里。AudioSystem提供的全部都是static函数,它总是运行在调用者的进程里,比如AudioService调用它,它就运行在SystemServer进程里。Framework里的服务如AudioFlinger,AudioPolicyService运行在MediaServer进程里,这种跨进程调用的标准做法就是Binder,所以AudioSystem.cpp总是持有AudioFlinger和AudioPolicyService的Bp。
AudioSystem.cpp第一次获取AudioFlinger时,注册一个AudioFlinger的死亡通知,对于APS同理。
const sp<IAudioFlinger> AudioSystem::get_audio_flinger()
{
sp<IAudioFlinger> af;
sp<AudioFlingerClient> afc;
{
Mutex::Autolock _l(gLock);
if (gAudioFlinger == 0) {
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder;
do {
binder = sm->getService(String16("media.audio_flinger"));
if (binder != 0)
break;
ALOGW("AudioFlingernot published, waiting...");
usleep(500000); // 0.5 s
} while (true);
if (gAudioFlingerClient == NULL) {
gAudioFlingerClient = new AudioFlingerClient();
} else {
if (gAudioErrorCallback) {
gAudioErrorCallback(NO_ERROR);
}
}
binder->linkToDeath(gAudioFlingerClient);
gAudioFlinger = interface_cast<IAudioFlinger>(binder);
LOG_ALWAYS_FATAL_IF(gAudioFlinger == 0);
afc = gAudioFlingerClient;
}
af = gAudioFlinger;
}
if (afc != 0) {
af->registerClient(afc);
}
return af;
}
如果MediaServer进程被杀死,那么AudioFlinger就会向它的所有Client发布一个Binder Die的消息,此时AudioSystem.cpp就会调用:
voidAudioSystem::AudioFlingerClient::binderDied(const wp<IBinder>& who__unused)
{
gAudioErrorCallback(DEAD_OBJECT);
}
最终在AudioService.java中处理消息MSG_MEDIA_SERVER_DIED,要等待mediaserver重启,并重新设置一遍参数等。
另外,AudioFlinger在audioConfigChanged的时候,会像所有的AudioFlingerClient发送通知mNotificationClients.valueAt(i)->audioFlingerClient()->ioConfigChanged()。
1.4 JNI
Android的Audio部分通过JNI向Java层提供接口,在Java层可以通过JNI接口完成Audio系统的大部分操作。AudioJNI部分的代码路径为:frameworks/base/core/jni。
其中,主要实现的3个文件为:android_media_AudioSystem.cpp、android_media_Audio Track.cpp和android_media_AudioRecord.cpp,它们分别对应了Android Java框架中的3个类的支持:
android.media.AudioSystem:负责Audio系统的总体控制;
android.media.AudioTrack:负责Audio系统的输出环节;
android.media.AudioRecorder:负责Audio系统的输入环节。
在Android的Java层中,可以对Audio系统进行控制和数据流操作,对于控制操作,和底层的处理基本一致;但是对于数据流操作,由于Java不支持指针,因此接口被封装成了另外的形式。
例如,对于音频输出,android_media_AudioTrack.cpp提供的是写字节和写短整型的接口类型。
相关文章推荐
- Android Audio System 架构初探:概述
- 网站怎么做扫码支付接口方便会员充值?
- 全新架构设计
- 【中级篇】LVS+keepalived 高可用负载均衡群集
- 从零开始搭建架构实施Android项目
- 从国外网站找到的 DirectX XAudio2 编程教程
- 构建高并发高可用的电商平台架构实践
- 三层架构
- web标签页,web网页的图标设置
- Android 设备benchmark 网站
- 2.1 项目的整体架构,项目搭建,也叫做 系统设计
- iOS开发中常用的几个苹果网站
- 一些前端设计相关网站收集
- 大型网站技术架构
- Heartbeat+DRBD+NFS高可用实例配置
- 网站推广的瞎想
- 前端架构,前端架构组织结构,目录结构架构
- 分布式网站部署
- 线上bug的解决方案--带来的全新架构设计
- Pinterest月PV百亿的架构设计