AudioTrack 主要的作用是播放音频,它是通过本地代码实现的。我主要是从两个方面分析AudioTrack,一是AudioTrack的系统架构,而是AudioTrack的使用。
AudioTrack的架构。
在android4.2.1中与 AudioTrack相关的代码分布在如下软件层中。
1. Application Framework
<1>AudioTrack.java(frameworks/base/media/java/android/media/AudioTrack.java)
AudioTrack.java 的主要作用是向Application层提供AudioTack的API。
AudioTrack.java 通过JNI 和AudioTrack的本地代码联系起来。AudioTrack的本地代码主要是在Libary 层。
<2>android_media_AudioTrack.cpp(frameworks/base/core/jni/android_media_AudioTrack.cpp
在这个jni中,会调用与AudioTrack相关的本地代码,如AudioTrack.cpp,AudioSystem.cpp
2. Libaries And Android Runtime
<1>AudioTrack.cpp
主要功能是通过 IAudioTrack来实现的。IAudioTrack和IAudioFlinger 的架构是一样的,都是基于Binder的服务架构。但是 IAudioFlinger 的实现类是 AudioFlinger.
但是 IAudioTrack的实现类不是 AudioTrack,而是 AudioFlinger 的内部类 TrackHandle,而TrackHandle 的核心则是 PlaybackThread::Track。换句话说IAudioTrack的功能是通过 PlaybackThread::Track,来实现的,PlaybackThread::Track,通过 AudioSystem.cpp调用 AudioPolicyService的功能,然后 AudioPolicyService 调用HAL 的功能。
<2>IAudioTrack.cpp
IAudioTrack是 AudioFlinger 提供给 AudioTrack 的接口。
<3>AudioFlinger.cpp
Audio 的核心Native Service,主要用于控制音频的输入输出,直接和HAL 通信,通过IAudioFlinger 提供调用接口。
AudioFlinger中的内部类TrackHanler,实现了Binder 接口IAudioTrack,也可以这么说,AudioFlinger 通过 IAudioFlinger 和 IAudioTrack,提供调用接口。
<4>AudioPolicyService.cpp
Audio 的核心 Native Service ,主要用于控制音频输入输出的策略,直接和 HAL 通信,通过IAudioPolicyService 提供调用接口。
<5>AudioSystem.cpp
主要是一个 控制器的作用,核心功能通过调用 IAudioFlinger,IAudioPolicyService 来实现。在Application Framework 中有 AudioSystem.java 和 android_media_AudioSystem.cpp 与它的功能对应。
3. HAL 层
这里不具体介绍Audio 的HAL 层,它会直接和 Audio Driver 交互。
AudioTrack 的初始化
1.AudioTrack::AudioTrack(
audio_stream_type_t streamType,
uint32_t sampleRate,
audio_format_t format,
audio_channel_mask_t channelMask,
const sp<IMemory>& sharedBuffer,
audio_output_flags_t flags,
callback_t cbf,
void* user,
int notificationFrames,
int sessionId)
: mStatus(NO_INIT),
mIsTimed(false),
mPreviousPriority(ANDROID_PRIORITY_NORMAL),
mPreviousSchedulingGroup(SP_DEFAULT)
{
mStatus = set(streamType, sampleRate, format, channelMask,
0 /*frameCount*/, flags, cbf, user, notificationFrames,
sharedBuffer, false /*threadCanCallJava*/, sessionId);
}
2.调用 AudioTrack::set 方法。
3.调用 AudioTrack::createTrack_l 方法
4.调用 AudioFlinger::createTrack 方法
sp<IAudioTrack> track = audioFlinger->createTrack(getpid(),
streamType,
sampleRate,
format,
channelMask,
frameCount,
trackFlags,
sharedBuffer,
output,
tid,
&mSessionId,
&status);
5.track = thread->createTrack_l(client, streamType, sampleRate, format,
channelMask, frameCount, sharedBuffer, lSessionId, flags, tid, &lStatus);
// move effect chain to this output thread if an effect on same session was waiting
// for a track to be created
if (lStatus == NO_ERROR && effectThread != NULL) {
Mutex::Autolock _dl(thread->mLock);
Mutex::Autolock _sl(effectThread->mLock);
moveEffectChain_l(lSessionId, effectThread, thread, true);
}
// Look for sync events awaiting for a session to be used.
for (int i = 0; i < (int)mPendingSyncEvents.size(); i++) {
if (mPendingSyncEvents[i]->triggerSession() == lSessionId) {
if (thread->isValidSyncEvent(mPendingSyncEvents[i])) {
if (lStatus == NO_ERROR) {
(void) track->setSyncEvent(mPendingSyncEvents[i]);
} else {
mPendingSyncEvents[i]->cancel();
}
mPendingSyncEvents.removeAt(i);
i--;
}
}
}
}
if (lStatus == NO_ERROR) {
trackHandle = new TrackHandle(track);
} else {
// remove local strong reference to Client before deleting the Track so that the Client
// destructor is called by the TrackBase destructor with mLock held
client.clear();
track.clear();
}
返回 TrackHandle,TrackHandle 持有 PlaybackThread::Track 对象。
6.调用 PlaybackThread::createTrack_l
if (!isTimed) {
track = new Track(this, client, streamType, sampleRate, format,
channelMask, frameCount, sharedBuffer, sessionId, flags);
} else {
track = TimedTrack::create(this, client, streamType, sampleRate, format,
channelMask, frameCount, sharedBuffer, sessionId);
}
if (track == 0 || track->getCblk() == NULL || track->name() < 0) {
lStatus = NO_MEMORY;
goto Exit;
}
mTracks.add(track);
AudioTrack的架构。
在android4.2.1中与 AudioTrack相关的代码分布在如下软件层中。
1. Application Framework
<1>AudioTrack.java(frameworks/base/media/java/android/media/AudioTrack.java)
AudioTrack.java 的主要作用是向Application层提供AudioTack的API。
AudioTrack.java 通过JNI 和AudioTrack的本地代码联系起来。AudioTrack的本地代码主要是在Libary 层。
<2>android_media_AudioTrack.cpp(frameworks/base/core/jni/android_media_AudioTrack.cpp
在这个jni中,会调用与AudioTrack相关的本地代码,如AudioTrack.cpp,AudioSystem.cpp
2. Libaries And Android Runtime
<1>AudioTrack.cpp
主要功能是通过 IAudioTrack来实现的。IAudioTrack和IAudioFlinger 的架构是一样的,都是基于Binder的服务架构。但是 IAudioFlinger 的实现类是 AudioFlinger.
但是 IAudioTrack的实现类不是 AudioTrack,而是 AudioFlinger 的内部类 TrackHandle,而TrackHandle 的核心则是 PlaybackThread::Track。换句话说IAudioTrack的功能是通过 PlaybackThread::Track,来实现的,PlaybackThread::Track,通过 AudioSystem.cpp调用 AudioPolicyService的功能,然后 AudioPolicyService 调用HAL 的功能。
<2>IAudioTrack.cpp
IAudioTrack是 AudioFlinger 提供给 AudioTrack 的接口。
<3>AudioFlinger.cpp
Audio 的核心Native Service,主要用于控制音频的输入输出,直接和HAL 通信,通过IAudioFlinger 提供调用接口。
AudioFlinger中的内部类TrackHanler,实现了Binder 接口IAudioTrack,也可以这么说,AudioFlinger 通过 IAudioFlinger 和 IAudioTrack,提供调用接口。
<4>AudioPolicyService.cpp
Audio 的核心 Native Service ,主要用于控制音频输入输出的策略,直接和 HAL 通信,通过IAudioPolicyService 提供调用接口。
<5>AudioSystem.cpp
主要是一个 控制器的作用,核心功能通过调用 IAudioFlinger,IAudioPolicyService 来实现。在Application Framework 中有 AudioSystem.java 和 android_media_AudioSystem.cpp 与它的功能对应。
3. HAL 层
这里不具体介绍Audio 的HAL 层,它会直接和 Audio Driver 交互。
AudioTrack 的初始化
1.AudioTrack::AudioTrack(
audio_stream_type_t streamType,
uint32_t sampleRate,
audio_format_t format,
audio_channel_mask_t channelMask,
const sp<IMemory>& sharedBuffer,
audio_output_flags_t flags,
callback_t cbf,
void* user,
int notificationFrames,
int sessionId)
: mStatus(NO_INIT),
mIsTimed(false),
mPreviousPriority(ANDROID_PRIORITY_NORMAL),
mPreviousSchedulingGroup(SP_DEFAULT)
{
mStatus = set(streamType, sampleRate, format, channelMask,
0 /*frameCount*/, flags, cbf, user, notificationFrames,
sharedBuffer, false /*threadCanCallJava*/, sessionId);
}
2.调用 AudioTrack::set 方法。
3.调用 AudioTrack::createTrack_l 方法
4.调用 AudioFlinger::createTrack 方法
sp<IAudioTrack> track = audioFlinger->createTrack(getpid(),
streamType,
sampleRate,
format,
channelMask,
frameCount,
trackFlags,
sharedBuffer,
output,
tid,
&mSessionId,
&status);
5.track = thread->createTrack_l(client, streamType, sampleRate, format,
channelMask, frameCount, sharedBuffer, lSessionId, flags, tid, &lStatus);
// move effect chain to this output thread if an effect on same session was waiting
// for a track to be created
if (lStatus == NO_ERROR && effectThread != NULL) {
Mutex::Autolock _dl(thread->mLock);
Mutex::Autolock _sl(effectThread->mLock);
moveEffectChain_l(lSessionId, effectThread, thread, true);
}
// Look for sync events awaiting for a session to be used.
for (int i = 0; i < (int)mPendingSyncEvents.size(); i++) {
if (mPendingSyncEvents[i]->triggerSession() == lSessionId) {
if (thread->isValidSyncEvent(mPendingSyncEvents[i])) {
if (lStatus == NO_ERROR) {
(void) track->setSyncEvent(mPendingSyncEvents[i]);
} else {
mPendingSyncEvents[i]->cancel();
}
mPendingSyncEvents.removeAt(i);
i--;
}
}
}
}
if (lStatus == NO_ERROR) {
trackHandle = new TrackHandle(track);
} else {
// remove local strong reference to Client before deleting the Track so that the Client
// destructor is called by the TrackBase destructor with mLock held
client.clear();
track.clear();
}
返回 TrackHandle,TrackHandle 持有 PlaybackThread::Track 对象。
6.调用 PlaybackThread::createTrack_l
if (!isTimed) {
track = new Track(this, client, streamType, sampleRate, format,
channelMask, frameCount, sharedBuffer, sessionId, flags);
} else {
track = TimedTrack::create(this, client, streamType, sampleRate, format,
channelMask, frameCount, sharedBuffer, sessionId);
}
if (track == 0 || track->getCblk() == NULL || track->name() < 0) {
lStatus = NO_MEMORY;
goto Exit;
}
mTracks.add(track);