Add tunnel mode video peek related APIs

Bug: 157501309
Test: atest android.media.cts.DecoderTest#testTunneledVideoPlayback
      atest android.media.cts.DecoderTest#testTunneledVideoFlush
CTS-Coverage-Bug: 157501309

Change-Id: I5107106bb64d96ac6cc7d8704955b2f4477b94a8
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 7f5dd5d..ded2e1b 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -81,6 +81,7 @@
     EVENT_CALLBACK = 1,
     EVENT_SET_CALLBACK = 2,
     EVENT_FRAME_RENDERED = 3,
+    EVENT_FIRST_TUNNEL_FRAME_READY = 4,
 };
 
 static struct CryptoErrorCodes {
@@ -269,6 +270,18 @@
     mClass = NULL;
 }
 
+status_t JMediaCodec::enableOnFirstTunnelFrameReadyListener(jboolean enable) {
+    if (enable) {
+        if (mOnFirstTunnelFrameReadyNotification == NULL) {
+            mOnFirstTunnelFrameReadyNotification = new AMessage(kWhatFirstTunnelFrameReady, this);
+        }
+    } else {
+        mOnFirstTunnelFrameReadyNotification.clear();
+    }
+
+    return mCodec->setOnFirstTunnelFrameReadyNotification(mOnFirstTunnelFrameReadyNotification);
+}
+
 status_t JMediaCodec::enableOnFrameRenderedListener(jboolean enable) {
     if (enable) {
         if (mOnFrameRenderedNotification == NULL) {
@@ -1058,6 +1071,27 @@
     env->DeleteLocalRef(obj);
 }
 
+void JMediaCodec::handleFirstTunnelFrameReadyNotification(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_FIRST_TUNNEL_FRAME_READY, arg1, arg2, obj);
+
+    env->DeleteLocalRef(obj);
+}
+
 void JMediaCodec::handleFrameRenderedNotification(const sp<AMessage> &msg) {
     int32_t arg1 = 0, arg2 = 0;
     jobject obj = NULL;
@@ -1100,6 +1134,11 @@
             }
             break;
         }
+        case kWhatFirstTunnelFrameReady:
+        {
+            handleFirstTunnelFrameReadyNotification(msg);
+            break;
+        }
         default:
             TRESPASS();
     }
@@ -1256,6 +1295,22 @@
     }
 }
 
+static void android_media_MediaCodec_native_enableOnFirstTunnelFrameReadyListener(
+        JNIEnv *env,
+        jobject thiz,
+        jboolean enabled) {
+    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
+
+    if (codec == NULL || codec->initCheck() != OK) {
+        throwExceptionAsNecessary(env, INVALID_OPERATION);
+        return;
+    }
+
+    status_t err = codec->enableOnFirstTunnelFrameReadyListener(enabled);
+
+    throwExceptionAsNecessary(env, err);
+}
+
 static void android_media_MediaCodec_native_enableOnFrameRenderedListener(
         JNIEnv *env,
         jobject thiz,
@@ -3138,6 +3193,9 @@
     { "native_setInputSurface", "(Landroid/view/Surface;)V",
       (void *)android_media_MediaCodec_setInputSurface },
 
+    { "native_enableOnFirstTunnelFrameReadyListener", "(Z)V",
+      (void *)android_media_MediaCodec_native_enableOnFirstTunnelFrameReadyListener },
+
     { "native_enableOnFrameRenderedListener", "(Z)V",
       (void *)android_media_MediaCodec_native_enableOnFrameRenderedListener },
 
diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h
index f16bcf3..5fd6bfd 100644
--- a/media/jni/android_media_MediaCodec.h
+++ b/media/jni/android_media_MediaCodec.h
@@ -63,6 +63,8 @@
     void release();
     void releaseAsync();
 
+    status_t enableOnFirstTunnelFrameReadyListener(jboolean enable);
+
     status_t enableOnFrameRenderedListener(jboolean enable);
 
     status_t setCallback(jobject cb);
@@ -176,6 +178,7 @@
         kWhatCallbackNotify,
         kWhatFrameRendered,
         kWhatAsyncReleaseComplete,
+        kWhatFirstTunnelFrameReady,
     };
 
     jclass mClass;
@@ -191,6 +194,7 @@
     std::once_flag mAsyncReleaseFlag;
 
     sp<AMessage> mCallbackNotification;
+    sp<AMessage> mOnFirstTunnelFrameReadyNotification;
     sp<AMessage> mOnFrameRenderedNotification;
 
     status_t mInitStatus;
@@ -203,6 +207,7 @@
             jobject *buf) const;
 
     void handleCallback(const sp<AMessage> &msg);
+    void handleFirstTunnelFrameReadyNotification(const sp<AMessage> &msg);
     void handleFrameRenderedNotification(const sp<AMessage> &msg);
 
     DISALLOW_EVIL_CONSTRUCTORS(JMediaCodec);