From 3e0c37b525ccb1da97113bd2247ebeae5ba6e908 Mon Sep 17 00:00:00 2001 From: shubang Date: Wed, 19 Feb 2020 19:09:10 -0800 Subject: [PATCH] Tuner JNI: FilterCallback Bug: 139308734 Test: make; acloud; Change-Id: I1f0b1b401bae833c44a37862eaa0f057d058da87 --- .../android/media/tv/tuner/filter/Filter.java | 1 + media/jni/android_media_tv_Tuner.cpp | 295 ++++++++++++++++-- media/jni/android_media_tv_Tuner.h | 19 +- 3 files changed, 295 insertions(+), 20 deletions(-) diff --git a/media/java/android/media/tv/tuner/filter/Filter.java b/media/java/android/media/tv/tuner/filter/Filter.java index cfb943b10d17b..b63c6b40db0ac 100644 --- a/media/java/android/media/tv/tuner/filter/Filter.java +++ b/media/java/android/media/tv/tuner/filter/Filter.java @@ -221,6 +221,7 @@ public class Filter implements AutoCloseable { mCallback = cb; mExecutor = executor; } + /** @hide */ public FilterCallback getCallback() { return mCallback; diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp index e68ccfaa08122..0c07c265d0dd4 100644 --- a/media/jni/android_media_tv_Tuner.cpp +++ b/media/jni/android_media_tv_Tuner.cpp @@ -34,19 +34,28 @@ using ::android::hardware::Void; using ::android::hardware::hidl_bitfield; using ::android::hardware::hidl_vec; +using ::android::hardware::tv::tuner::V1_0::AudioExtraMetaData; +using ::android::hardware::tv::tuner::V1_0::Constant; using ::android::hardware::tv::tuner::V1_0::DataFormat; using ::android::hardware::tv::tuner::V1_0::DemuxAlpFilterSettings; using ::android::hardware::tv::tuner::V1_0::DemuxAlpFilterType; using ::android::hardware::tv::tuner::V1_0::DemuxAlpLengthType; using ::android::hardware::tv::tuner::V1_0::DemuxFilterAvSettings; +using ::android::hardware::tv::tuner::V1_0::DemuxFilterDownloadEvent; using ::android::hardware::tv::tuner::V1_0::DemuxFilterDownloadSettings; +using ::android::hardware::tv::tuner::V1_0::DemuxFilterIpPayloadEvent; using ::android::hardware::tv::tuner::V1_0::DemuxFilterMainType; using ::android::hardware::tv::tuner::V1_0::DemuxFilterMediaEvent; +using ::android::hardware::tv::tuner::V1_0::DemuxFilterMmtpRecordEvent; using ::android::hardware::tv::tuner::V1_0::DemuxFilterPesDataSettings; +using ::android::hardware::tv::tuner::V1_0::DemuxFilterPesEvent; using ::android::hardware::tv::tuner::V1_0::DemuxFilterRecordSettings; using ::android::hardware::tv::tuner::V1_0::DemuxFilterSectionBits; +using ::android::hardware::tv::tuner::V1_0::DemuxFilterSectionEvent; using ::android::hardware::tv::tuner::V1_0::DemuxFilterSectionSettings; using ::android::hardware::tv::tuner::V1_0::DemuxFilterSettings; +using ::android::hardware::tv::tuner::V1_0::DemuxFilterTemiEvent; +using ::android::hardware::tv::tuner::V1_0::DemuxFilterTsRecordEvent; using ::android::hardware::tv::tuner::V1_0::DemuxIpAddress; using ::android::hardware::tv::tuner::V1_0::DemuxIpFilterSettings; using ::android::hardware::tv::tuner::V1_0::DemuxIpFilterType; @@ -132,6 +141,7 @@ struct fields_t { jmethodID dvrInitID; jmethodID onFrontendEventID; jmethodID onFilterStatusID; + jmethodID onFilterEventID; jmethodID lnbInitID; jmethodID onLnbEventID; jmethodID descramblerInitID; @@ -227,48 +237,287 @@ jobject FilterCallback::handleToLinearBlock(const native_handle_t* handle, uint3 return linearBlock; } -jobject FilterCallback::getMediaEvent(const DemuxFilterEvent::Event& event) { +jobjectArray FilterCallback::getSectionEvent( + jobjectArray& arr, const std::vector& events) { JNIEnv *env = AndroidRuntime::getJNIEnv(); - jclass clazz = env->FindClass("android/media/tv/tuner/filter/MediaEvent"); - jmethodID eventInit = env->GetMethodID(clazz, + jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/SectionEvent"); + jmethodID eventInit = env->GetMethodID(eventClazz, "", "(IIII)V"); + + for (int i = 0; i < events.size(); i++) { + auto event = events[i]; + DemuxFilterSectionEvent sectionEvent = event.section(); + + jint tableId = static_cast(sectionEvent.tableId); + jint version = static_cast(sectionEvent.version); + jint sectionNum = static_cast(sectionEvent.sectionNum); + jint dataLength = static_cast(sectionEvent.dataLength); + + jobject obj = + env->NewObject(eventClazz, eventInit, tableId, version, sectionNum, dataLength); + env->SetObjectArrayElement(arr, i, obj); + } + return arr; +} + +jobjectArray FilterCallback::getMediaEvent( + jobjectArray& arr, const std::vector& events) { + JNIEnv *env = AndroidRuntime::getJNIEnv(); + jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/MediaEvent"); + jmethodID eventInit = env->GetMethodID(eventClazz, "", "(IZJJJLandroid/media/MediaCodec$LinearBlock;" "ZJIZLandroid/media/tv/tuner/filter/AudioDescriptor;)V"); - DemuxFilterMediaEvent mediaEvent = event.media(); - uint32_t dataLength = mediaEvent.dataLength; - const native_handle_t* h = mediaEvent.avMemory.getNativeHandle(); - jobject block = handleToLinearBlock(h, dataLength); - // TODO: handle other fields + for (int i = 0; i < events.size(); i++) { + auto event = events[i]; + DemuxFilterMediaEvent mediaEvent = event.media(); - return env->NewObject(clazz, eventInit, (jint) 0, (jboolean) 0, (jlong) 0, (jlong) 0, (jlong) 0, - block, (jboolean) 0, (jlong) 0, (jint) 0, (jboolean) 0, NULL); + jobject audioDescriptor = NULL; + if (mediaEvent.extraMetaData.getDiscriminator() + == DemuxFilterMediaEvent::ExtraMetaData::hidl_discriminator::audio) { + jclass adClazz = env->FindClass("android/media/tv/tuner/filter/AudioDescriptor"); + jmethodID adInit = env->GetMethodID(adClazz, "", "(BBCBBB)V"); + + AudioExtraMetaData ad = mediaEvent.extraMetaData.audio(); + jbyte adFade = static_cast(ad.adFade); + jbyte adPan = static_cast(ad.adPan); + jchar versionTextTag = static_cast(ad.versionTextTag); + jbyte adGainCenter = static_cast(ad.adGainCenter); + jbyte adGainFront = static_cast(ad.adGainFront); + jbyte adGainSurround = static_cast(ad.adGainSurround); + + audioDescriptor = + env->NewObject(adClazz, adInit, adFade, adPan, versionTextTag, adGainCenter, + adGainFront, adGainSurround); + } + + jlong dataLength = static_cast(mediaEvent.dataLength); + const native_handle_t* h = NULL; + jobject block = NULL; + if (mediaEvent.avMemory != NULL) { + h = mediaEvent.avMemory.getNativeHandle(); + block = handleToLinearBlock(h, dataLength); + } + + jint streamId = static_cast(mediaEvent.streamId); + jboolean isPtsPresent = static_cast(mediaEvent.isPtsPresent); + jlong pts = static_cast(mediaEvent.pts); + jlong offset = static_cast(mediaEvent.offset); + jboolean isSecureMemory = static_cast(mediaEvent.isSecureMemory); + jlong avDataId = static_cast(mediaEvent.avDataId); + jint mpuSequenceNumber = static_cast(mediaEvent.mpuSequenceNumber); + jboolean isPesPrivateData = static_cast(mediaEvent.isPesPrivateData); + + jobject obj = + env->NewObject(eventClazz, eventInit, streamId, isPtsPresent, pts, dataLength, + offset, block, isSecureMemory, avDataId, mpuSequenceNumber, isPesPrivateData, + audioDescriptor); + env->SetObjectArrayElement(arr, i, obj); + } + return arr; +} + +jobjectArray FilterCallback::getPesEvent( + jobjectArray& arr, const std::vector& events) { + JNIEnv *env = AndroidRuntime::getJNIEnv(); + jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/PesEvent"); + jmethodID eventInit = env->GetMethodID(eventClazz, "", "(III)V"); + + for (int i = 0; i < events.size(); i++) { + auto event = events[i]; + DemuxFilterPesEvent pesEvent = event.pes(); + + jint streamId = static_cast(pesEvent.streamId); + jint dataLength = static_cast(pesEvent.dataLength); + jint mpuSequenceNumber = static_cast(pesEvent.mpuSequenceNumber); + + jobject obj = + env->NewObject(eventClazz, eventInit, streamId, dataLength, mpuSequenceNumber); + env->SetObjectArrayElement(arr, i, obj); + } + return arr; +} + +jobjectArray FilterCallback::getTsRecordEvent( + jobjectArray& arr, const std::vector& events) { + JNIEnv *env = AndroidRuntime::getJNIEnv(); + jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/TsRecordEvent"); + jmethodID eventInit = env->GetMethodID(eventClazz, "", "(IIIJ)V"); + + for (int i = 0; i < events.size(); i++) { + auto event = events[i]; + DemuxFilterTsRecordEvent tsRecordEvent = event.tsRecord(); + DemuxPid pid = tsRecordEvent.pid; + + jint jpid = static_cast(Constant::INVALID_TS_PID); + + if (pid.getDiscriminator() == DemuxPid::hidl_discriminator::tPid) { + jpid = static_cast(pid.tPid()); + } else if (pid.getDiscriminator() == DemuxPid::hidl_discriminator::mmtpPid) { + jpid = static_cast(pid.mmtpPid()); + } + + jint sc = 0; + + if (tsRecordEvent.scIndexMask.getDiscriminator() + == DemuxFilterTsRecordEvent::ScIndexMask::hidl_discriminator::sc) { + sc = static_cast(tsRecordEvent.scIndexMask.sc()); + } else if (tsRecordEvent.scIndexMask.getDiscriminator() + == DemuxFilterTsRecordEvent::ScIndexMask::hidl_discriminator::scHevc) { + sc = static_cast(tsRecordEvent.scIndexMask.scHevc()); + } + + jint ts = static_cast(tsRecordEvent.tsIndexMask); + + jlong byteNumber = static_cast(tsRecordEvent.byteNumber); + + jobject obj = + env->NewObject(eventClazz, eventInit, jpid, ts, sc, byteNumber); + env->SetObjectArrayElement(arr, i, obj); + } + return arr; +} + +jobjectArray FilterCallback::getMmtpRecordEvent( + jobjectArray& arr, const std::vector& events) { + JNIEnv *env = AndroidRuntime::getJNIEnv(); + jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/MmtpRecordEvent"); + jmethodID eventInit = env->GetMethodID(eventClazz, "", "(IJ)V"); + + for (int i = 0; i < events.size(); i++) { + auto event = events[i]; + DemuxFilterMmtpRecordEvent mmtpRecordEvent = event.mmtpRecord(); + + jint scHevcIndexMask = static_cast(mmtpRecordEvent.scHevcIndexMask); + jlong byteNumber = static_cast(mmtpRecordEvent.byteNumber); + + jobject obj = + env->NewObject(eventClazz, eventInit, scHevcIndexMask, byteNumber); + env->SetObjectArrayElement(arr, i, obj); + } + return arr; +} + +jobjectArray FilterCallback::getDownloadEvent( + jobjectArray& arr, const std::vector& events) { + JNIEnv *env = AndroidRuntime::getJNIEnv(); + jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/DownloadEvent"); + jmethodID eventInit = env->GetMethodID(eventClazz, "", "(IIIII)V"); + + for (int i = 0; i < events.size(); i++) { + auto event = events[i]; + DemuxFilterDownloadEvent downloadEvent = event.download(); + + jint itemId = static_cast(downloadEvent.itemId); + jint mpuSequenceNumber = static_cast(downloadEvent.mpuSequenceNumber); + jint itemFragmentIndex = static_cast(downloadEvent.itemFragmentIndex); + jint lastItemFragmentIndex = static_cast(downloadEvent.lastItemFragmentIndex); + jint dataLength = static_cast(downloadEvent.dataLength); + + jobject obj = + env->NewObject(eventClazz, eventInit, itemId, mpuSequenceNumber, itemFragmentIndex, + lastItemFragmentIndex, dataLength); + env->SetObjectArrayElement(arr, i, obj); + } + return arr; +} + +jobjectArray FilterCallback::getIpPayloadEvent( + jobjectArray& arr, const std::vector& events) { + JNIEnv *env = AndroidRuntime::getJNIEnv(); + jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/IpPayloadEvent"); + jmethodID eventInit = env->GetMethodID(eventClazz, "", "(I)V"); + + for (int i = 0; i < events.size(); i++) { + auto event = events[i]; + DemuxFilterIpPayloadEvent ipPayloadEvent = event.ipPayload(); + jint dataLength = static_cast(ipPayloadEvent.dataLength); + jobject obj = env->NewObject(eventClazz, eventInit, dataLength); + env->SetObjectArrayElement(arr, i, obj); + } + return arr; +} + +jobjectArray FilterCallback::getTemiEvent( + jobjectArray& arr, const std::vector& events) { + JNIEnv *env = AndroidRuntime::getJNIEnv(); + jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/TemiEvent"); + jmethodID eventInit = env->GetMethodID(eventClazz, "", "(JB[B)V"); + + for (int i = 0; i < events.size(); i++) { + auto event = events[i]; + DemuxFilterTemiEvent temiEvent = event.temi(); + jlong pts = static_cast(temiEvent.pts); + jbyte descrTag = static_cast(temiEvent.descrTag); + std::vector descrData = temiEvent.descrData; + + jbyteArray array = env->NewByteArray(descrData.size()); + env->SetByteArrayRegion( + array, 0, descrData.size(), reinterpret_cast(&descrData[0])); + + jobject obj = env->NewObject(eventClazz, eventInit, pts, descrTag, array); + env->SetObjectArrayElement(arr, i, obj); + } + return arr; } Return FilterCallback::onFilterEvent(const DemuxFilterEvent& filterEvent) { ALOGD("FilterCallback::onFilterEvent"); JNIEnv *env = AndroidRuntime::getJNIEnv(); - jclass clazz = env->FindClass("android/media/tv/tuner/filter/Filter"); std::vector events = filterEvent.events; jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/FilterEvent"); jobjectArray array = env->NewObjectArray(events.size(), eventClazz, NULL); - for (int i = 0; i < events.size(); i++) { - auto event = events[i]; - if (event.getDiscriminator() == DemuxFilterEvent::Event::hidl_discriminator::media) { - env->SetObjectArrayElement(array, i, getMediaEvent(event)); + if (!events.empty()) { + auto event = events[0]; + switch (event.getDiscriminator()) { + case DemuxFilterEvent::Event::hidl_discriminator::media: { + array = getMediaEvent(array, events); + break; + } + case DemuxFilterEvent::Event::hidl_discriminator::section: { + array = getSectionEvent(array, events); + break; + } + case DemuxFilterEvent::Event::hidl_discriminator::pes: { + array = getPesEvent(array, events); + break; + } + case DemuxFilterEvent::Event::hidl_discriminator::tsRecord: { + array = getTsRecordEvent(array, events); + break; + } + case DemuxFilterEvent::Event::hidl_discriminator::mmtpRecord: { + array = getMmtpRecordEvent(array, events); + break; + } + case DemuxFilterEvent::Event::hidl_discriminator::download: { + array = getDownloadEvent(array, events); + break; + } + case DemuxFilterEvent::Event::hidl_discriminator::ipPayload: { + array = getIpPayloadEvent(array, events); + break; + } + case DemuxFilterEvent::Event::hidl_discriminator::temi: { + array = getTemiEvent(array, events); + break; + } + default: { + break; + } } } env->CallVoidMethod( mFilter, - env->GetMethodID(clazz, "onFilterEvent", - "([Landroid/media/tv/tuner/filter/FilterEvent;)V"), + gFields.onFilterEventID, array); return Void(); } + Return FilterCallback::onFilterStatus(const DemuxFilterStatus status) { ALOGD("FilterCallback::onFilterStatus"); JNIEnv *env = AndroidRuntime::getJNIEnv(); @@ -287,9 +536,16 @@ void FilterCallback::setFilter(const jobject filter) { /////////////// Filter /////////////////////// -Filter::Filter(sp sp, jweak obj) : mFilterSp(sp), mFilterObj(obj) {} +Filter::Filter(sp sp, jobject obj) : mFilterSp(sp) { + JNIEnv *env = AndroidRuntime::getJNIEnv(); + mFilterObj = env->NewWeakGlobalRef(obj); +} Filter::~Filter() { + JNIEnv *env = AndroidRuntime::getJNIEnv(); + + env->DeleteWeakGlobalRef(mFilterObj); + mFilterObj = NULL; EventFlag::deleteEventFlag(&mFilterMQEventFlag); } @@ -1598,6 +1854,9 @@ static void android_media_tv_Tuner_native_init(JNIEnv *env) { env->GetMethodID(filterClazz, "", "(I)V"); gFields.onFilterStatusID = env->GetMethodID(filterClazz, "onFilterStatus", "(I)V"); + gFields.onFilterEventID = + env->GetMethodID(filterClazz, "onFilterEvent", + "([Landroid/media/tv/tuner/filter/FilterEvent;)V"); jclass timeFilterClazz = env->FindClass("android/media/tv/tuner/filter/TimeFilter"); gFields.timeFilterContext = env->GetFieldID(timeFilterClazz, "mNativeContext", "J"); diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h index b786fc4e76b79..6a67ebcd1b31a 100644 --- a/media/jni/android_media_tv_Tuner.h +++ b/media/jni/android_media_tv_Tuner.h @@ -106,7 +106,22 @@ struct FilterCallback : public IFilterCallback { jobject handleToLinearBlock(const native_handle_t* handle, uint32_t size); private: jweak mFilter; - jobject getMediaEvent(const DemuxFilterEvent::Event& event); + jobjectArray getSectionEvent( + jobjectArray& arr, const std::vector& events); + jobjectArray getMediaEvent( + jobjectArray& arr, const std::vector& events); + jobjectArray getPesEvent( + jobjectArray& arr, const std::vector& events); + jobjectArray getTsRecordEvent( + jobjectArray& arr, const std::vector& events); + jobjectArray getMmtpRecordEvent( + jobjectArray& arr, const std::vector& events); + jobjectArray getDownloadEvent( + jobjectArray& arr, const std::vector& events); + jobjectArray getIpPayloadEvent( + jobjectArray& arr, const std::vector& events); + jobjectArray getTemiEvent( + jobjectArray& arr, const std::vector& events); }; struct FrontendCallback : public IFrontendCallback { @@ -121,7 +136,7 @@ struct FrontendCallback : public IFrontendCallback { }; struct Filter : public RefBase { - Filter(sp sp, jweak obj); + Filter(sp sp, jobject obj); ~Filter(); int close(); sp getIFilter();