这一节我们来看看在Android N Audio播放一:如何播放一首音乐中介绍的播放音乐的第二步:
player.prepare();
同样,我们在MusicDemo中将start方法注释掉。这样可以看得更清楚。
private void play(){
try {
String path = Environment.getExternalStorageDirectory().getAbsolutePath()+"/Music/Test.mp3";
player.setDataSource(path);
Log.d("Jaychou","MusicDemo setDataSource");
player.prepare();
Log.d("Jaychou","MusicDemo Prepare");
//player.start();
} catch (IOException e) {
e.printStackTrace();
Log.d("Jaychou","err when play");
}
}
1. prepare序列图
先来一张用UML工具Astah画的prepare的序列图, 让我们对流程有个大致的认识。
我也不知道为啥每次传上来的流程图看着都不清晰,看不清楚的同学可以下载到本地再放大一点看。
2. prepare都干了些啥
2.1 Client端
序列图中的MusicDemo, MediaPlayer.java, Mediaplayer.cpp都是属于Client端,他们属于同一个进程。
一直调到Mediaplayer.cpp的prepare.
./frameworks/av/media/libmedia/Mediaplayer.cpp#prepare
status_t MediaPlayer::prepare()
{
ALOGV("prepare");
Mutex::Autolock _l(mLock);
mLockThreadId = getThreadId();
if (mPrepareSync) {
mLockThreadId = 0;
return -EALREADY;
}
mPrepareSync = true;
status_t ret = prepareAsync_l();
if (ret != NO_ERROR) {
mLockThreadId = 0;
return ret;
}
if (mPrepareSync) {
mSignal.wait(mLock); // wait for prepare done
mPrepareSync = false;
}
ALOGV("prepare complete - status=%d", mPrepareStatus);
mLockThreadId = 0;
return mPrepareStatus;
再到
status_t MediaPlayer::prepareAsync_l()
{
if ( (mPlayer != 0) && ( mCurrentState & (MEDIA_PLAYER_INITIALIZED | MEDIA_PLAYER_STOPPED) ) ) {
if (mAudioAttributesParcel != NULL) {
mPlayer->setParameter(KEY_PARAMETER_AUDIO_ATTRIBUTES, *mAudioAttributesParcel);
} else {
mPlayer->setAudioStreamType(mStreamType);
}
mCurrentState = MEDIA_PLAYER_PREPARING;
return mPlayer->prepareAsync();
}
ALOGE("prepareAsync called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
return INVALID_OPERATION;
}
可以看到,client端主要是调用service端的方法来设置Parameter, AudioStreamType和调用具体播放器(上一节我们知道是Nuplayer)的prepare方法. 还有一个是任务就是设置VideoSurfaceTexture,这个是在JNI层调用下来的,在日志中也可以看到:
02-13 18:57:15.769 V/MediaPlayer( 4477): setVideoSurfaceTexture
02-13 18:57:15.772 V/MediaPlayerService( 616): [4] setVideoSurfaceTexture(0x0)
02-13 18:57:15.774 V/MediaPlayerService( 616): [4] setAudioStreamType(3)
2.2 Service端
序列图中的mediaplayerservice之后的部分都是属于service端,它们是属于另一个进程。
2.2.1 MediaPlayerService
./frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp#prepareAsync
status_t MediaPlayerService::Client::prepareAsync()
{
ALOGV("[%d] prepareAsync", mConnId);
sp<MediaPlayerBase> p = getPlayer();
if (p == 0) return UNKNOWN_ERROR;
status_t ret = p->prepareAsync();
#if CALLBACK_ANTAGONIZER
ALOGD("start Antagonizer");
if (ret == NO_ERROR) mAntagonizer->start();
#endif
return ret;
}
这里主要是调用Nupl