Support shared av memory handle in Tuner JNI

In the MediaEvent of AV filters, the AV memory handle is mapped/unmapped on each event.
If the vendor allocates a persistent memory block, and use MediaEvent.offset to access the data,
the mapping change is unnecessary.

To improve this, a new API to get shared AV Memory is introduced in
Tuner HAL 1.1.

Tuner JNI queries the sharedAvMemory Handle when the media filter is
opened. It builds up linear block through either shared or independent
memory block by checking the memory handle fd number.

Test: make
Bug: 162013047
Bug: 157143515
Bug: 156664393
Change-Id: I5bfe3a8f4c26b5789212f56709b70c512ed15a0c
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index e0afe29..04dba36 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -309,9 +309,9 @@
 
 /////////////// MediaEvent ///////////////////////
 
-MediaEvent::MediaEvent(sp<IFilter> iFilter, hidl_handle avHandle,
-        uint64_t dataId, uint64_t dataLength, jobject obj) : mIFilter(iFilter),
-        mDataId(dataId), mDataLength(dataLength), mBuffer(nullptr),
+MediaEvent::MediaEvent(sp<Filter> filter, hidl_handle avHandle,
+        uint64_t dataId, uint64_t dataSize, jobject obj) : mFilter(filter),
+        mDataId(dataId), mDataSize(dataSize), mBuffer(nullptr),
         mDataIdRefCnt(0), mAvHandleRefCnt(0), mIonHandle(nullptr) {
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     mMediaEventObj = env->NewWeakGlobalRef(obj);
@@ -335,7 +335,8 @@
 
 void MediaEvent::finalize() {
     if (mAvHandleRefCnt == 0) {
-        mIFilter->releaseAvHandle(hidl_handle(mAvHandle), mDataIdRefCnt == 0 ? mDataId : 0);
+        mFilter->mFilterSp->releaseAvHandle(
+                hidl_handle(mAvHandle), mDataIdRefCnt == 0 ? mDataId : 0);
         native_handle_close(mAvHandle);
     }
 }
@@ -348,7 +349,47 @@
     if (mLinearBlockObj != NULL) {
         return mLinearBlockObj;
     }
-    mIonHandle = new C2HandleIon(dup(mAvHandle->data[0]), mDataLength);
+
+    int fd;
+    int numInts = 0;
+    int memIndex;
+    int dataSize;
+    if (mAvHandle->numFds == 0) {
+        if (mFilter->mAvSharedHandle == NULL) {
+            ALOGE("Shared AV memory handle is not initialized.");
+            return NULL;
+        }
+        if (mFilter->mAvSharedHandle->numFds == 0) {
+            ALOGE("Shared AV memory handle is empty.");
+            return NULL;
+        }
+        fd = mFilter->mAvSharedHandle->data[0];
+        dataSize = mFilter->mAvSharedMemSize;
+        numInts = mFilter->mAvSharedHandle->numInts;
+        if (numInts > 0) {
+            // If the first int in the shared native handle has value, use it as the index
+            memIndex = mFilter->mAvSharedHandle->data[mFilter->mAvSharedHandle->numFds];
+        }
+    } else {
+        fd = mAvHandle->data[0];
+        dataSize = mDataSize;
+        numInts = mAvHandle->numInts;
+        if (numInts > 0) {
+            // Otherwise if the first int in the av native handle returned from the filter
+            // event has value, use it as the index
+            memIndex = mAvHandle->data[mAvHandle->numFds];
+        } else {
+            if (mFilter->mAvSharedHandle != NULL) {
+                numInts = mFilter->mAvSharedHandle->numInts;
+                if (numInts > 0) {
+                    // If the first int in the shared native handle has value, use it as the index
+                    memIndex = mFilter->mAvSharedHandle->data[mFilter->mAvSharedHandle->numFds];
+                }
+            }
+        }
+    }
+
+    mIonHandle = new C2HandleIon(dup(fd), dataSize);
     std::shared_ptr<C2LinearBlock> block = _C2BlockFactory::CreateLinearBlock(mIonHandle);
     if (block != nullptr) {
         // CreateLinearBlock delete mIonHandle after it create block successfully.
@@ -357,13 +398,11 @@
         JNIEnv *env = AndroidRuntime::getJNIEnv();
         std::unique_ptr<JMediaCodecLinearBlock> context{new JMediaCodecLinearBlock};
         context->mBlock = block;
-        std::shared_ptr<C2Buffer> pC2Buffer = context->toC2Buffer(0, mDataLength);
+        std::shared_ptr<C2Buffer> pC2Buffer = context->toC2Buffer(0, dataSize);
         context->mBuffer = pC2Buffer;
         mC2Buffer = pC2Buffer;
-        if (mAvHandle->numInts > 0) {
-            // use first int in the native_handle as the index
-            int index = mAvHandle->data[mAvHandle->numFds];
-            std::shared_ptr<C2Param> c2param = std::make_shared<C2DataIdInfo>(index, mDataId);
+        if (numInts > 0) {
+            std::shared_ptr<C2Param> c2param = std::make_shared<C2DataIdInfo>(memIndex, mDataId);
             std::shared_ptr<C2Info> info(std::static_pointer_cast<C2Info>(c2param));
             pC2Buffer->setInfo(info);
         }
@@ -470,7 +509,7 @@
 
         if (mediaEvent.avMemory.getNativeHandle() != NULL || mediaEvent.avDataId != 0) {
             sp<MediaEvent> mediaEventSp =
-                           new MediaEvent(mIFilter, mediaEvent.avMemory,
+                           new MediaEvent(mFilter, mediaEvent.avMemory,
                                mediaEvent.avDataId, dataLength + offset, obj);
             mediaEventSp->mAvHandleRefCnt++;
             env->SetLongField(obj, eventContext, (jlong) mediaEventSp.get());
@@ -690,7 +729,7 @@
         }
     }
     env->CallVoidMethod(
-            mFilter,
+            mFilter->mFilterObj,
             gFields.onFilterEventID,
             array);
     return Void();
@@ -709,7 +748,7 @@
     ALOGD("FilterCallback::onFilterStatus");
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     env->CallVoidMethod(
-            mFilter,
+            mFilter->mFilterObj,
             gFields.onFilterStatusID,
             (jint)status);
     return Void();
@@ -717,17 +756,11 @@
 
 void FilterCallback::setFilter(const sp<Filter> filter) {
     ALOGD("FilterCallback::setFilter");
-    mFilter = filter->mFilterObj;
-    mIFilter = filter->mFilterSp;
+    // JNI Object
+    mFilter = filter;
 }
 
-FilterCallback::~FilterCallback() {
-    JNIEnv *env = AndroidRuntime::getJNIEnv();
-    if (mFilter != NULL) {
-        env->DeleteWeakGlobalRef(mFilter);
-        mFilter = NULL;
-    }
-}
+FilterCallback::~FilterCallback() {}
 
 /////////////// Filter ///////////////////////
 
@@ -1575,9 +1608,33 @@
     sp<Filter> filterSp = new Filter(iFilterSp, filterObj);
     filterSp->incStrong(filterObj);
     env->SetLongField(filterObj, gFields.filterContext, (jlong)filterSp.get());
-
+    filterSp->mIsMediaFilter = false;
+    filterSp->mAvSharedHandle = NULL;
     callback->setFilter(filterSp);
 
+    if (type.mainType == DemuxFilterMainType::MMTP) {
+        if (type.subType.mmtpFilterType() == DemuxMmtpFilterType::AUDIO ||
+                type.subType.mmtpFilterType() == DemuxMmtpFilterType::VIDEO) {
+            filterSp->mIsMediaFilter = true;
+        }
+    }
+
+    if (type.mainType == DemuxFilterMainType::TS) {
+        if (type.subType.tsFilterType() == DemuxTsFilterType::AUDIO ||
+                type.subType.tsFilterType() == DemuxTsFilterType::VIDEO) {
+            filterSp->mIsMediaFilter = true;
+        }
+    }
+
+    if (iFilterSp_1_1 != NULL && filterSp->mIsMediaFilter) {
+        iFilterSp_1_1->getAvSharedHandle([&](Result r, hidl_handle avMemory, uint64_t avMemSize) {
+            if (r == Result::SUCCESS) {
+                filterSp->mAvSharedHandle = native_handle_clone(avMemory.getNativeHandle());
+                filterSp->mAvSharedMemSize = avMemSize;
+            }
+        });
+    }
+
     return filterObj;
 }
 
diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h
index d7dc600..7a633f8 100644
--- a/media/jni/android_media_tv_Tuner.h
+++ b/media/jni/android_media_tv_Tuner.h
@@ -117,28 +117,6 @@
     int mFd;
 };
 
-struct MediaEvent : public RefBase {
-    MediaEvent(sp<IFilter> iFilter, hidl_handle avHandle, uint64_t dataId,
-        uint64_t dataLength, jobject obj);
-    ~MediaEvent();
-    jobject getLinearBlock();
-    uint64_t getAudioHandle();
-    void finalize();
-
-    sp<IFilter> mIFilter;
-    native_handle_t* mAvHandle;
-    uint64_t mDataId;
-    uint64_t mDataLength;
-    uint8_t* mBuffer;
-    android::Mutex mLock;
-    int mDataIdRefCnt;
-    int mAvHandleRefCnt;
-    jweak mMediaEventObj;
-    jweak mLinearBlockObj;
-    C2HandleIon* mIonHandle;
-    std::weak_ptr<C2Buffer> mC2Buffer;
-};
-
 struct Filter : public RefBase {
     Filter(sp<IFilter> sp, jobject obj);
     ~Filter();
@@ -148,6 +126,31 @@
     std::unique_ptr<MQ> mFilterMQ;
     EventFlag* mFilterMQEventFlag;
     jweak mFilterObj;
+    native_handle_t* mAvSharedHandle;
+    uint64_t mAvSharedMemSize;
+    bool mIsMediaFilter;
+};
+
+struct MediaEvent : public RefBase {
+    MediaEvent(sp<Filter> filter, hidl_handle avHandle, uint64_t dataId,
+        uint64_t dataSize, jobject obj);
+    ~MediaEvent();
+    jobject getLinearBlock();
+    uint64_t getAudioHandle();
+    void finalize();
+
+    sp<Filter> mFilter;
+    native_handle_t* mAvHandle;
+    uint64_t mDataId;
+    uint64_t mDataSize;
+    uint8_t* mBuffer;
+    android::Mutex mLock;
+    int mDataIdRefCnt;
+    int mAvHandleRefCnt;
+    jweak mMediaEventObj;
+    jweak mLinearBlockObj;
+    C2HandleIon* mIonHandle;
+    std::weak_ptr<C2Buffer> mC2Buffer;
 };
 
 struct FilterCallback : public IFilterCallback {
@@ -159,8 +162,7 @@
 
     void setFilter(const sp<Filter> filter);
 private:
-    jweak mFilter;
-    sp<IFilter> mIFilter;
+    sp<Filter> mFilter;
     jobjectArray getSectionEvent(
             jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events);
     jobjectArray getMediaEvent(