Android Audio代码分析5 - 函数getAudioSessionId
在我们学习AudioTrack对象的创建过程时,了解到,创建一个AudioTrack对象,必须指定一个SessionId,并与其他使用该SessionId的AudioTrack和MediaPlayer共享AudioEffect。
如果不指定SessionId,将会自动生成一个SessionId,AudioEffect会将该SessionId与新创建的AudioTrack对象关联起来。
别人可以通过getAudioSessionId函数取得该SessionId。
今天我们就看看getAudioSessionId函数。
在frameworks的代码中搜了一下,发现有两个地方实现了该函数,分别来说一下。
先说说在类MediaPlayer中的实现。
*****************************************源码*************************************************
int MediaPlayer::getAudioSessionId()
{
Mutex::Autolock _l(mLock);
return mAudioSessionId;
}
**********************************************************************************************
源码路径:
frameworks\base\media\libmedia\mediaplayer.cpp
###########################################说明################################################
代码很简单,只是将成员变量返回,没啥好说的。
那我们看看该成员变量是何时被赋值的。
找了下代码,发现有两个地方对该成员变量进行了赋值。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
一个在构造函数中。
MediaPlayer::MediaPlayer()
{
LOGV("constructor");
mListener = NULL;
mCookie = NULL;
mDuration = -1;
mStreamType = AudioSystem::MUSIC;
mCurrentPosition = -1;
mSeekPosition = -1;
mCurrentState = MEDIA_PLAYER_IDLE;
mPrepareSync = false;
mPrepareStatus = NO_ERROR;
mLoop = false;
mLeftVolume = mRightVolume = 1.0;
mVideoWidth = mVideoHeight = 0;
mLockThreadId = 0;
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
int AudioSystem::newAudioSessionId() {
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
if (af == 0) return 0;
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
int AudioFlinger::newAudioSessionId()
{
// 看到了函数nextUniqueId,我们感觉到有点熟悉。
// 不错,在我们看函数AudioSystem::getOutputSamplingRate的时候,看到,在函数AudioFlinger::openOutput中有调过函数nextUniqueId
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
int AudioFlinger::nextUniqueId()
{
// 这是一个自增的操作
// 可见,SessionId最终是在AudioFlinger中维护的。
// 关于函数android_atomic_inc,可参考以下链接:
// http://www.zzzyk.com/kf/201110/106982.html
return android_atomic_inc(&mNextUniqueId);
}
----------------------------------------------------------------
return nextUniqueId();
}
----------------------------------------------------------------
return af->newAudioSessionId();
}
----------------------------------------------------------------
mAudioSessionId = AudioSystem::newAudioSessionId();
mSendLevel = 0;
}
----------------------------------------------------------------
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
另一个给成员变量mAudioSessionId赋值的地方是在函数MediaPlayer::setAudioSessionId中。
status_t MediaPlayer::setAudioSessionId(int sessionId)
{
LOGV("MediaPlayer::setAudioSessionId(%d)", sessionId);
Mutex::Autolock _l(mLock);
if (!(mCurrentState & MEDIA_PLAYER_IDLE)) {
LOGE("setAudioSessionId called in state %d", mCurrentState);
return INVALID_OPERATION;
}
if (sessionId < 0) {
return BAD_VALUE;
}
mAudioSessionId = sessionId;
return NO_ERROR;
}
函数MediaPlayer::setAudioSessionId在函数android_media_MediaPlayer_set_audio_session_id中被调用。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
static void android_media_MediaPlayer_set_audio_session_id(JNIEnv *env, jobject thiz, jint sessionId) {
LOGV("set_session_id(): %d", sessionId);
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
static sp<MediaPlayer> getMediaPlayer(JNIEnv* env, jobject thiz)
{
Mutex::Autolock l(sLock);
MediaPlayer* const p = (MediaPlayer*)env->GetIntField(thiz, fields.context);
return sp<MediaPlayer>(p);
}
以前见到过类似的函数,肯定有某个地方把它set进去。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
static sp<MediaPlayer> setMediaPlayer(JNIEnv* env, jobject thiz, const sp<MediaPlayer>& player)
{
Mutex::Autolock l(sLock);
sp<MediaPlayer> old = (MediaPlayer*)env->GetIntField(thiz, fields.context);
if (player.get()) {
player->incStrong(thiz);
}
if (old != 0) {
old->decStrong(thiz);
}
env->SetIntField(thiz, fields.context, (int)player.get());
return old;
}
函数setMediaPlayer在函数android_media_MediaPlayer_native_setup中被调用。
函数android_media_MediaPlayer_native_setup也是供java调用的。
对应的接口,在下面的一个列表中可以看到。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
static void
android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this)
{
LOGV("native_setup");
// 在上面的代码中,SessionId的一个赋值的地方就是MediaPlayer的构造函数中。
// MediaPlayer对象就是在这儿被构造的。
sp<MediaPlayer> mp = new MediaPlayer();
if (mp == NULL) {
jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
return;
}
// create new listener and give it to MediaPlayer
// JNIMediaPlayerListener是一个代码量不多的类,其声明和实现如下:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ref-counted object for callbacks
class JNIMediaPlayerListener: public MediaPlayerListener
{
public:
JNIMediaPlayerListener(JNIEnv* env, jobject thiz, jobject weak_thiz);
~JNIMediaPlayerListener();
void notify(int msg, int
补充:移动开发 , Android ,