您的位置:首页 > 运维架构 > 网站架构

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提供的是写字节和写短整型的接口类型。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: