media: hook up OnFrameRenderedListener events to framework events

Bug: 20503131
Change-Id: Ife6d4862d14daf5b9659307af57417bd3532e8fe
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 93b8ec7..ce7f7e5 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -56,6 +56,7 @@
 enum {
     EVENT_CALLBACK = 1,
     EVENT_SET_CALLBACK = 2,
+    EVENT_FRAME_RENDERED = 3,
 };
 
 static struct CryptoErrorCodes {
@@ -226,6 +227,18 @@
     mByteBufferLimitMethodID = NULL;
 }
 
+status_t JMediaCodec::enableOnFrameRenderedListener(jboolean enable) {
+    if (enable) {
+        if (mOnFrameRenderedNotification == NULL) {
+            mOnFrameRenderedNotification = new AMessage(kWhatFrameRendered, this);
+        }
+    } else {
+        mOnFrameRenderedNotification.clear();
+    }
+
+    return mCodec->setOnFrameRenderedNotification(mOnFrameRenderedNotification);
+}
+
 status_t JMediaCodec::setCallback(jobject cb) {
     if (cb != NULL) {
         if (mCallbackNotification == NULL) {
@@ -728,6 +741,27 @@
     env->DeleteLocalRef(obj);
 }
 
+void JMediaCodec::handleFrameRenderedNotification(const sp<AMessage> &msg) {
+    int32_t arg1 = 0, arg2 = 0;
+    jobject obj = NULL;
+    JNIEnv *env = AndroidRuntime::getJNIEnv();
+
+    sp<AMessage> data;
+    CHECK(msg->findMessage("data", &data));
+
+    status_t err = ConvertMessageToMap(env, data, &obj);
+    if (err != OK) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return;
+    }
+
+    env->CallVoidMethod(
+            mObject, gFields.postEventFromNativeID,
+            EVENT_FRAME_RENDERED, arg1, arg2, obj);
+
+    env->DeleteLocalRef(obj);
+}
+
 void JMediaCodec::onMessageReceived(const sp<AMessage> &msg) {
     switch (msg->what()) {
         case kWhatCallbackNotify:
@@ -735,6 +769,11 @@
             handleCallback(msg);
             break;
         }
+        case kWhatFrameRendered:
+        {
+            handleFrameRenderedNotification(msg);
+            break;
+        }
         default:
             TRESPASS();
     }
@@ -848,6 +887,22 @@
     }
 }
 
+static void android_media_MediaCodec_native_enableOnFrameRenderedListener(
+        JNIEnv *env,
+        jobject thiz,
+        jboolean enabled) {
+    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
+
+    if (codec == NULL) {
+        throwExceptionAsNecessary(env, INVALID_OPERATION);
+        return;
+    }
+
+    status_t err = codec->enableOnFrameRenderedListener(enabled);
+
+    throwExceptionAsNecessary(env, err);
+}
+
 static void android_media_MediaCodec_native_setCallback(
         JNIEnv *env,
         jobject thiz,
@@ -1744,6 +1799,9 @@
     { "native_setInputSurface", "(Landroid/view/Surface;)V",
       (void *)android_media_MediaCodec_setInputSurface },
 
+    { "native_enableOnFrameRenderedListener", "(Z)V",
+      (void *)android_media_MediaCodec_native_enableOnFrameRenderedListener },
+
     { "native_setCallback",
       "(Landroid/media/MediaCodec$Callback;)V",
       (void *)android_media_MediaCodec_native_setCallback },
diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h
index a4ed67b..6650cf9 100644
--- a/media/jni/android_media_MediaCodec.h
+++ b/media/jni/android_media_MediaCodec.h
@@ -46,6 +46,8 @@
     void registerSelf();
     void release();
 
+    status_t enableOnFrameRenderedListener(jboolean enable);
+
     status_t setCallback(jobject cb);
 
     status_t configure(
@@ -116,11 +118,11 @@
     virtual ~JMediaCodec();
 
     virtual void onMessageReceived(const sp<AMessage> &msg);
-    void handleCallback(const sp<AMessage> &msg);
 
 private:
     enum {
         kWhatCallbackNotify,
+        kWhatFrameRendered,
     };
 
     jclass mClass;
@@ -139,6 +141,7 @@
     sp<MediaCodec> mCodec;
 
     sp<AMessage> mCallbackNotification;
+    sp<AMessage> mOnFrameRenderedNotification;
 
     status_t mInitStatus;
 
@@ -148,6 +151,8 @@
 
     void cacheJavaObjects(JNIEnv *env);
     void deleteJavaObjects(JNIEnv *env);
+    void handleCallback(const sp<AMessage> &msg);
+    void handleFrameRenderedNotification(const sp<AMessage> &msg);
 
     DISALLOW_EVIL_CONSTRUCTORS(JMediaCodec);
 };