在各层处理消息时都是使用notify将处理的信息返回的。各层都对下一层注册了notify函数。
Java层是处理返回给应用层的消息,postEventFromNative
- private static void postEventFromNative(Object mediaplayer_ref,
- int what, int arg1, int arg2, Object obj)
- {
- MediaPlayer mp = (MediaPlayer)((WeakReference)mediaplayer_ref).get();
- if (mp == null) {
- return;
- }
-
- if (what == MEDIA_INFO && arg1 == MEDIA_INFO_STARTED_AS_NEXT) {
-
- mp.start();
- }
- if (mp.mEventHandler != null) {
- Message m = mp.mEventHandler.obtainMessage(what, arg1, arg2, obj);
- mp.mEventHandler.sendMessage(m);
- }
- }
之后将一些消息扔给EventHandler处理。有些是调用app注册的回调函数,如onPrepared,onCompletion,onBufferingUpdate,onSeekComplete等。
JNI层首先定义了各种Java层的本地变量和回调函数,MediaPlayer的Java层回调函数使用post_event:
- struct fields_t {
- jfieldID context;
- jfieldID surface_texture;
-
- jmethodID post_event;
-
- jmethodID proxyConfigGetHost;
- jmethodID proxyConfigGetPort;
- jmethodID proxyConfigGetExclusionList;
- };
- static fields_t fields;
获取post_event的代码:
- jclass clazz;
-
- clazz = env->FindClass("android/media/MediaPlayer");
- if (clazz == NULL) {
- return;
- }
-
- 。。。。。。
-
- fields.post_event = env->GetStaticMethodID(clazz, "postEventFromNative",
- "(Ljava/lang/Object;IIILjava/lang/Object;)V");
- if (fields.post_event == NULL) {
- return;
- }
那么在什么地方调用它呢?当然是在jni层提供给下层的notify中了
- void JNIMediaPlayerListener::notify(int msg, int ext1, int ext2, const Parcel *obj)
- {
- JNIEnv *env = AndroidRuntime::getJNIEnv();
- if (obj && obj->dataSize() > 0) {
- jobject jParcel = createJavaParcelObject(env);
- if (jParcel != NULL) {
- Parcel* nativeParcel = parcelForJavaObject(env, jParcel);
- nativeParcel->setData(obj->data(), obj->dataSize());
- env->CallStaticVoidMethod(mClass, fields.post_event, mObject,
- msg, ext1, ext2, jParcel);
- env->DeleteLocalRef(jParcel);
- }
- } else {
- env->CallStaticVoidMethod(mClass, <strong>fields.post_event</strong>, mObject,
- msg, ext1, ext2, NULL);
- }
- if (env->ExceptionCheck()) {
- ALOGW("An exception occurred while notifying an event.");
- LOGW_EX(env);
- env->ExceptionClear();
- }
- }
下层注册回调的地方是
- static void
- android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this)
- {
- ALOGV("native_setup");
- sp<MediaPlayer> mp = new MediaPlayer();
- if (mp == NULL) {
- jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
- return;
- }
-
-
- sp<JNIMediaPlayerListener> listener = new JNIMediaPlayerListener(env, thiz, weak_this);
- <strong>mp->setListener(listener)</strong>;
-
-
- setMediaPlayer(env, thiz, mp);
- }
继续看MediaPlayer层的setListener
- status_t MediaPlayer::setListener(const sp<MediaPlayerListener>& listener)
- {
- ALOGV("setListener");
- Mutex::Autolock _l(mLock);
- mListener = listener;
- return NO_ERROR;
- }
这层就是将JNI层的JNIMediaPlayerListener赋值给mListener。那么何时调用notify呢?
在MediaPlayer给下层的notify中找到了它,同时我们也找到了MediaPlayer给Stagefright层注册的notify回调
- void MediaPlayer::notify(int msg, int ext1, int ext2, const Parcel *obj)
- {
- ALOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2);
- bool send = true;
- bool locked = false;
-
-
-
-
-
-
-
-
-
- if (mLockThreadId != getThreadId()) {
- mLock.lock();
- locked = true;
- }
-
-
- if (!(msg == MEDIA_ERROR && mCurrentState == MEDIA_PLAYER_IDLE) && mPlayer == 0) {
- ALOGV("notify(%d, %d, %d) callback on disconnected mediaplayer", msg, ext1, ext2);
- if (locked) mLock.unlock();
- return;
- }
-
- switch (msg) {
- case MEDIA_NOP:
- break;
- case MEDIA_PREPARED:
- ALOGV("prepared");
- mCurrentState = MEDIA_PLAYER_PREPARED;
- if (mPrepareSync) {
- ALOGV("signal application thread");
- mPrepareSync = false;
- mPrepareStatus = NO_ERROR;
- mSignal.signal();
- }
- break;
- case MEDIA_PLAYBACK_COMPLETE:
- ALOGV("playback complete");
- if (mCurrentState == MEDIA_PLAYER_IDLE) {
- ALOGE("playback complete in idle state");
- }
- if (!mLoop) {
- mCurrentState = MEDIA_PLAYER_PLAYBACK_COMPLETE;
- }
- break;
- case MEDIA_ERROR:
-
-
-
- ALOGE("error (%d, %d)", ext1, ext2);
- mCurrentState = MEDIA_PLAYER_STATE_ERROR;
- if (mPrepareSync)
- {
- ALOGV("signal application thread");
- mPrepareSync = false;
- mPrepareStatus = ext1;
- mSignal.signal();
- send = false;
- }
- break;
- case MEDIA_INFO:
-
-
- if (ext1 != MEDIA_INFO_VIDEO_TRACK_LAGGING) {
- ALOGW("info/warning (%d, %d)", ext1, ext2);
- }
- break;
- case MEDIA_SEEK_COMPLETE:
- ALOGV("Received seek complete");
- if (mSeekPosition != mCurrentPosition) {
- ALOGV("Executing queued seekTo(%d)", mSeekPosition);
- mSeekPosition = -1;
- seekTo_l(mCurrentPosition);
- }
- else {
- ALOGV("All seeks complete - return to regularly scheduled program");
- mCurrentPosition = mSeekPosition = -1;
- }
- break;
- case MEDIA_BUFFERING_UPDATE:
- ALOGV("buffering %d", ext1);
- break;
- case MEDIA_SET_VIDEO_SIZE:
- ALOGV("New video size %d x %d", ext1, ext2);
- mVideoWidth = ext1;
- mVideoHeight = ext2;
- break;
- case MEDIA_TIMED_TEXT:
- ALOGV("Received timed text message");
- break;
- case MEDIA_SUBTITLE_DATA:
- ALOGV("Received subtitle data message");
- break;
- default:
- ALOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2);
- break;
- }
-
- sp<MediaPlayerListener> <strong>listener = mListene</strong>r;
- if (locked) mLock.unlock();
-
-
- if ((listener != 0) && send) {
- Mutex::Autolock _l(mNotifyLock);
- ALOGV("callback application");
- <strong>listener->notify</strong>(msg, ext1, ext2, obj);
- ALOGV("back from callback");
- }
- }
根据前一篇的分析,MediaPlayer是一个BpMediaPlayer,而调用它的notify的函数肯定在BnMediaPlayer里。BnMediaPlayer是MediaPlayer::Client
那么BnMediaPlayer的notify函数里肯定有BpMediaPlayer的notify,继续寻找:
- void MediaPlayerService::Client::notify(
- void* cookie, int msg, int ext1, int ext2, const Parcel *obj)
- {
- Client* client = static_cast<Client*>(cookie);
- if (client == NULL) {
- return;
- }
-
- sp<IMediaPlayerClient> c;
- {
- Mutex::Autolock l(client->mLock);
- <strong>c = client->mClient</strong>;
- if (msg == MEDIA_PLAYBACK_COMPLETE && client->mNextClient != NULL) {
- if (client->mAudioOutput != NULL)
- client->mAudioOutput->switchToNextOutput();
- client->mNextClient->start();
- client->mNextClient->mClient->notify(MEDIA_INFO, MEDIA_INFO_STARTED_AS_NEXT, 0, obj);
- }
- }
-
- if (MEDIA_INFO == msg &&
- MEDIA_INFO_METADATA_UPDATE == ext1) {
- const media::Metadata::Type metadata_type = ext2;
-
- if(client->shouldDropMetadata(metadata_type)) {
- return;
- }
-
-
-
- client->addNewMetadataUpdate(metadata_type);
- }
-
- if (c != NULL) {
- ALOGV("[%d] notify (%p, %d, %d, %d)", client->mConnId, cookie, msg, ext1, ext2);
- <strong>c->notify</strong>(msg, ext1, ext2, obj);
- }
- }
上面的c代表BpMediaPlayer对象。
这样,MediaPlayerService::Client::notify就是BnMediaPlayer的通知函数了。接着找调用它的位置。
再往下找根据前一篇的分析,肯定是要到AwesomePlayer里找,但是我们只在AwesomePlayer里找到了AwesomePlayer::notifyListener_l。
那么究竟是从什么地方注册了MediaPlayerService::Client::notify,又是从什么地方调用它的呢?继续找
我们按照前一篇的思路,从create函数开始找。
- sp<MediaPlayerBase> MediaPlayerService::Client::createPlayer(player_type playerType)
- {
-
- sp<MediaPlayerBase> p = mPlayer;
- if ((p != NULL) && (p->playerType() != playerType)) {
- ALOGV("delete player");
- p.clear();
- }
- if (p == NULL) {
- p = MediaPlayerFactory::createPlayer(playerType, this, <strong><span style="color:#ff0000;">notify</span></strong>);
- }
-
- if (p != NULL) {
- p->setUID(mUID);
- }
-
- return p;
- }
一下就找到了MediaPlayerService::Client::notify,继续往下找
- sp<MediaPlayerBase> MediaPlayerFactory::createPlayer(
- player_type playerType,
- void* cookie,
- notify_callback_f <strong>notifyFunc</strong>) {
- sp<MediaPlayerBase> p;
- IFactory* factory;
- status_t init_result;
- Mutex::Autolock lock_(&sLock);
-
- if (sFactoryMap.indexOfKey(playerType) < 0) {
- ALOGE("Failed to create player object of type %d, no registered"
- " factory", playerType);
- return p;
- }
-
- factory = sFactoryMap.valueFor(playerType);
- CHECK(NULL != factory);
- p = factory->createPlayer();
-
- if (p == NULL) {
- ALOGE("Failed to create player object of type %d, create failed",
- playerType);
- return p;
- }
-
- init_result = p->initCheck();
- if (init_result == NO_ERROR) {
- <strong><span style="color:#ff0000;">p->setNotifyCallback(cookie, notifyFunc)</span></strong>;
- } else {
- ALOGE("Failed to create player object of type %d, initCheck failed"
- " (res = %d)", playerType, init_result);
- p.clear();
- }
-
- return p;
- }
变量p是MediaPlayerBase类的对象,那么setNotifyCallback就是将MediaPlayerService::Client::notify注册给了它。
我们来看看setNotifyCallback函数,很简单,就是赋值
- void setNotifyCallback(
- void* cookie, notify_callback_f notifyFunc) {
- Mutex::Autolock autoLock(mNotifyLock);
- mCookie = cookie; mNotify = notifyFunc;
- }
终于在MediaPlayerBase类里找到了notify赋值的地方,那么对应的就应该有调用的地方。
没错,就在下面的sendEvent
- void sendEvent(int msg, int ext1=0, int ext2=0,
- const Parcel *obj=NULL) {
- Mutex::Autolock autoLock(mNotifyLock);
- if (mNotify) mNotify(mCookie, msg, ext1, ext2, obj);
- }
而这个sendEvent就是在AwesomePlayer::notifyListener_l里调用的:
- void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
- if ((mListener != NULL) && !mAudioTearDown) {
- sp<MediaPlayerBase> listener = mListener.promote();
-
- if (listener != NULL) {
- listener->sendEvent(msg, ext1, ext2);
- }
- }
- }
看来帅哥为了通知上面的app,也是费尽周折啊。
- AwesomePlayer.cpp: notifyListener_l(MEDIA_PAUSED);
- AwesomePlayer.cpp: notifyListener_l(MEDIA_PAUSED);
- AwesomePlayer.cpp: notifyListener_l(MEDIA_PAUSED);
- AwesomePlayer.cpp: notifyListener_l(MEDIA_SEEK_COMPLETE);
- AwesomePlayer.cpp: notifyListener_l(MEDIA_SKIPPED);
- AwesomePlayer.cpp: notifyListener_l(MEDIA_SEEK_COMPLETE);
- AwesomePlayer.cpp: notifyListener_l(MEDIA_INFO, MEDIA_INFO_RENDERING_START);
- AwesomePlayer.cpp: notifyListener_l(MEDIA_SEEK_COMPLETE);
- AwesomePlayer.cpp: notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
- AwesomePlayer.cpp: notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
- AwesomePlayer.cpp: notifyListener_l(MEDIA_PREPARED);
- AwesomePlayer.cpp: notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
这里仅列出一部分通知的调用。