| /* |
| * Copyright 2019 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #define LOG_TAG "TvTuner-JNI" |
| #include <utils/Log.h> |
| |
| #include "android_media_MediaCodecLinearBlock.h" |
| #include "android_media_tv_Tuner.h" |
| #include "android_runtime/AndroidRuntime.h" |
| |
| #include <android-base/logging.h> |
| #include <media/stagefright/foundation/ADebug.h> |
| #include <nativehelper/JNIHelp.h> |
| #include <nativehelper/ScopedLocalRef.h> |
| #include <utils/NativeHandle.h> |
| |
| #pragma GCC diagnostic ignored "-Wunused-function" |
| |
| 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::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::DemuxCapabilities; |
| 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; |
| using ::android::hardware::tv::tuner::V1_0::DemuxMmtpFilterSettings; |
| using ::android::hardware::tv::tuner::V1_0::DemuxMmtpFilterType; |
| using ::android::hardware::tv::tuner::V1_0::DemuxMmtpPid; |
| using ::android::hardware::tv::tuner::V1_0::DemuxQueueNotifyBits; |
| using ::android::hardware::tv::tuner::V1_0::DemuxRecordScIndexType; |
| using ::android::hardware::tv::tuner::V1_0::DemuxScHevcIndex; |
| using ::android::hardware::tv::tuner::V1_0::DemuxScIndex; |
| using ::android::hardware::tv::tuner::V1_0::DemuxTlvFilterSettings; |
| using ::android::hardware::tv::tuner::V1_0::DemuxTlvFilterType; |
| using ::android::hardware::tv::tuner::V1_0::DemuxTpid; |
| using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterSettings; |
| using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterType; |
| using ::android::hardware::tv::tuner::V1_0::DemuxTsIndex; |
| using ::android::hardware::tv::tuner::V1_0::DvrSettings; |
| using ::android::hardware::tv::tuner::V1_0::FrontendAnalogSettings; |
| using ::android::hardware::tv::tuner::V1_0::FrontendAnalogSifStandard; |
| using ::android::hardware::tv::tuner::V1_0::FrontendAnalogType; |
| using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3Bandwidth; |
| using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3CodeRate; |
| using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3DemodOutputFormat; |
| using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3Fec; |
| using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3Modulation; |
| using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3PlpSettings; |
| using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3Settings; |
| using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3TimeInterleaveMode; |
| using ::android::hardware::tv::tuner::V1_0::FrontendAtscSettings; |
| using ::android::hardware::tv::tuner::V1_0::FrontendAtscModulation; |
| using ::android::hardware::tv::tuner::V1_0::FrontendDvbcAnnex; |
| using ::android::hardware::tv::tuner::V1_0::FrontendDvbcModulation; |
| using ::android::hardware::tv::tuner::V1_0::FrontendDvbcOuterFec; |
| using ::android::hardware::tv::tuner::V1_0::FrontendDvbcSettings; |
| using ::android::hardware::tv::tuner::V1_0::FrontendDvbcSpectralInversion; |
| using ::android::hardware::tv::tuner::V1_0::FrontendDvbsCodeRate; |
| using ::android::hardware::tv::tuner::V1_0::FrontendDvbsModulation; |
| using ::android::hardware::tv::tuner::V1_0::FrontendDvbsPilot; |
| using ::android::hardware::tv::tuner::V1_0::FrontendDvbsRolloff; |
| using ::android::hardware::tv::tuner::V1_0::FrontendDvbsSettings; |
| using ::android::hardware::tv::tuner::V1_0::FrontendDvbsStandard; |
| using ::android::hardware::tv::tuner::V1_0::FrontendDvbsVcmMode; |
| using ::android::hardware::tv::tuner::V1_0::FrontendDvbtBandwidth; |
| using ::android::hardware::tv::tuner::V1_0::FrontendDvbtCoderate; |
| using ::android::hardware::tv::tuner::V1_0::FrontendDvbtConstellation; |
| using ::android::hardware::tv::tuner::V1_0::FrontendDvbtGuardInterval; |
| using ::android::hardware::tv::tuner::V1_0::FrontendDvbtHierarchy; |
| using ::android::hardware::tv::tuner::V1_0::FrontendDvbtPlpMode; |
| using ::android::hardware::tv::tuner::V1_0::FrontendDvbtSettings; |
| using ::android::hardware::tv::tuner::V1_0::FrontendDvbtStandard; |
| using ::android::hardware::tv::tuner::V1_0::FrontendDvbtTransmissionMode; |
| using ::android::hardware::tv::tuner::V1_0::FrontendInnerFec; |
| using ::android::hardware::tv::tuner::V1_0::FrontendIsdbs3Coderate; |
| using ::android::hardware::tv::tuner::V1_0::FrontendIsdbs3Modulation; |
| using ::android::hardware::tv::tuner::V1_0::FrontendIsdbs3Rolloff; |
| using ::android::hardware::tv::tuner::V1_0::FrontendIsdbs3Settings; |
| using ::android::hardware::tv::tuner::V1_0::FrontendIsdbsCoderate; |
| using ::android::hardware::tv::tuner::V1_0::FrontendIsdbsModulation; |
| using ::android::hardware::tv::tuner::V1_0::FrontendIsdbsRolloff; |
| using ::android::hardware::tv::tuner::V1_0::FrontendIsdbsSettings; |
| using ::android::hardware::tv::tuner::V1_0::FrontendIsdbsStreamIdType; |
| using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtBandwidth; |
| using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtCoderate; |
| using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtGuardInterval; |
| using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtMode; |
| using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtModulation; |
| using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtSettings; |
| using ::android::hardware::tv::tuner::V1_0::FrontendModulationStatus; |
| using ::android::hardware::tv::tuner::V1_0::FrontendScanAtsc3PlpInfo; |
| using ::android::hardware::tv::tuner::V1_0::FrontendStatus; |
| using ::android::hardware::tv::tuner::V1_0::FrontendStatusAtsc3PlpInfo; |
| using ::android::hardware::tv::tuner::V1_0::FrontendStatusType; |
| using ::android::hardware::tv::tuner::V1_0::FrontendType; |
| using ::android::hardware::tv::tuner::V1_0::LnbPosition; |
| using ::android::hardware::tv::tuner::V1_0::LnbTone; |
| using ::android::hardware::tv::tuner::V1_0::LnbVoltage; |
| using ::android::hardware::tv::tuner::V1_0::PlaybackSettings; |
| using ::android::hardware::tv::tuner::V1_0::RecordSettings; |
| using ::android::hardware::tv::tuner::V1_1::AudioStreamType; |
| using ::android::hardware::tv::tuner::V1_1::AvStreamType; |
| using ::android::hardware::tv::tuner::V1_1::Constant; |
| using ::android::hardware::tv::tuner::V1_1::Constant64Bit; |
| using ::android::hardware::tv::tuner::V1_1::FrontendAnalogAftFlag; |
| using ::android::hardware::tv::tuner::V1_1::FrontendAnalogSettingsExt1_1; |
| using ::android::hardware::tv::tuner::V1_1::FrontendBandwidth; |
| using ::android::hardware::tv::tuner::V1_1::FrontendCableTimeInterleaveMode; |
| using ::android::hardware::tv::tuner::V1_1::FrontendDvbcBandwidth; |
| using ::android::hardware::tv::tuner::V1_1::FrontendDvbsScanType; |
| using ::android::hardware::tv::tuner::V1_1::FrontendDvbcSettingsExt1_1; |
| using ::android::hardware::tv::tuner::V1_1::FrontendDvbsSettingsExt1_1; |
| using ::android::hardware::tv::tuner::V1_1::FrontendDvbtSettingsExt1_1; |
| using ::android::hardware::tv::tuner::V1_1::FrontendDtmbBandwidth; |
| using ::android::hardware::tv::tuner::V1_1::FrontendDtmbCapabilities; |
| using ::android::hardware::tv::tuner::V1_1::FrontendDtmbCodeRate; |
| using ::android::hardware::tv::tuner::V1_1::FrontendDtmbGuardInterval; |
| using ::android::hardware::tv::tuner::V1_1::FrontendDtmbModulation; |
| using ::android::hardware::tv::tuner::V1_1::FrontendDtmbSettings; |
| using ::android::hardware::tv::tuner::V1_1::FrontendDtmbTimeInterleaveMode; |
| using ::android::hardware::tv::tuner::V1_1::FrontendDtmbTransmissionMode; |
| using ::android::hardware::tv::tuner::V1_1::FrontendGuardInterval; |
| using ::android::hardware::tv::tuner::V1_1::FrontendInterleaveMode; |
| using ::android::hardware::tv::tuner::V1_1::FrontendModulation; |
| using ::android::hardware::tv::tuner::V1_1::FrontendRollOff; |
| using ::android::hardware::tv::tuner::V1_1::FrontendSpectralInversion; |
| using ::android::hardware::tv::tuner::V1_1::FrontendStatusExt1_1; |
| using ::android::hardware::tv::tuner::V1_1::FrontendStatusTypeExt1_1; |
| using ::android::hardware::tv::tuner::V1_1::FrontendTransmissionMode; |
| using ::android::hardware::tv::tuner::V1_1::VideoStreamType; |
| |
| struct fields_t { |
| jfieldID tunerContext; |
| jfieldID lnbContext; |
| jfieldID filterContext; |
| jfieldID timeFilterContext; |
| jfieldID descramblerContext; |
| jfieldID dvrRecorderContext; |
| jfieldID dvrPlaybackContext; |
| jfieldID mediaEventContext; |
| jmethodID frontendInitID; |
| jmethodID filterInitID; |
| jmethodID timeFilterInitID; |
| jmethodID dvrRecorderInitID; |
| jmethodID dvrPlaybackInitID; |
| jmethodID onFrontendEventID; |
| jmethodID onFilterStatusID; |
| jmethodID onFilterEventID; |
| jmethodID lnbInitID; |
| jmethodID onLnbEventID; |
| jmethodID onLnbDiseqcMessageID; |
| jmethodID onDvrRecordStatusID; |
| jmethodID onDvrPlaybackStatusID; |
| jmethodID descramblerInitID; |
| jmethodID linearBlockInitID; |
| jmethodID linearBlockSetInternalStateID; |
| }; |
| |
| static fields_t gFields; |
| |
| |
| static int IP_V4_LENGTH = 4; |
| static int IP_V6_LENGTH = 16; |
| |
| void DestroyCallback(const C2Buffer * buf, void *arg) { |
| android::sp<android::MediaEvent> event = (android::MediaEvent *)arg; |
| android::Mutex::Autolock autoLock(event->mLock); |
| if (event->mLinearBlockObj != NULL) { |
| JNIEnv *env = android::AndroidRuntime::getJNIEnv(); |
| env->DeleteWeakGlobalRef(event->mLinearBlockObj); |
| event->mLinearBlockObj = NULL; |
| } |
| |
| event->mAvHandleRefCnt--; |
| event->finalize(); |
| event->decStrong(buf); |
| } |
| |
| namespace android { |
| |
| /////////////// LnbClientCallbackImpl /////////////////////// |
| |
| void LnbClientCallbackImpl::onEvent(const LnbEventType lnbEventType) { |
| ALOGD("LnbClientCallbackImpl::onEvent, type=%d", lnbEventType); |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| jobject lnb(env->NewLocalRef(mLnbObj)); |
| if (!env->IsSameObject(lnb, nullptr)) { |
| env->CallVoidMethod( |
| lnb, |
| gFields.onLnbEventID, |
| (jint)lnbEventType); |
| } else { |
| ALOGE("LnbClientCallbackImpl::onEvent:" |
| "Lnb object has been freed. Ignoring callback."); |
| } |
| } |
| |
| void LnbClientCallbackImpl::onDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage) { |
| ALOGD("LnbClientCallbackImpl::onDiseqcMessage"); |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| jobject lnb(env->NewLocalRef(mLnbObj)); |
| if (!env->IsSameObject(lnb, nullptr)) { |
| jbyteArray array = env->NewByteArray(diseqcMessage.size()); |
| env->SetByteArrayRegion( |
| array, 0, diseqcMessage.size(), reinterpret_cast<jbyte*>(diseqcMessage[0])); |
| env->CallVoidMethod( |
| lnb, |
| gFields.onLnbDiseqcMessageID, |
| array); |
| } else { |
| ALOGE("LnbClientCallbackImpl::onDiseqcMessage:" |
| "Lnb object has been freed. Ignoring callback."); |
| } |
| } |
| |
| void LnbClientCallbackImpl::setLnb(jweak lnbObj) { |
| ALOGD("LnbClientCallbackImpl::setLnb"); |
| mLnbObj = lnbObj; |
| } |
| |
| LnbClientCallbackImpl::~LnbClientCallbackImpl() { |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| if (mLnbObj != NULL) { |
| env->DeleteWeakGlobalRef(mLnbObj); |
| mLnbObj = NULL; |
| } |
| } |
| |
| /////////////// DvrClientCallbackImpl /////////////////////// |
| |
| void DvrClientCallbackImpl::onRecordStatus(RecordStatus status) { |
| ALOGD("DvrClientCallbackImpl::onRecordStatus"); |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| jobject dvr(env->NewLocalRef(mDvrObj)); |
| if (!env->IsSameObject(dvr, nullptr)) { |
| env->CallVoidMethod( |
| dvr, |
| gFields.onDvrRecordStatusID, |
| (jint) status); |
| } else { |
| ALOGE("DvrClientCallbackImpl::onRecordStatus:" |
| "Dvr object has been freed. Ignoring callback."); |
| } |
| } |
| |
| void DvrClientCallbackImpl::onPlaybackStatus(PlaybackStatus status) { |
| ALOGD("DvrClientCallbackImpl::onPlaybackStatus"); |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| jobject dvr(env->NewLocalRef(mDvrObj)); |
| if (!env->IsSameObject(dvr, nullptr)) { |
| env->CallVoidMethod( |
| dvr, |
| gFields.onDvrPlaybackStatusID, |
| (jint) status); |
| } else { |
| ALOGE("DvrClientCallbackImpl::onPlaybackStatus:" |
| "Dvr object has been freed. Ignoring callback."); |
| } |
| } |
| |
| void DvrClientCallbackImpl::setDvr(jweak dvrObj) { |
| ALOGD("DvrClientCallbackImpl::setDvr"); |
| mDvrObj = dvrObj; |
| } |
| |
| DvrClientCallbackImpl::~DvrClientCallbackImpl() { |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| if (mDvrObj != NULL) { |
| env->DeleteWeakGlobalRef(mDvrObj); |
| mDvrObj = NULL; |
| } |
| } |
| |
| /////////////// C2DataIdInfo /////////////////////// |
| |
| C2DataIdInfo::C2DataIdInfo(uint32_t index, uint64_t value) : C2Param(kParamSize, index) { |
| CHECK(isGlobal()); |
| CHECK_EQ(C2Param::INFO, kind()); |
| mInfo = StubInfo(value); |
| memcpy(static_cast<C2Param *>(this) + 1, static_cast<C2Param *>(&mInfo) + 1, |
| kParamSize - sizeof(C2Param)); |
| } |
| |
| /////////////// MediaEvent /////////////////////// |
| |
| MediaEvent::MediaEvent(sp<FilterClient> filterClient, hidl_handle avHandle, |
| uint64_t dataId, uint64_t dataSize, jobject obj) : mFilterClient(filterClient), |
| mDataId(dataId), mDataSize(dataSize), mBuffer(nullptr), |
| mDataIdRefCnt(0), mAvHandleRefCnt(0), mIonHandle(nullptr) { |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| mMediaEventObj = env->NewWeakGlobalRef(obj); |
| mAvHandle = native_handle_clone(avHandle.getNativeHandle()); |
| mLinearBlockObj = NULL; |
| } |
| |
| MediaEvent::~MediaEvent() { |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| env->DeleteWeakGlobalRef(mMediaEventObj); |
| mMediaEventObj = NULL; |
| native_handle_delete(mAvHandle); |
| if (mIonHandle != NULL) { |
| delete mIonHandle; |
| } |
| std::shared_ptr<C2Buffer> pC2Buffer = mC2Buffer.lock(); |
| if (pC2Buffer != NULL) { |
| pC2Buffer->unregisterOnDestroyNotify(&DestroyCallback, this); |
| } |
| mFilterClient = NULL; |
| } |
| |
| void MediaEvent::finalize() { |
| if (mAvHandleRefCnt == 0 && mFilterClient != NULL) { |
| mFilterClient->releaseAvHandle( |
| mAvHandle, mDataIdRefCnt == 0 ? mDataId : 0); |
| native_handle_close(mAvHandle); |
| } |
| } |
| |
| jobject MediaEvent::getLinearBlock() { |
| ALOGD("MediaEvent::getLinearBlock"); |
| if (mAvHandle == NULL) { |
| return NULL; |
| } |
| if (mLinearBlockObj != NULL) { |
| return mLinearBlockObj; |
| } |
| |
| int fd; |
| int numInts = 0; |
| int memIndex; |
| int dataSize; |
| SharedHandleInfo info = mFilterClient->getAvSharedHandleInfo(); |
| native_handle_t* avSharedHandle = info.sharedHandle; |
| uint64_t avSharedMemSize = info.size; |
| |
| if (mAvHandle->numFds == 0) { |
| if (avSharedHandle == NULL) { |
| ALOGE("Shared AV memory handle is not initialized."); |
| return NULL; |
| } |
| if (avSharedHandle->numFds == 0) { |
| ALOGE("Shared AV memory handle is empty."); |
| return NULL; |
| } |
| fd = avSharedHandle->data[0]; |
| dataSize = avSharedMemSize; |
| numInts = avSharedHandle->numInts; |
| if (numInts > 0) { |
| // If the first int in the shared native handle has value, use it as the index |
| memIndex = avSharedHandle->data[avSharedHandle->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 (avSharedHandle != NULL) { |
| numInts = avSharedHandle->numInts; |
| if (numInts > 0) { |
| // If the first int in the shared native handle has value, use it as the index |
| memIndex = avSharedHandle->data[avSharedHandle->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. |
| // ToDo: coordinate who is response to delete mIonHandle |
| mIonHandle = NULL; |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| std::unique_ptr<JMediaCodecLinearBlock> context{new JMediaCodecLinearBlock}; |
| context->mBlock = block; |
| std::shared_ptr<C2Buffer> pC2Buffer = context->toC2Buffer(0, dataSize); |
| context->mBuffer = pC2Buffer; |
| mC2Buffer = pC2Buffer; |
| 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); |
| } |
| pC2Buffer->registerOnDestroyNotify(&DestroyCallback, this); |
| incStrong(pC2Buffer.get()); |
| jobject linearBlock = |
| env->NewObject( |
| env->FindClass("android/media/MediaCodec$LinearBlock"), |
| gFields.linearBlockInitID); |
| env->CallVoidMethod( |
| linearBlock, |
| gFields.linearBlockSetInternalStateID, |
| (jlong)context.release(), |
| true); |
| mLinearBlockObj = env->NewWeakGlobalRef(linearBlock); |
| mAvHandleRefCnt++; |
| return linearBlock; |
| } else { |
| native_handle_close(const_cast<native_handle_t*>( |
| reinterpret_cast<const native_handle_t*>(mIonHandle))); |
| native_handle_delete(const_cast<native_handle_t*>( |
| reinterpret_cast<const native_handle_t*>(mIonHandle))); |
| mIonHandle = NULL; |
| return NULL; |
| } |
| } |
| |
| uint64_t MediaEvent::getAudioHandle() { |
| mDataIdRefCnt++; |
| return mDataId; |
| } |
| |
| /////////////// FilterClientCallbackImpl /////////////////////// |
| |
| jobjectArray FilterClientCallbackImpl::getSectionEvent( |
| jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) { |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/SectionEvent"); |
| jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(IIII)V"); |
| |
| for (int i = 0; i < events.size(); i++) { |
| auto event = events[i]; |
| DemuxFilterSectionEvent sectionEvent = event.section(); |
| |
| jint tableId = static_cast<jint>(sectionEvent.tableId); |
| jint version = static_cast<jint>(sectionEvent.version); |
| jint sectionNum = static_cast<jint>(sectionEvent.sectionNum); |
| jint dataLength = static_cast<jint>(sectionEvent.dataLength); |
| |
| jobject obj = |
| env->NewObject(eventClazz, eventInit, tableId, version, sectionNum, dataLength); |
| env->SetObjectArrayElement(arr, i, obj); |
| } |
| return arr; |
| } |
| |
| jobjectArray FilterClientCallbackImpl::getMediaEvent( |
| jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) { |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/MediaEvent"); |
| jmethodID eventInit = env->GetMethodID(eventClazz, |
| "<init>", |
| "(IZJJJLandroid/media/MediaCodec$LinearBlock;" |
| "ZJIZLandroid/media/tv/tuner/filter/AudioDescriptor;)V"); |
| jfieldID eventContext = env->GetFieldID(eventClazz, "mNativeContext", "J"); |
| |
| for (int i = 0; i < events.size(); i++) { |
| auto event = events[i]; |
| DemuxFilterMediaEvent mediaEvent = event.media(); |
| |
| 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, "<init>", "(BBCBBB)V"); |
| |
| AudioExtraMetaData ad = mediaEvent.extraMetaData.audio(); |
| jbyte adFade = static_cast<jbyte>(ad.adFade); |
| jbyte adPan = static_cast<jbyte>(ad.adPan); |
| jchar versionTextTag = static_cast<jchar>(ad.versionTextTag); |
| jbyte adGainCenter = static_cast<jbyte>(ad.adGainCenter); |
| jbyte adGainFront = static_cast<jbyte>(ad.adGainFront); |
| jbyte adGainSurround = static_cast<jbyte>(ad.adGainSurround); |
| |
| audioDescriptor = |
| env->NewObject(adClazz, adInit, adFade, adPan, versionTextTag, adGainCenter, |
| adGainFront, adGainSurround); |
| } |
| |
| jlong dataLength = static_cast<jlong>(mediaEvent.dataLength); |
| |
| jint streamId = static_cast<jint>(mediaEvent.streamId); |
| jboolean isPtsPresent = static_cast<jboolean>(mediaEvent.isPtsPresent); |
| jlong pts = static_cast<jlong>(mediaEvent.pts); |
| jlong offset = static_cast<jlong>(mediaEvent.offset); |
| jboolean isSecureMemory = static_cast<jboolean>(mediaEvent.isSecureMemory); |
| jlong avDataId = static_cast<jlong>(mediaEvent.avDataId); |
| jint mpuSequenceNumber = static_cast<jint>(mediaEvent.mpuSequenceNumber); |
| jboolean isPesPrivateData = static_cast<jboolean>(mediaEvent.isPesPrivateData); |
| |
| jobject obj = |
| env->NewObject(eventClazz, eventInit, streamId, isPtsPresent, pts, dataLength, |
| offset, NULL, isSecureMemory, avDataId, mpuSequenceNumber, isPesPrivateData, |
| audioDescriptor); |
| |
| if (mediaEvent.avMemory.getNativeHandle() != NULL || mediaEvent.avDataId != 0) { |
| sp<MediaEvent> mediaEventSp = |
| new MediaEvent(mFilterClient, mediaEvent.avMemory, |
| mediaEvent.avDataId, dataLength + offset, obj); |
| mediaEventSp->mAvHandleRefCnt++; |
| env->SetLongField(obj, eventContext, (jlong) mediaEventSp.get()); |
| mediaEventSp->incStrong(obj); |
| } |
| |
| env->SetObjectArrayElement(arr, i, obj); |
| } |
| return arr; |
| } |
| |
| jobjectArray FilterClientCallbackImpl::getPesEvent( |
| jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) { |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/PesEvent"); |
| jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(III)V"); |
| |
| for (int i = 0; i < events.size(); i++) { |
| auto event = events[i]; |
| DemuxFilterPesEvent pesEvent = event.pes(); |
| |
| jint streamId = static_cast<jint>(pesEvent.streamId); |
| jint dataLength = static_cast<jint>(pesEvent.dataLength); |
| jint mpuSequenceNumber = static_cast<jint>(pesEvent.mpuSequenceNumber); |
| |
| jobject obj = |
| env->NewObject(eventClazz, eventInit, streamId, dataLength, mpuSequenceNumber); |
| env->SetObjectArrayElement(arr, i, obj); |
| } |
| return arr; |
| } |
| |
| jobjectArray FilterClientCallbackImpl::getTsRecordEvent( |
| jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events, |
| const std::vector<DemuxFilterEventExt::Event>& eventsExt) { |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/TsRecordEvent"); |
| jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(IIIJJI)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<jint>(Constant::INVALID_TS_PID); |
| |
| if (pid.getDiscriminator() == DemuxPid::hidl_discriminator::tPid) { |
| jpid = static_cast<jint>(pid.tPid()); |
| } else if (pid.getDiscriminator() == DemuxPid::hidl_discriminator::mmtpPid) { |
| jpid = static_cast<jint>(pid.mmtpPid()); |
| } |
| |
| jint sc = 0; |
| |
| if (tsRecordEvent.scIndexMask.getDiscriminator() |
| == DemuxFilterTsRecordEvent::ScIndexMask::hidl_discriminator::sc) { |
| sc = static_cast<jint>(tsRecordEvent.scIndexMask.sc()); |
| } else if (tsRecordEvent.scIndexMask.getDiscriminator() |
| == DemuxFilterTsRecordEvent::ScIndexMask::hidl_discriminator::scHevc) { |
| sc = static_cast<jint>(tsRecordEvent.scIndexMask.scHevc()); |
| } |
| |
| jint ts = static_cast<jint>(tsRecordEvent.tsIndexMask); |
| |
| jlong byteNumber = static_cast<jlong>(tsRecordEvent.byteNumber); |
| |
| jlong pts; |
| jlong firstMbInSlice; |
| if (eventsExt.size() > i && eventsExt[i].getDiscriminator() == |
| DemuxFilterEventExt::Event::hidl_discriminator::tsRecord) { |
| pts = static_cast<jlong>(eventsExt[i].tsRecord().pts); |
| firstMbInSlice = static_cast<jint>(eventsExt[i].tsRecord().firstMbInSlice); |
| } else { |
| pts = static_cast<jlong>(Constant64Bit::INVALID_PRESENTATION_TIME_STAMP); |
| firstMbInSlice = static_cast<jint>(Constant::INVALID_FIRST_MACROBLOCK_IN_SLICE); |
| } |
| |
| jobject obj = |
| env->NewObject(eventClazz, eventInit, jpid, ts, sc, byteNumber, |
| pts, firstMbInSlice); |
| env->SetObjectArrayElement(arr, i, obj); |
| } |
| return arr; |
| } |
| |
| jobjectArray FilterClientCallbackImpl::getMmtpRecordEvent( |
| jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events, |
| const std::vector<DemuxFilterEventExt::Event>& eventsExt) { |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/MmtpRecordEvent"); |
| jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(IJIJII)V"); |
| |
| for (int i = 0; i < events.size(); i++) { |
| auto event = events[i]; |
| |
| DemuxFilterMmtpRecordEvent mmtpRecordEvent = event.mmtpRecord(); |
| |
| jint scHevcIndexMask = static_cast<jint>(mmtpRecordEvent.scHevcIndexMask); |
| jlong byteNumber = static_cast<jlong>(mmtpRecordEvent.byteNumber); |
| |
| jint mpuSequenceNumber; |
| jlong pts; |
| jlong firstMbInSlice; |
| jlong tsIndexMask; |
| |
| if (eventsExt.size() > i && eventsExt[i].getDiscriminator() == |
| DemuxFilterEventExt::Event::hidl_discriminator::mmtpRecord) { |
| mpuSequenceNumber = static_cast<jint>(eventsExt[i].mmtpRecord().mpuSequenceNumber); |
| pts = static_cast<jlong>(eventsExt[i].mmtpRecord().pts); |
| firstMbInSlice = static_cast<jint>(eventsExt[i].mmtpRecord().firstMbInSlice); |
| tsIndexMask = static_cast<jint>(eventsExt[i].mmtpRecord().tsIndexMask); |
| } else { |
| mpuSequenceNumber = |
| static_cast<jint>(Constant::INVALID_MMTP_RECORD_EVENT_MPT_SEQUENCE_NUM); |
| pts = static_cast<jlong>(Constant64Bit::INVALID_PRESENTATION_TIME_STAMP); |
| firstMbInSlice = static_cast<jint>(Constant::INVALID_FIRST_MACROBLOCK_IN_SLICE); |
| tsIndexMask = 0; |
| } |
| |
| jobject obj = |
| env->NewObject(eventClazz, eventInit, scHevcIndexMask, byteNumber, |
| mpuSequenceNumber, pts, firstMbInSlice, tsIndexMask); |
| env->SetObjectArrayElement(arr, i, obj); |
| } |
| return arr; |
| } |
| |
| jobjectArray FilterClientCallbackImpl::getDownloadEvent( |
| jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) { |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/DownloadEvent"); |
| jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(IIIII)V"); |
| |
| for (int i = 0; i < events.size(); i++) { |
| auto event = events[i]; |
| DemuxFilterDownloadEvent downloadEvent = event.download(); |
| |
| jint itemId = static_cast<jint>(downloadEvent.itemId); |
| jint mpuSequenceNumber = static_cast<jint>(downloadEvent.mpuSequenceNumber); |
| jint itemFragmentIndex = static_cast<jint>(downloadEvent.itemFragmentIndex); |
| jint lastItemFragmentIndex = static_cast<jint>(downloadEvent.lastItemFragmentIndex); |
| jint dataLength = static_cast<jint>(downloadEvent.dataLength); |
| |
| jobject obj = |
| env->NewObject(eventClazz, eventInit, itemId, mpuSequenceNumber, itemFragmentIndex, |
| lastItemFragmentIndex, dataLength); |
| env->SetObjectArrayElement(arr, i, obj); |
| } |
| return arr; |
| } |
| |
| jobjectArray FilterClientCallbackImpl::getIpPayloadEvent( |
| jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) { |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/IpPayloadEvent"); |
| jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(I)V"); |
| |
| for (int i = 0; i < events.size(); i++) { |
| auto event = events[i]; |
| DemuxFilterIpPayloadEvent ipPayloadEvent = event.ipPayload(); |
| jint dataLength = static_cast<jint>(ipPayloadEvent.dataLength); |
| jobject obj = env->NewObject(eventClazz, eventInit, dataLength); |
| env->SetObjectArrayElement(arr, i, obj); |
| } |
| return arr; |
| } |
| |
| jobjectArray FilterClientCallbackImpl::getTemiEvent( |
| jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) { |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/TemiEvent"); |
| jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(JB[B)V"); |
| |
| for (int i = 0; i < events.size(); i++) { |
| auto event = events[i]; |
| DemuxFilterTemiEvent temiEvent = event.temi(); |
| jlong pts = static_cast<jlong>(temiEvent.pts); |
| jbyte descrTag = static_cast<jbyte>(temiEvent.descrTag); |
| std::vector<uint8_t> descrData = temiEvent.descrData; |
| |
| jbyteArray array = env->NewByteArray(descrData.size()); |
| env->SetByteArrayRegion( |
| array, 0, descrData.size(), reinterpret_cast<jbyte*>(&descrData[0])); |
| |
| jobject obj = env->NewObject(eventClazz, eventInit, pts, descrTag, array); |
| env->SetObjectArrayElement(arr, i, obj); |
| } |
| return arr; |
| } |
| |
| jobjectArray FilterClientCallbackImpl::getScramblingStatusEvent( |
| jobjectArray& arr, const std::vector<DemuxFilterEventExt::Event>& eventsExt) { |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/ScramblingStatusEvent"); |
| jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(I)V"); |
| |
| auto scramblingStatus = eventsExt[0].monitorEvent().scramblingStatus(); |
| jobject obj = env->NewObject(eventClazz, eventInit, static_cast<jint>(scramblingStatus)); |
| env->SetObjectArrayElement(arr, 0, obj); |
| return arr; |
| } |
| |
| jobjectArray FilterClientCallbackImpl::getIpCidChangeEvent( |
| jobjectArray& arr, const std::vector<DemuxFilterEventExt::Event>& eventsExt) { |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/IpCidChangeEvent"); |
| jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(I)V"); |
| |
| auto cid = eventsExt[0].monitorEvent().cid(); |
| jobject obj = env->NewObject(eventClazz, eventInit, static_cast<jint>(cid)); |
| env->SetObjectArrayElement(arr, 0, obj); |
| return arr; |
| } |
| |
| jobjectArray FilterClientCallbackImpl::getRestartEvent( |
| jobjectArray& arr, const std::vector<DemuxFilterEventExt::Event>& eventsExt) { |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/RestartEvent"); |
| jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(I)V"); |
| |
| auto startId = eventsExt[0].startId(); |
| jobject obj = env->NewObject(eventClazz, eventInit, static_cast<jint>(startId)); |
| env->SetObjectArrayElement(arr, 0, obj); |
| return arr; |
| } |
| |
| void FilterClientCallbackImpl::onFilterEvent_1_1(const DemuxFilterEvent& filterEvent, |
| const DemuxFilterEventExt& filterEventExt) { |
| ALOGD("FilterClientCallbackImpl::onFilterEvent_1_1"); |
| |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| jobjectArray array; |
| |
| std::vector<DemuxFilterEvent::Event> events = filterEvent.events; |
| std::vector<DemuxFilterEventExt::Event> eventsExt = filterEventExt.events; |
| jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/FilterEvent"); |
| |
| if (events.empty() && !eventsExt.empty()) { |
| // Monitor event should be sent with one DemuxFilterMonitorEvent in DemuxFilterEventExt. |
| array = env->NewObjectArray(1, eventClazz, NULL); |
| auto eventExt = eventsExt[0]; |
| switch (eventExt.getDiscriminator()) { |
| case DemuxFilterEventExt::Event::hidl_discriminator::monitorEvent: { |
| switch (eventExt.monitorEvent().getDiscriminator()) { |
| case DemuxFilterMonitorEvent::hidl_discriminator::scramblingStatus: { |
| array = getScramblingStatusEvent(array, eventsExt); |
| break; |
| } |
| case DemuxFilterMonitorEvent::hidl_discriminator::cid: { |
| array = getIpCidChangeEvent(array, eventsExt); |
| break; |
| } |
| default: { |
| break; |
| } |
| } |
| break; |
| } |
| case DemuxFilterEventExt::Event::hidl_discriminator::startId: { |
| array = getRestartEvent(array, eventsExt); |
| break; |
| } |
| default: { |
| break; |
| } |
| } |
| } |
| |
| if (!events.empty()) { |
| array = env->NewObjectArray(events.size(), eventClazz, NULL); |
| 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, eventsExt); |
| break; |
| } |
| case DemuxFilterEvent::Event::hidl_discriminator::mmtpRecord: { |
| array = getMmtpRecordEvent(array, events, eventsExt); |
| 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; |
| } |
| } |
| } |
| jobject filter(env->NewLocalRef(mFilterObj)); |
| if (!env->IsSameObject(filter, nullptr)) { |
| env->CallVoidMethod( |
| filter, |
| gFields.onFilterEventID, |
| array); |
| } else { |
| ALOGE("FilterClientCallbackImpl::onFilterEvent_1_1:" |
| "Filter object has been freed. Ignoring callback."); |
| } |
| } |
| |
| void FilterClientCallbackImpl::onFilterEvent(const DemuxFilterEvent& filterEvent) { |
| ALOGD("FilterClientCallbackImpl::onFilterEvent"); |
| std::vector<DemuxFilterEventExt::Event> emptyEventsExt; |
| DemuxFilterEventExt emptyFilterEventExt { |
| .events = emptyEventsExt, |
| }; |
| return onFilterEvent_1_1(filterEvent, emptyFilterEventExt); |
| } |
| |
| void FilterClientCallbackImpl::onFilterStatus(const DemuxFilterStatus status) { |
| ALOGD("FilterClientCallbackImpl::onFilterStatus"); |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| jobject filter(env->NewLocalRef(mFilterObj)); |
| if (!env->IsSameObject(filter, nullptr)) { |
| env->CallVoidMethod( |
| filter, |
| gFields.onFilterStatusID, |
| (jint)status); |
| } else { |
| ALOGE("FilterClientCallbackImpl::onFilterStatus:" |
| "Filter object has been freed. Ignoring callback."); |
| } |
| } |
| |
| void FilterClientCallbackImpl::setFilter(jweak filterObj, sp<FilterClient> filterClient) { |
| ALOGD("FilterClientCallbackImpl::setFilter"); |
| // Java Object |
| mFilterObj = filterObj; |
| mFilterClient = filterClient; |
| } |
| |
| FilterClientCallbackImpl::~FilterClientCallbackImpl() { |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| if (mFilterObj != NULL) { |
| env->DeleteWeakGlobalRef(mFilterObj); |
| mFilterObj = NULL; |
| } |
| mFilterClient = NULL; |
| } |
| |
| /////////////// FrontendClientCallbackImpl /////////////////////// |
| |
| FrontendClientCallbackImpl::FrontendClientCallbackImpl(jweak tunerObj) : mObject(tunerObj) {} |
| |
| void FrontendClientCallbackImpl::onEvent(FrontendEventType frontendEventType) { |
| ALOGD("FrontendClientCallbackImpl::onEvent, type=%d", frontendEventType); |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| jobject frontend(env->NewLocalRef(mObject)); |
| if (!env->IsSameObject(frontend, nullptr)) { |
| env->CallVoidMethod( |
| frontend, |
| gFields.onFrontendEventID, |
| (jint)frontendEventType); |
| } else { |
| ALOGE("FrontendClientCallbackImpl::onEvent:" |
| "Frontend object has been freed. Ignoring callback."); |
| } |
| } |
| |
| void FrontendClientCallbackImpl::onScanMessage( |
| FrontendScanMessageType type, const FrontendScanMessage& message) { |
| ALOGD("FrontendClientCallbackImpl::onScanMessage, type=%d", type); |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| jclass clazz = env->FindClass("android/media/tv/tuner/Tuner"); |
| jobject frontend(env->NewLocalRef(mObject)); |
| if (env->IsSameObject(frontend, nullptr)) { |
| ALOGE("FrontendClientCallbackImpl::onScanMessage:" |
| "Frontend object has been freed. Ignoring callback."); |
| return; |
| } |
| switch(type) { |
| case FrontendScanMessageType::LOCKED: { |
| if (message.isLocked()) { |
| env->CallVoidMethod( |
| frontend, |
| env->GetMethodID(clazz, "onLocked", "()V")); |
| } |
| break; |
| } |
| case FrontendScanMessageType::END: { |
| if (message.isEnd()) { |
| env->CallVoidMethod( |
| frontend, |
| env->GetMethodID(clazz, "onScanStopped", "()V")); |
| } |
| break; |
| } |
| case FrontendScanMessageType::PROGRESS_PERCENT: { |
| env->CallVoidMethod( |
| frontend, |
| env->GetMethodID(clazz, "onProgress", "(I)V"), |
| (jint) message.progressPercent()); |
| break; |
| } |
| case FrontendScanMessageType::FREQUENCY: { |
| std::vector<uint32_t> v = message.frequencies(); |
| jintArray freqs = env->NewIntArray(v.size()); |
| env->SetIntArrayRegion(freqs, 0, v.size(), reinterpret_cast<jint*>(&v[0])); |
| |
| env->CallVoidMethod( |
| frontend, |
| env->GetMethodID(clazz, "onFrequenciesReport", "([I)V"), |
| freqs); |
| break; |
| } |
| case FrontendScanMessageType::SYMBOL_RATE: { |
| std::vector<uint32_t> v = message.symbolRates(); |
| jintArray symbolRates = env->NewIntArray(v.size()); |
| env->SetIntArrayRegion(symbolRates, 0, v.size(), reinterpret_cast<jint*>(&v[0])); |
| |
| env->CallVoidMethod( |
| frontend, |
| env->GetMethodID(clazz, "onSymbolRates", "([I)V"), |
| symbolRates); |
| break; |
| } |
| case FrontendScanMessageType::HIERARCHY: { |
| env->CallVoidMethod( |
| frontend, |
| env->GetMethodID(clazz, "onHierarchy", "(I)V"), |
| (jint) message.hierarchy()); |
| break; |
| } |
| case FrontendScanMessageType::ANALOG_TYPE: { |
| env->CallVoidMethod( |
| frontend, |
| env->GetMethodID(clazz, "onSignalType", "(I)V"), |
| (jint) message.analogType()); |
| break; |
| } |
| case FrontendScanMessageType::PLP_IDS: { |
| std::vector<uint8_t> v = message.plpIds(); |
| std::vector<jint> jintV(v.begin(), v.end()); |
| jintArray plpIds = env->NewIntArray(v.size()); |
| env->SetIntArrayRegion(plpIds, 0, jintV.size(), &jintV[0]); |
| |
| env->CallVoidMethod( |
| frontend, |
| env->GetMethodID(clazz, "onPlpIds", "([I)V"), |
| plpIds); |
| break; |
| } |
| case FrontendScanMessageType::GROUP_IDS: { |
| std::vector<uint8_t> v = message.groupIds(); |
| std::vector<jint> jintV(v.begin(), v.end()); |
| jintArray groupIds = env->NewIntArray(v.size()); |
| env->SetIntArrayRegion(groupIds, 0, jintV.size(), &jintV[0]); |
| |
| env->CallVoidMethod( |
| frontend, |
| env->GetMethodID(clazz, "onGroupIds", "([I)V"), |
| groupIds); |
| break; |
| } |
| case FrontendScanMessageType::INPUT_STREAM_IDS: { |
| std::vector<uint16_t> v = message.inputStreamIds(); |
| std::vector<jint> jintV(v.begin(), v.end()); |
| jintArray streamIds = env->NewIntArray(v.size()); |
| env->SetIntArrayRegion(streamIds, 0, jintV.size(), &jintV[0]); |
| |
| env->CallVoidMethod( |
| frontend, |
| env->GetMethodID(clazz, "onInputStreamIds", "([I)V"), |
| streamIds); |
| break; |
| } |
| case FrontendScanMessageType::STANDARD: { |
| FrontendScanMessage::Standard std = message.std(); |
| jint standard; |
| if (std.getDiscriminator() == FrontendScanMessage::Standard::hidl_discriminator::sStd) { |
| standard = (jint) std.sStd(); |
| env->CallVoidMethod( |
| frontend, |
| env->GetMethodID(clazz, "onDvbsStandard", "(I)V"), |
| standard); |
| } else if (std.getDiscriminator() == |
| FrontendScanMessage::Standard::hidl_discriminator::tStd) { |
| standard = (jint) std.tStd(); |
| env->CallVoidMethod( |
| frontend, |
| env->GetMethodID(clazz, "onDvbtStandard", "(I)V"), |
| standard); |
| } else if (std.getDiscriminator() == |
| FrontendScanMessage::Standard::hidl_discriminator::sifStd) { |
| standard = (jint) std.sifStd(); |
| env->CallVoidMethod( |
| frontend, |
| env->GetMethodID(clazz, "onAnalogSifStandard", "(I)V"), |
| standard); |
| } |
| break; |
| } |
| case FrontendScanMessageType::ATSC3_PLP_INFO: { |
| jclass plpClazz = env->FindClass("android/media/tv/tuner/frontend/Atsc3PlpInfo"); |
| jmethodID init = env->GetMethodID(plpClazz, "<init>", "(IZ)V"); |
| std::vector<FrontendScanAtsc3PlpInfo> plpInfos = message.atsc3PlpInfos(); |
| jobjectArray array = env->NewObjectArray(plpInfos.size(), plpClazz, NULL); |
| |
| for (int i = 0; i < plpInfos.size(); i++) { |
| auto info = plpInfos[i]; |
| jint plpId = (jint) info.plpId; |
| jboolean lls = (jboolean) info.bLlsFlag; |
| |
| jobject obj = env->NewObject(plpClazz, init, plpId, lls); |
| env->SetObjectArrayElement(array, i, obj); |
| } |
| env->CallVoidMethod( |
| frontend, |
| env->GetMethodID(clazz, "onAtsc3PlpInfos", |
| "([Landroid/media/tv/tuner/frontend/Atsc3PlpInfo;)V"), |
| array); |
| break; |
| } |
| } |
| } |
| |
| void FrontendClientCallbackImpl::onScanMessageExt1_1(FrontendScanMessageTypeExt1_1 type, |
| const FrontendScanMessageExt1_1& message) { |
| ALOGD("FrontendClientCallbackImpl::onScanMessageExt1_1, type=%d", type); |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| jclass clazz = env->FindClass("android/media/tv/tuner/Tuner"); |
| jobject frontend(env->NewLocalRef(mObject)); |
| if (env->IsSameObject(frontend, nullptr)) { |
| ALOGE("FrontendClientCallbackImpl::onScanMessageExt1_1:" |
| "Frontend object has been freed. Ignoring callback."); |
| return; |
| } |
| switch(type) { |
| case FrontendScanMessageTypeExt1_1::MODULATION: { |
| jint modulation = -1; |
| switch (message.modulation().getDiscriminator()) { |
| case FrontendModulation::hidl_discriminator::dvbc: { |
| modulation = (jint) message.modulation().dvbc(); |
| break; |
| } |
| case FrontendModulation::hidl_discriminator::dvbt: { |
| modulation = (jint) message.modulation().dvbt(); |
| break; |
| } |
| case FrontendModulation::hidl_discriminator::dvbs: { |
| modulation = (jint) message.modulation().dvbs(); |
| break; |
| } |
| case FrontendModulation::hidl_discriminator::isdbs: { |
| modulation = (jint) message.modulation().isdbs(); |
| break; |
| } |
| case FrontendModulation::hidl_discriminator::isdbs3: { |
| modulation = (jint) message.modulation().isdbs3(); |
| break; |
| } |
| case FrontendModulation::hidl_discriminator::isdbt: { |
| modulation = (jint) message.modulation().isdbt(); |
| break; |
| } |
| case FrontendModulation::hidl_discriminator::atsc: { |
| modulation = (jint) message.modulation().atsc(); |
| break; |
| } |
| case FrontendModulation::hidl_discriminator::atsc3: { |
| modulation = (jint) message.modulation().atsc3(); |
| break; |
| } |
| case FrontendModulation::hidl_discriminator::dtmb: { |
| modulation = (jint) message.modulation().dtmb(); |
| break; |
| } |
| default: { |
| break; |
| } |
| } |
| if (modulation > 0) { |
| env->CallVoidMethod( |
| frontend, |
| env->GetMethodID(clazz, "onModulationReported", "(I)V"), |
| modulation); |
| } |
| break; |
| } |
| case FrontendScanMessageTypeExt1_1::HIGH_PRIORITY: { |
| bool isHighPriority = message.isHighPriority(); |
| env->CallVoidMethod( |
| frontend, |
| env->GetMethodID(clazz, "onPriorityReported", "(Z)V"), |
| isHighPriority); |
| break; |
| } |
| case FrontendScanMessageTypeExt1_1::DVBC_ANNEX: { |
| jint dvbcAnnex = (jint) message.annex(); |
| env->CallVoidMethod( |
| frontend, |
| env->GetMethodID(clazz, "onDvbcAnnexReported", "(I)V"), |
| dvbcAnnex); |
| break; |
| } |
| default: |
| break; |
| } |
| } |
| |
| FrontendClientCallbackImpl::~FrontendClientCallbackImpl() { |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| if (mObject != NULL) { |
| env->DeleteWeakGlobalRef(mObject); |
| mObject = NULL; |
| } |
| } |
| |
| /////////////// Tuner /////////////////////// |
| |
| sp<TunerClient> JTuner::mTunerClient; |
| |
| JTuner::JTuner(JNIEnv *env, jobject thiz) |
| : mClass(NULL) { |
| jclass clazz = env->GetObjectClass(thiz); |
| CHECK(clazz != NULL); |
| |
| mClass = (jclass)env->NewGlobalRef(clazz); |
| mObject = env->NewWeakGlobalRef(thiz); |
| if (mTunerClient == NULL) { |
| mTunerClient = new TunerClient(); |
| } |
| } |
| |
| JTuner::~JTuner() { |
| if (mFeClient != NULL) { |
| mFeClient->close(); |
| } |
| if (mDemuxClient != NULL) { |
| mDemuxClient->close(); |
| } |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| |
| env->DeleteWeakGlobalRef(mObject); |
| env->DeleteGlobalRef(mClass); |
| mTunerClient = NULL; |
| mFeClient = NULL; |
| mDemuxClient = NULL; |
| mClass = NULL; |
| mObject = NULL; |
| } |
| |
| jint JTuner::getTunerVersion() { |
| ALOGD("JTuner::getTunerVersion()"); |
| return (jint) mTunerClient->getHalTunerVersion(); |
| } |
| |
| jobject JTuner::getFrontendIds() { |
| ALOGD("JTuner::getFrontendIds()"); |
| vector<FrontendId> ids = mTunerClient->getFrontendIds(); |
| if (ids.size() == 0) { |
| ALOGW("Frontend isn't available"); |
| return NULL; |
| } |
| |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| jclass arrayListClazz = env->FindClass("java/util/ArrayList"); |
| jmethodID arrayListAdd = env->GetMethodID(arrayListClazz, "add", "(Ljava/lang/Object;)Z"); |
| jobject obj = env->NewObject(arrayListClazz, env->GetMethodID(arrayListClazz, "<init>", "()V")); |
| |
| jclass integerClazz = env->FindClass("java/lang/Integer"); |
| jmethodID intInit = env->GetMethodID(integerClazz, "<init>", "(I)V"); |
| |
| for (int i=0; i < ids.size(); i++) { |
| jobject idObj = env->NewObject(integerClazz, intInit, ids[i]); |
| env->CallBooleanMethod(obj, arrayListAdd, idObj); |
| } |
| return obj; |
| } |
| |
| jobject JTuner::openFrontendByHandle(int feHandle) { |
| // TODO: Handle reopening frontend with different handle |
| sp<FrontendClient> feClient = mTunerClient->openFrontend(feHandle); |
| if (feClient == NULL) { |
| ALOGE("Failed to open frontend"); |
| return NULL; |
| } |
| mFeClient = feClient; |
| |
| mFeId = mFeClient->getId(); |
| if (mDemuxClient != NULL) { |
| mDemuxClient->setFrontendDataSource(mFeClient); |
| } |
| |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| jobject tuner(env->NewLocalRef(mObject)); |
| if (env->IsSameObject(tuner, nullptr)) { |
| ALOGE("openFrontendByHandle" |
| "Tuner object has been freed. Failed to open frontend."); |
| return NULL; |
| } |
| |
| sp<FrontendClientCallbackImpl> feClientCb = new FrontendClientCallbackImpl(mObject); |
| mFeClient->setCallback(feClientCb); |
| // TODO: add more fields to frontend |
| return env->NewObject( |
| env->FindClass("android/media/tv/tuner/Tuner$Frontend"), |
| gFields.frontendInitID, |
| tuner, |
| (jint) mFeId); |
| } |
| |
| jobject JTuner::getAnalogFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) { |
| jclass clazz = env->FindClass("android/media/tv/tuner/frontend/AnalogFrontendCapabilities"); |
| jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(II)V"); |
| |
| jint typeCap = caps.analogCaps().typeCap; |
| jint sifStandardCap = caps.analogCaps().sifStandardCap; |
| return env->NewObject(clazz, capsInit, typeCap, sifStandardCap); |
| } |
| |
| jobject JTuner::getAtsc3FrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) { |
| jclass clazz = env->FindClass("android/media/tv/tuner/frontend/Atsc3FrontendCapabilities"); |
| jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(IIIIII)V"); |
| |
| jint bandwidthCap = caps.atsc3Caps().bandwidthCap; |
| jint modulationCap = caps.atsc3Caps().modulationCap; |
| jint timeInterleaveModeCap = caps.atsc3Caps().timeInterleaveModeCap; |
| jint codeRateCap = caps.atsc3Caps().codeRateCap; |
| jint fecCap = caps.atsc3Caps().fecCap; |
| jint demodOutputFormatCap = caps.atsc3Caps().demodOutputFormatCap; |
| |
| return env->NewObject(clazz, capsInit, bandwidthCap, modulationCap, timeInterleaveModeCap, |
| codeRateCap, fecCap, demodOutputFormatCap); |
| } |
| |
| jobject JTuner::getAtscFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) { |
| jclass clazz = env->FindClass("android/media/tv/tuner/frontend/AtscFrontendCapabilities"); |
| jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(I)V"); |
| |
| jint modulationCap = caps.atscCaps().modulationCap; |
| |
| return env->NewObject(clazz, capsInit, modulationCap); |
| } |
| |
| jobject JTuner::getDvbcFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) { |
| jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbcFrontendCapabilities"); |
| jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(IJI)V"); |
| |
| jint modulationCap = caps.dvbcCaps().modulationCap; |
| jlong fecCap = caps.dvbcCaps().fecCap; |
| jint annexCap = caps.dvbcCaps().annexCap; |
| |
| return env->NewObject(clazz, capsInit, modulationCap, fecCap, annexCap); |
| } |
| |
| jobject JTuner::getDvbsFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) { |
| jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbsFrontendCapabilities"); |
| jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(IJI)V"); |
| |
| jint modulationCap = caps.dvbsCaps().modulationCap; |
| jlong innerfecCap = caps.dvbsCaps().innerfecCap; |
| jint standard = caps.dvbsCaps().standard; |
| |
| return env->NewObject(clazz, capsInit, modulationCap, innerfecCap, standard); |
| } |
| |
| jobject JTuner::getDvbtFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) { |
| jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbtFrontendCapabilities"); |
| jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(IIIIIIZZ)V"); |
| |
| jint transmissionModeCap = caps.dvbtCaps().transmissionModeCap; |
| jint bandwidthCap = caps.dvbtCaps().bandwidthCap; |
| jint constellationCap = caps.dvbtCaps().constellationCap; |
| jint coderateCap = caps.dvbtCaps().coderateCap; |
| jint hierarchyCap = caps.dvbtCaps().hierarchyCap; |
| jint guardIntervalCap = caps.dvbtCaps().guardIntervalCap; |
| jboolean isT2Supported = caps.dvbtCaps().isT2Supported; |
| jboolean isMisoSupported = caps.dvbtCaps().isMisoSupported; |
| |
| return env->NewObject(clazz, capsInit, transmissionModeCap, bandwidthCap, constellationCap, |
| coderateCap, hierarchyCap, guardIntervalCap, isT2Supported, isMisoSupported); |
| } |
| |
| jobject JTuner::getIsdbs3FrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) { |
| jclass clazz = env->FindClass("android/media/tv/tuner/frontend/Isdbs3FrontendCapabilities"); |
| jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(II)V"); |
| |
| jint modulationCap = caps.isdbs3Caps().modulationCap; |
| jint coderateCap = caps.isdbs3Caps().coderateCap; |
| |
| return env->NewObject(clazz, capsInit, modulationCap, coderateCap); |
| } |
| |
| jobject JTuner::getIsdbsFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) { |
| jclass clazz = env->FindClass("android/media/tv/tuner/frontend/IsdbsFrontendCapabilities"); |
| jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(II)V"); |
| |
| jint modulationCap = caps.isdbsCaps().modulationCap; |
| jint coderateCap = caps.isdbsCaps().coderateCap; |
| |
| return env->NewObject(clazz, capsInit, modulationCap, coderateCap); |
| } |
| |
| jobject JTuner::getIsdbtFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) { |
| jclass clazz = env->FindClass("android/media/tv/tuner/frontend/IsdbtFrontendCapabilities"); |
| jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(IIIII)V"); |
| |
| jint modeCap = caps.isdbtCaps().modeCap; |
| jint bandwidthCap = caps.isdbtCaps().bandwidthCap; |
| jint modulationCap = caps.isdbtCaps().modulationCap; |
| jint coderateCap = caps.isdbtCaps().coderateCap; |
| jint guardIntervalCap = caps.isdbtCaps().guardIntervalCap; |
| |
| return env->NewObject(clazz, capsInit, modeCap, bandwidthCap, modulationCap, coderateCap, |
| guardIntervalCap); |
| } |
| |
| jobject JTuner::getDtmbFrontendCaps(JNIEnv *env, int id) { |
| jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DtmbFrontendCapabilities"); |
| jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(IIIIII)V"); |
| |
| shared_ptr<FrontendDtmbCapabilities> dtmbCaps = mTunerClient->getFrontendDtmbCapabilities(id); |
| if (dtmbCaps == NULL) { |
| return NULL; |
| } |
| |
| jint modulationCap = dtmbCaps->modulationCap; |
| jint transmissionModeCap = dtmbCaps->transmissionModeCap; |
| jint guardIntervalCap = dtmbCaps->guardIntervalCap; |
| jint interleaveModeCap = dtmbCaps->interleaveModeCap; |
| jint codeRateCap = dtmbCaps->codeRateCap; |
| jint bandwidthCap = dtmbCaps->bandwidthCap; |
| |
| return env->NewObject(clazz, capsInit, modulationCap, transmissionModeCap, guardIntervalCap, |
| interleaveModeCap, codeRateCap, bandwidthCap); |
| } |
| |
| jobject JTuner::getFrontendInfo(int id) { |
| shared_ptr<FrontendInfo> feInfo; |
| feInfo = mTunerClient->getFrontendInfo(id); |
| if (feInfo == NULL) { |
| return NULL; |
| } |
| |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| jclass clazz = env->FindClass("android/media/tv/tuner/frontend/FrontendInfo"); |
| jmethodID infoInit = env->GetMethodID(clazz, "<init>", |
| "(IIIIIIII[ILandroid/media/tv/tuner/frontend/FrontendCapabilities;)V"); |
| |
| jint type = (jint) feInfo->type; |
| jint minFrequency = feInfo->minFrequency; |
| jint maxFrequency = feInfo->maxFrequency; |
| jint minSymbolRate = feInfo->minSymbolRate; |
| jint maxSymbolRate = feInfo->maxSymbolRate; |
| jint acquireRange = feInfo->acquireRange; |
| jint exclusiveGroupId = feInfo->exclusiveGroupId; |
| jintArray statusCaps = env->NewIntArray(feInfo->statusCaps.size()); |
| env->SetIntArrayRegion( |
| statusCaps, 0, feInfo->statusCaps.size(), |
| reinterpret_cast<jint*>(&feInfo->statusCaps[0])); |
| FrontendInfo::FrontendCapabilities caps = feInfo->frontendCaps; |
| |
| jobject jcaps = NULL; |
| |
| if (feInfo->type == static_cast<FrontendType>( |
| ::android::hardware::tv::tuner::V1_1::FrontendType::DTMB)) { |
| jcaps = getDtmbFrontendCaps(env, id); |
| } |
| |
| switch(feInfo->type) { |
| case FrontendType::ANALOG: |
| if (FrontendInfo::FrontendCapabilities::hidl_discriminator::analogCaps |
| == caps.getDiscriminator()) { |
| jcaps = getAnalogFrontendCaps(env, caps); |
| } |
| break; |
| case FrontendType::ATSC3: |
| if (FrontendInfo::FrontendCapabilities::hidl_discriminator::atsc3Caps |
| == caps.getDiscriminator()) { |
| jcaps = getAtsc3FrontendCaps(env, caps); |
| } |
| break; |
| case FrontendType::ATSC: |
| if (FrontendInfo::FrontendCapabilities::hidl_discriminator::atscCaps |
| == caps.getDiscriminator()) { |
| jcaps = getAtscFrontendCaps(env, caps); |
| } |
| break; |
| case FrontendType::DVBC: |
| if (FrontendInfo::FrontendCapabilities::hidl_discriminator::dvbcCaps |
| == caps.getDiscriminator()) { |
| jcaps = getDvbcFrontendCaps(env, caps); |
| } |
| break; |
| case FrontendType::DVBS: |
| if (FrontendInfo::FrontendCapabilities::hidl_discriminator::dvbsCaps |
| == caps.getDiscriminator()) { |
| jcaps = getDvbsFrontendCaps(env, caps); |
| } |
| break; |
| case FrontendType::DVBT: |
| if (FrontendInfo::FrontendCapabilities::hidl_discriminator::dvbtCaps |
| == caps.getDiscriminator()) { |
| jcaps = getDvbtFrontendCaps(env, caps); |
| } |
| break; |
| case FrontendType::ISDBS: |
| if (FrontendInfo::FrontendCapabilities::hidl_discriminator::isdbsCaps |
| == caps.getDiscriminator()) { |
| jcaps = getIsdbsFrontendCaps(env, caps); |
| } |
| break; |
| case FrontendType::ISDBS3: |
| if (FrontendInfo::FrontendCapabilities::hidl_discriminator::isdbs3Caps |
| == caps.getDiscriminator()) { |
| jcaps = getIsdbs3FrontendCaps(env, caps); |
| } |
| break; |
| case FrontendType::ISDBT: |
| if (FrontendInfo::FrontendCapabilities::hidl_discriminator::isdbtCaps |
| == caps.getDiscriminator()) { |
| jcaps = getIsdbtFrontendCaps(env, caps); |
| } |
| break; |
| default: |
| break; |
| } |
| |
| return env->NewObject( |
| clazz, infoInit, (jint) id, type, minFrequency, maxFrequency, minSymbolRate, |
| maxSymbolRate, acquireRange, exclusiveGroupId, statusCaps, jcaps); |
| } |
| |
| jobject JTuner::openLnbByHandle(int handle) { |
| if (mTunerClient == NULL) { |
| return NULL; |
| } |
| |
| sp<LnbClient> lnbClient; |
| sp<LnbClientCallbackImpl> callback = new LnbClientCallbackImpl(); |
| lnbClient = mTunerClient->openLnb(handle); |
| if (lnbClient == NULL) { |
| ALOGD("Failed to open lnb, handle = %d", handle); |
| return NULL; |
| } |
| |
| if (lnbClient->setCallback(callback) != Result::SUCCESS) { |
| ALOGD("Failed to set lnb callback"); |
| return NULL; |
| } |
| |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| jobject lnbObj = env->NewObject( |
| env->FindClass("android/media/tv/tuner/Lnb"), |
| gFields.lnbInitID); |
| |
| lnbClient->incStrong(lnbObj); |
| env->SetLongField(lnbObj, gFields.lnbContext, (jlong)lnbClient.get()); |
| callback->setLnb(env->NewWeakGlobalRef(lnbObj)); |
| |
| return lnbObj; |
| } |
| |
| jobject JTuner::openLnbByName(jstring name) { |
| if (mTunerClient == NULL) { |
| return NULL; |
| } |
| |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| std::string lnbName(env->GetStringUTFChars(name, nullptr)); |
| sp<LnbClient> lnbClient; |
| sp<LnbClientCallbackImpl> callback = new LnbClientCallbackImpl(); |
| lnbClient = mTunerClient->openLnbByName(lnbName); |
| if (lnbClient == NULL) { |
| ALOGD("Failed to open lnb by name, name = %s", lnbName.c_str()); |
| return NULL; |
| } |
| |
| if (lnbClient->setCallback(callback) != Result::SUCCESS) { |
| ALOGD("Failed to set lnb callback"); |
| return NULL; |
| } |
| |
| jobject lnbObj = env->NewObject( |
| env->FindClass("android/media/tv/tuner/Lnb"), |
| gFields.lnbInitID); |
| |
| lnbClient->incStrong(lnbObj); |
| env->SetLongField(lnbObj, gFields.lnbContext, (jlong)lnbClient.get()); |
| callback->setLnb(env->NewWeakGlobalRef(lnbObj)); |
| |
| return lnbObj; |
| } |
| |
| int JTuner::tune(const FrontendSettings& settings, const FrontendSettingsExt1_1& settingsExt1_1) { |
| if (mFeClient == nullptr) { |
| ALOGE("frontend is not initialized"); |
| return (int)Result::INVALID_STATE; |
| } |
| return (int) mFeClient->tune(settings, settingsExt1_1); |
| } |
| |
| int JTuner::stopTune() { |
| if (mFeClient == nullptr) { |
| ALOGE("frontend is not initialized"); |
| return (int)Result::INVALID_STATE; |
| } |
| return (int) mFeClient->stopTune(); |
| } |
| |
| int JTuner::scan(const FrontendSettings& settings, FrontendScanType scanType, |
| const FrontendSettingsExt1_1& settingsExt1_1) { |
| if (mFeClient == NULL) { |
| ALOGE("frontend client is not initialized"); |
| return (int)Result::INVALID_STATE; |
| } |
| Result result = mFeClient->scan(settings, scanType, settingsExt1_1); |
| return (int)result; |
| } |
| |
| int JTuner::stopScan() { |
| if (mFeClient == NULL) { |
| ALOGE("frontend client is not initialized"); |
| return (int)Result::INVALID_STATE; |
| } |
| Result result = mFeClient->stopScan(); |
| return (int)result; |
| } |
| |
| int JTuner::setLnb(sp<LnbClient> lnbClient) { |
| if (mFeClient == NULL) { |
| ALOGE("frontend client is not initialized"); |
| return (int)Result::INVALID_STATE; |
| } |
| if (lnbClient == NULL) { |
| ALOGE("lnb is not initialized"); |
| return (int)Result::INVALID_STATE; |
| } |
| Result result = mFeClient->setLnb(lnbClient); |
| return (int)result; |
| } |
| |
| int JTuner::setLna(bool enable) { |
| if (mFeClient == NULL) { |
| ALOGE("frontend client is not initialized"); |
| return (int)Result::INVALID_STATE; |
| } |
| Result result = mFeClient->setLna(enable); |
| return (int)result; |
| } |
| |
| Result JTuner::openDemux(int handle) { |
| if (mTunerClient == nullptr) { |
| return Result::NOT_INITIALIZED; |
| } |
| |
| if (mDemuxClient == nullptr) { |
| mDemuxClient = mTunerClient->openDemux(handle); |
| if (mDemuxClient == NULL) { |
| ALOGE("Failed to open demux"); |
| return Result::UNKNOWN_ERROR; |
| } |
| if (mFeClient != NULL) { |
| mDemuxClient->setFrontendDataSource(mFeClient); |
| } |
| } |
| |
| return Result::SUCCESS; |
| } |
| |
| jint JTuner::close() { |
| Result res = Result::SUCCESS; |
| |
| if (mFeClient != NULL) { |
| res = mFeClient->close(); |
| if (res != Result::SUCCESS) { |
| return (jint) res; |
| } |
| mFeClient = NULL; |
| } |
| if (mDemuxClient != NULL) { |
| res = mDemuxClient->close(); |
| if (res != Result::SUCCESS) { |
| return (jint) res; |
| } |
| mDemuxClient = NULL; |
| } |
| return (jint) res; |
| } |
| |
| jobject JTuner::getAvSyncHwId(sp<FilterClient> filterClient) { |
| if (mDemuxClient == NULL) { |
| return NULL; |
| } |
| |
| int avSyncHwId = mDemuxClient->getAvSyncHwId(filterClient); |
| if (avSyncHwId >= 0) { |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| jclass integerClazz = env->FindClass("java/lang/Integer"); |
| jmethodID intInit = env->GetMethodID(integerClazz, "<init>", "(I)V"); |
| return env->NewObject(integerClazz, intInit, avSyncHwId); |
| } |
| return NULL; |
| } |
| |
| jobject JTuner::getAvSyncTime(jint id) { |
| if (mDemuxClient == NULL) { |
| return NULL; |
| } |
| long time = mDemuxClient->getAvSyncTime((int)id); |
| if (time >= 0) { |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| jclass longClazz = env->FindClass("java/lang/Long"); |
| jmethodID longInit = env->GetMethodID(longClazz, "<init>", "(J)V"); |
| return env->NewObject(longClazz, longInit, static_cast<jlong>(time)); |
| } |
| return NULL; |
| } |
| |
| int JTuner::connectCiCam(jint id) { |
| if (mDemuxClient == NULL) { |
| return (int)Result::NOT_INITIALIZED; |
| } |
| Result r = mDemuxClient->connectCiCam((int)id); |
| return (int) r; |
| } |
| |
| int JTuner::linkCiCam(int id) { |
| if (mFeClient == NULL) { |
| ALOGE("frontend client is not initialized"); |
| return (int)Constant::INVALID_LTS_ID; |
| } |
| return mFeClient->linkCiCamToFrontend(id); |
| } |
| |
| int JTuner::disconnectCiCam() { |
| if (mDemuxClient == NULL) { |
| return (int)Result::NOT_INITIALIZED; |
| } |
| Result r = mDemuxClient->disconnectCiCam(); |
| return (int) r; |
| } |
| |
| |
| int JTuner::unlinkCiCam(int id) { |
| if (mFeClient == NULL) { |
| ALOGE("frontend client is not initialized"); |
| return (int)Result::INVALID_STATE; |
| } |
| |
| Result r = mFeClient->unlinkCiCamToFrontend(id); |
| |
| return (int) r; |
| } |
| |
| jobject JTuner::openDescrambler() { |
| ALOGD("JTuner::openDescrambler"); |
| if (mTunerClient == nullptr || mDemuxClient == nullptr) { |
| return NULL; |
| } |
| sp<DescramblerClient> descramblerClient = mTunerClient->openDescrambler(0/*unused*/); |
| |
| if (descramblerClient == NULL) { |
| ALOGD("Failed to open descrambler"); |
| return NULL; |
| } |
| |
| descramblerClient->setDemuxSource(mDemuxClient); |
| |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| jobject descramblerObj = |
| env->NewObject( |
| env->FindClass("android/media/tv/tuner/Descrambler"), |
| gFields.descramblerInitID); |
| |
| descramblerClient->incStrong(descramblerObj); |
| env->SetLongField(descramblerObj, gFields.descramblerContext, (jlong)descramblerClient.get()); |
| |
| return descramblerObj; |
| } |
| |
| jobject JTuner::openFilter(DemuxFilterType type, int bufferSize) { |
| if (mDemuxClient == NULL) { |
| return NULL; |
| } |
| |
| sp<FilterClient> filterClient; |
| sp<FilterClientCallbackImpl> callback = new FilterClientCallbackImpl(); |
| filterClient = mDemuxClient->openFilter(type, bufferSize, callback); |
| if (filterClient == NULL) { |
| ALOGD("Failed to open filter, type = %d", type.mainType); |
| return NULL; |
| } |
| uint64_t fId; |
| Result res = filterClient->getId64Bit(fId); |
| if (res != Result::SUCCESS) { |
| uint32_t id; |
| filterClient->getId(id); |
| fId = static_cast<uint64_t>(id); |
| } |
| |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| jobject filterObj = |
| env->NewObject( |
| env->FindClass("android/media/tv/tuner/filter/Filter"), |
| gFields.filterInitID, |
| (jlong) fId); |
| |
| filterClient->incStrong(filterObj); |
| env->SetLongField(filterObj, gFields.filterContext, (jlong)filterClient.get()); |
| callback->setFilter(env->NewWeakGlobalRef(filterObj), filterClient); |
| |
| return filterObj; |
| } |
| |
| jobject JTuner::openTimeFilter() { |
| if (mDemuxClient == NULL) { |
| return NULL; |
| } |
| |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| jobject timeFilterObj = |
| env->NewObject( |
| env->FindClass("android/media/tv/tuner/filter/TimeFilter"), |
| gFields.timeFilterInitID); |
| sp<TimeFilterClient> timeFilterClient = mDemuxClient->openTimeFilter(); |
| if (timeFilterClient == NULL) { |
| ALOGD("Failed to open time filter."); |
| return NULL; |
| } |
| timeFilterClient->incStrong(timeFilterObj); |
| env->SetLongField(timeFilterObj, gFields.timeFilterContext, (jlong)timeFilterClient.get()); |
| |
| return timeFilterObj; |
| } |
| |
| jobject JTuner::openDvr(DvrType type, jlong bufferSize) { |
| ALOGD("JTuner::openDvr"); |
| if (mDemuxClient == NULL) { |
| return NULL; |
| } |
| sp<DvrClient> dvrClient; |
| sp<DvrClientCallbackImpl> callback = new DvrClientCallbackImpl(); |
| dvrClient = mDemuxClient->openDvr(type, (int) bufferSize, callback); |
| |
| if (dvrClient == NULL) { |
| return NULL; |
| } |
| |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| jobject dvrObj; |
| if (type == DvrType::RECORD) { |
| dvrObj = |
| env->NewObject( |
| env->FindClass("android/media/tv/tuner/dvr/DvrRecorder"), |
| gFields.dvrRecorderInitID); |
| dvrClient->incStrong(dvrObj); |
| env->SetLongField(dvrObj, gFields.dvrRecorderContext, (jlong)dvrClient.get()); |
| } else { |
| dvrObj = |
| env->NewObject( |
| env->FindClass("android/media/tv/tuner/dvr/DvrPlayback"), |
| gFields.dvrPlaybackInitID); |
| dvrClient->incStrong(dvrObj); |
| env->SetLongField(dvrObj, gFields.dvrPlaybackContext, (jlong)dvrClient.get()); |
| } |
| |
| callback->setDvr(env->NewWeakGlobalRef(dvrObj)); |
| |
| return dvrObj; |
| } |
| |
| jobject JTuner::getDemuxCaps() { |
| if (mTunerClient == NULL) { |
| return NULL; |
| } |
| |
| shared_ptr<DemuxCapabilities> caps; |
| caps = mTunerClient->getDemuxCaps(); |
| if (caps == NULL) { |
| return NULL; |
| } |
| |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| jclass clazz = env->FindClass("android/media/tv/tuner/DemuxCapabilities"); |
| jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(IIIIIIIIIJI[IZ)V"); |
| |
| jint numDemux = caps->numDemux; |
| jint numRecord = caps->numRecord; |
| jint numPlayback = caps->numPlayback; |
| jint numTsFilter = caps->numTsFilter; |
| jint numSectionFilter = caps->numSectionFilter; |
| jint numAudioFilter = caps->numAudioFilter; |
| jint numVideoFilter = caps->numVideoFilter; |
| jint numPesFilter = caps->numPesFilter; |
| jint numPcrFilter = caps->numPcrFilter; |
| jlong numBytesInSectionFilter = caps->numBytesInSectionFilter; |
| jint filterCaps = static_cast<jint>(caps->filterCaps); |
| jboolean bTimeFilter = caps->bTimeFilter; |
| |
| jintArray linkCaps = env->NewIntArray(caps->linkCaps.size()); |
| env->SetIntArrayRegion( |
| linkCaps, 0, caps->linkCaps.size(), reinterpret_cast<jint*>(&caps->linkCaps[0])); |
| |
| return env->NewObject(clazz, capsInit, numDemux, numRecord, numPlayback, numTsFilter, |
| numSectionFilter, numAudioFilter, numVideoFilter, numPesFilter, numPcrFilter, |
| numBytesInSectionFilter, filterCaps, linkCaps, bTimeFilter); |
| } |
| |
| jobject JTuner::getFrontendStatus(jintArray types) { |
| if (mFeClient == NULL) { |
| return NULL; |
| } |
| JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| jsize size = env->GetArrayLength(types); |
| jint intTypes[size]; |
| env->GetIntArrayRegion(types, 0, size, intTypes); |
| std::vector<FrontendStatusType> v; |
| std::vector<FrontendStatusTypeExt1_1> v_1_1; |
| for (int i = 0; i < size; i++) { |
| if (isV1_1ExtendedStatusType(intTypes[i])) { |
| v_1_1.push_back(static_cast<FrontendStatusTypeExt1_1>(intTypes[i])); |
| } else { |
| v.push_back(static_cast<FrontendStatusType>(intTypes[i])); |
| } |
| } |
| |
| hidl_vec<FrontendStatus> status = mFeClient->getStatus(v); |
| hidl_vec<FrontendStatusExt1_1> status_1_1 = mFeClient->getStatusExtended_1_1(v_1_1); |
| |
| jclass clazz = env->FindClass("android/media/tv/tuner/frontend/FrontendStatus"); |
| jmethodID init = env->GetMethodID(clazz, "<init>", "()V"); |
| jobject statusObj = env->NewObject(clazz, init); |
| |
| jclass intClazz = env->FindClass("java/lang/Integer"); |
| jmethodID initInt = env->GetMethodID(intClazz, "<init>", "(I)V"); |
| jclass booleanClazz = env->FindClass("java/lang/Boolean"); |
| jmethodID initBoolean = env->GetMethodID(booleanClazz, "<init>", "(Z)V"); |
| |
| for (auto s : status) { |
| switch(s.getDiscriminator()) { |
| case FrontendStatus::hidl_discriminator::isDemodLocked: { |
| jfieldID field = env->GetFieldID(clazz, "mIsDemodLocked", "Ljava/lang/Boolean;"); |
| jobject newBooleanObj = env->NewObject( |
| booleanClazz, initBoolean, static_cast<jboolean>(s.isDemodLocked())); |
| env->SetObjectField(statusObj, field, newBooleanObj); |
| break; |
| } |
| case FrontendStatus::hidl_discriminator::snr: { |
| jfieldID field = env->GetFieldID(clazz, "mSnr", "Ljava/lang/Integer;"); |
| jobject newIntegerObj = env->NewObject( |
| intClazz, initInt, static_cast<jint>(s.snr())); |
| env->SetObjectField(statusObj, field, newIntegerObj); |
| break; |
| } |
| case FrontendStatus::hidl_discriminator::ber: { |
| jfieldID field = env->GetFieldID(clazz, "mBer", "Ljava/lang/Integer;"); |
| jobject newIntegerObj = env->NewObject( |
| intClazz, initInt, static_cast<jint>(s.ber())); |
| env->SetObjectField(statusObj, field, newIntegerObj); |
| break; |
| } |
| case FrontendStatus::hidl_discriminator::per: { |
| jfieldID field = env->GetFieldID(clazz, "mPer", "Ljava/lang/Integer;"); |
| jobject newIntegerObj = env->NewObject( |
| intClazz, initInt, static_cast<jint>(s.per())); |
| env->SetObjectField(statusObj, field, newIntegerObj); |
| break; |
| } |
| case FrontendStatus::hidl_discriminator::preBer: { |
| jfieldID field = env->GetFieldID(clazz, "mPerBer", "Ljava/lang/Integer;"); |
| jobject newIntegerObj = env->NewObject( |
| intClazz, initInt, static_cast<jint>(s.preBer())); |
| env->SetObjectField(statusObj, field, newIntegerObj); |
| break; |
| } |
| case FrontendStatus::hidl_discriminator::signalQuality: { |
| jfieldID field = env->GetFieldID(clazz, "mSignalQuality", "Ljava/lang/Integer;"); |
| jobject newIntegerObj = env->NewObject( |
| intClazz, initInt, static_cast<jint>(s.signalQuality())); |
| env->SetObjectField(statusObj, field, newIntegerObj); |
| break; |
| } |
| case FrontendStatus::hidl_discriminator::signalStrength: { |
| jfieldID field = env->GetFieldID(clazz, "mSignalStrength", "Ljava/lang/Integer;"); |
| jobject newIntegerObj = env->NewObject( |
| intClazz, initInt, static_cast<jint>(s.signalStrength())); |
| env->SetObjectField(statusObj, field, newIntegerObj); |
| break; |
| } |
| case FrontendStatus::hidl_discriminator::symbolRate: { |
| jfieldID field = env->GetFieldID(clazz, "mSymbolRate", "Ljava/lang/Integer;"); |
| jobject newIntegerObj = env->NewObject( |
| intClazz, initInt, static_cast<jint>(s.symbolRate())); |
| env->SetObjectField(statusObj, field, newIntegerObj); |
| break; |
| } |
| case FrontendStatus::hidl_discriminator::innerFec: { |
| jfieldID field = env->GetFieldID(clazz, "mInnerFec", "Ljava/lang/Long;"); |
| jclass longClazz = env->FindClass("java/lang/Long"); |
| jmethodID initLong = env->GetMethodID(longClazz, "<init>", "(J)V"); |
| jobject newLongObj = env->NewObject( |
| longClazz, initLong, static_cast<jlong>(s.innerFec())); |
| env->SetObjectField(statusObj, field, newLongObj); |
| break; |
| } |
| case FrontendStatus::hidl_discriminator::modulation: { |
| jfieldID field = env->GetFieldID(clazz, "mModulation", "Ljava/lang/Integer;"); |
| FrontendModulationStatus modulation = s.modulation(); |
| jint intModulation; |
| bool valid = true; |
| switch(modulation.getDiscriminator()) { |
| case FrontendModulationStatus::hidl_discriminator::dvbc: { |
| intModulation = static_cast<jint>(modulation.dvbc()); |
| break; |
| } |
| case FrontendModulationStatus::hidl_discriminator::dvbs: { |
| intModulation = static_cast<jint>(modulation.dvbs()); |
| break; |
| } |
| case FrontendModulationStatus::hidl_discriminator::isdbs: { |
| intModulation = static_cast<jint>(modulation.isdbs()); |
| break; |
| } |
| case FrontendModulationStatus::hidl_discriminator::isdbs3: { |
| intModulation = static_cast<jint>(modulation.isdbs3()); |
| break; |
| } |
| case FrontendModulationStatus::hidl_discriminator::isdbt: { |
| intModulation = static_cast<jint>(modulation.isdbt()); |
| break; |
| } |
| default: { |
| valid = false; |
| break; |
| } |
| } |
| if (valid) { |
| jobject newIntegerObj = env->NewObject(intClazz, initInt, intModulation); |
| env->SetObjectField(statusObj, field, newIntegerObj); |
| } |
| break; |
| } |
| case FrontendStatus::hidl_discriminator::inversion: { |
| jfieldID field = env->GetFieldID(clazz, "mInversion", "Ljava/lang/Integer;"); |
| jobject newIntegerObj = env->NewObject( |
| intClazz, initInt, static_cast<jint>(s.inversion())); |
| env->SetObjectField(statusObj, field, newIntegerObj); |
| break; |
| } |
| case FrontendStatus::hidl_discriminator::lnbVoltage: { |
| jfieldID field = env->GetFieldID(clazz, "mLnbVoltage", "Ljava/lang/Integer;"); |
| jobject newIntegerObj = env->NewObject( |
| intClazz, initInt, static_cast<jint>(s.lnbVoltage())); |
| env->SetObjectField(statusObj, field, newIntegerObj); |
| break; |
| } |
| case FrontendStatus::hidl_discriminator::plpId: { |
| jfieldID field = env->GetFieldID(clazz, "mPlpId", "Ljava/lang/Integer;"); |
| jobject newIntegerObj = env->NewObject( |
| intClazz, initInt, static_cast<jint>(s.plpId())); |
| env->SetObjectField(statusObj, field, newIntegerObj); |
| break; |
| } |
| case FrontendStatus::hidl_discriminator::isEWBS: { |
| jfieldID field = env->GetFieldID(clazz, "mIsEwbs", "Ljava/lang/Boolean;"); |
| jobject newBooleanObj = env->NewObject( |
| booleanClazz, initBoolean, static_cast<jboolean>(s.isEWBS())); |
| env->SetObjectField(statusObj, field, newBooleanObj); |
| break; |
| } |
| case FrontendStatus::hidl_discriminator::agc: { |
| jfieldID field = env->GetFieldID(clazz, "mAgc", "Ljava/lang/Integer;"); |
| jobject newIntegerObj = env->NewObject( |
| intClazz, initInt, static_cast<jint>(s.agc())); |
| env->SetObjectField(statusObj, field, newIntegerObj); |
| break; |
| } |
| case FrontendStatus::hidl_discriminator::isLnaOn: { |
| jfieldID field = env->GetFieldID(clazz, "mIsLnaOn", "Ljava/lang/Boolean;"); |
| jobject newBooleanObj = env->NewObject( |
| booleanClazz, initBoolean, static_cast<jboolean>(s.isLnaOn())); |
| env->SetObjectField(statusObj, field, newBooleanObj); |
| break; |
| } |
| case FrontendStatus::hidl_discriminator::isLayerError: { |
| jfieldID field = env->GetFieldID(clazz, "mIsLayerErrors", "[Z"); |
| hidl_vec<bool> layerErr = s.isLayerError(); |
| |
| jbooleanArray valObj = env->NewBooleanArray(layerErr.size()); |
| |
| for (size_t i = 0; i < layerErr.size(); i++) { |
| jboolean x = layerErr[i]; |
| env->SetBooleanArrayRegion(valObj, i, 1, &x); |
| } |
| env->SetObjectField(statusObj, field, valObj); |
| break; |
| } |
| case FrontendStatus::hidl_discriminator::mer: { |
| jfieldID field = env->GetFieldID(clazz, "mMer", "Ljava/lang/Integer;"); |
| jobject newIntegerObj = env->NewObject( |
| intClazz, initInt, static_cast<jint>(s.mer())); |
| env->SetObjectField(statusObj, field, newIntegerObj); |
| break; |
| } |
| case FrontendStatus::hidl_discriminator::freqOffset: { |
| jfieldID field = env->GetFieldID(clazz, "mFreqOffset", "Ljava/lang/Integer;"); |
| jobject newIntegerObj = env->NewObject( |
| intClazz, initInt, static_cast<jint>(s.freqOffset())); |
| env->SetObjectField(statusObj, field, newIntegerObj); |
| break; |
| } |
| case FrontendStatus::hidl_discriminator::hierarchy: { |
| jfieldID field = env->GetFieldID(clazz, "mHierarchy", "Ljava/lang/Integer;"); |
| jobject newIntegerObj = env->NewObject( |
| intClazz, initInt, static_cast<jint>(s.hierarchy())); |
| env->SetObjectField(statusObj, field, newIntegerObj); |
| break; |
| } |
| case FrontendStatus::hidl_discriminator::isRfLocked: { |
| jfieldID field = env->GetFieldID(clazz, "mIsRfLocked", "Ljava/lang/Boolean;"); |
| jobject newBooleanObj = env->NewObject( |
| booleanClazz, initBoolean, static_cast<jboolean>(s.isRfLocked())); |
| env->SetObjectField(statusObj, field, newBooleanObj); |
| break; |
| } |
| case FrontendStatus::hidl_discriminator::plpInfo: { |
| jfieldID field = env->GetFieldID(clazz, "mPlpInfo", |
| "[Landroid/media/tv/tuner/frontend/FrontendStatus$Atsc3PlpTuningInfo;"); |
| jclass plpClazz = env->FindClass( |
| "android/media/tv/tuner/frontend/FrontendStatus$Atsc3PlpTuningInfo"); |
| jmethodID initPlp = env->GetMethodID(plpClazz, "<init>", "(IZI)V"); |
| |
| hidl_vec<FrontendStatusAtsc3PlpInfo> plpInfos = s.plpInfo(); |
| |
| jobjectArray valObj = env->NewObjectArray(plpInfos.size(), plpClazz, NULL); |
| for (int i = 0; i < plpInfos.size(); i++) { |
| auto info = plpInfos[i]; |
| jint plpId = (jint) info.plpId; |
| jboolean isLocked = (jboolean) info.isLocked; |
| jint uec = (jint) info.uec; |
| |
| jobject plpObj = env->NewObject(plpClazz, initPlp, plpId, isLocked, uec); |
| env->SetObjectArrayElement(valObj, i, plpObj); |
| } |
| |
| env->SetObjectField(statusObj, field, valObj); |
| break; |
| } |
| default: { |
| break; |
| } |
| } |
| } |
| |
| for (auto s : status_1_1) { |
| switch(s.getDiscriminator()) { |
| case FrontendStatusExt1_1::hidl_discriminator::modulations: { |
| jfieldID field = env->GetFieldID(clazz, "mModulationsExt", "[I"); |
| std::vector<FrontendModulation> v = s.modulations(); |
| |
| jintArray valObj = env->NewIntArray(v.size()); |
| bool valid = false; |
| jint m[1]; |
| for (int i = 0; i < v.size(); i++) { |
| auto modulation = v[i]; |
| switch(modulation.getDiscriminator()) { |
| case FrontendModulation::hidl_discriminator::dvbc: { |
| m[0] = static_cast<jint>(modulation.dvbc()); |
| env->SetIntArrayRegion(valObj, i, 1, m); |
| valid = true; |
| break; |
| } |
| case FrontendModulation::hidl_discriminator::dvbs: { |
| m[0] = static_cast<jint>(modulation.dvbs()); |
| env->SetIntArrayRegion(valObj, i, 1, m); |
| valid = true; |
| break; |
| } |
| case FrontendModulation::hidl_discriminator::dvbt: { |
| m[0] = static_cast<jint>(modulation.dvbt()); |
| env->SetIntArrayRegion(valObj, i, 1, m); |
| valid = true; |
| break; |
| } |
| case FrontendModulation::hidl_discriminator::isdbs: { |
| m[0] = static_cast<jint>(modulation.isdbs()); |
| env->SetIntArrayRegion(valObj, i, 1, m); |
| valid = true; |
| break; |
| } |
| case FrontendModulation::hidl_discriminator::isdbs3: { |
| m[0] = static_cast<jint>(modulation.isdbs3()); |
| env->SetIntArrayRegion(valObj, i, 1, m); |
| valid = true; |
| break; |
| } |
| case FrontendModulation::hidl_discriminator::isdbt: { |
| m[0] = static_cast<jint>(modulation.isdbt()); |
| env->SetIntArrayRegion(valObj, i, 1, m); |
| valid = true; |
| break; |
| } |
| case FrontendModulation::hidl_discriminator::atsc: { |
| m[0] = static_cast<jint>(modulation.atsc()); |
| env->SetIntArrayRegion(valObj, i, 1, m); |
| valid = true; |
| break; |
| } |
| case FrontendModulation::hidl_discriminator::atsc3: { |
| m[0] = static_cast<jint>(modulation.atsc3()); |
| env->SetIntArrayRegion(valObj, i, 1, m); |
| valid = true; |
| break; |
| } |
| case FrontendModulation::hidl_discriminator::dtmb: { |
| m[0] = static_cast<jint>(modulation.dtmb()); |
| env->SetIntArrayRegion(valObj, i, 1, m); |
| valid = true; |
| break; |
| } |
| default: |
| break; |
| } |
| } |
| if (valid) { |
| env->SetObjectField(statusObj, field, valObj); |
| } |
| break; |
| } |
| case FrontendStatusExt1_1::hidl_discriminator::bers: { |
| jfieldID field = env->GetFieldID(clazz, "mBers", "[I"); |
| std::vector<uint32_t> v = s.bers(); |
| |
| jintArray valObj = env->NewIntArray(v.size()); |
| env->SetIntArrayRegion(valObj, 0, v.size(), reinterpret_cast<jint*>(&v[0])); |
| |
| env->SetObjectField(statusObj, field, valObj); |
| break; |
| } |
| case FrontendStatusExt1_1::hidl_discriminator::codeRates: { |
| jfieldID field = env->GetFieldID(clazz, "mCodeRates", "[I"); |
| std::vector<::android::hardware::tv::tuner::V1_1::FrontendInnerFec> v |
| = s.codeRates(); |
| |
| jintArray valObj = env->NewIntArray(v.size()); |
| env->SetIntArrayRegion(valObj, 0, v.size(), reinterpret_cast<jint*>(&v[0])); |
| |
| env->SetObjectField(statusObj, field, valObj); |
| break; |
| } |
| case FrontendStatusExt1_1::hidl_discriminator::bandwidth: { |
| jfieldID field = env->GetFieldID(clazz, "mBandwidth", "Ljava/lang/Integer;"); |
| auto bandwidth = s.bandwidth(); |
| jint intBandwidth; |
| bool valid = true; |
| switch(bandwidth.getDiscriminator()) { |
| case FrontendBandwidth::hidl_discriminator::atsc3: { |
| intBandwidth = static_cast<jint>(bandwidth.atsc3()); |
| break; |
| } |
| case FrontendBandwidth::hidl_discriminator::dvbt: { |
| intBandwidth = static_cast<jint>(bandwidth.dvbt()); |
| break; |
| } |
| case FrontendBandwidth::hidl_discriminator::dvbc: { |
| intBandwidth = static_cast<jint>(bandwidth.dvbc()); |
| break; |
| } |
| case FrontendBandwidth::hidl_discriminator::isdbt: { |
| intBandwidth = static_cast<jint>(bandwidth.isdbt()); |
| break; |
| } |
| case FrontendBandwidth::hidl_discriminator::dtmb: { |
| intBandwidth = static_cast<jint>(bandwidth.dtmb()); |
| break; |
| } |
| default: |
| valid = false; |
| break; |
| } |
| if (valid) { |
| jobject newIntegerObj = env->NewObject(intClazz, initInt, intBandwidth); |
| env->SetObjectField(statusObj, field, newIntegerObj); |
| } |
| break; |
| } |
| case FrontendStatusExt1_1::hidl_discriminator::interval: { |
| jfieldID field = env->GetFieldID(clazz, "mGuardInterval", "Ljava/lang/Integer;"); |
| auto interval = s.interval(); |
| jint intInterval; |
| bool valid = true; |
| switch(interval.getDiscriminator()) { |
| case FrontendGuardInterval::hidl_discriminator::dvbt: { |
| intInterval = static_cast<jint>(interval.dvbt()); |
| break; |
| } |
| case FrontendGuardInterval::hidl_discriminator::isdbt: { |
| intInterval = static_cast<jint>(interval.isdbt()); |
| break; |
| } |
| case FrontendGuardInterval::hidl_discriminator::dtmb: { |
| intInterval = static_cast<jint>(interval.dtmb()); |
| break; |
| } |
| default: |
| valid = false; |
| break; |
| } |
| if (valid) { |
| jobject newIntegerObj = env->NewObject(intClazz, initInt, intInterval); |
| env->SetObjectField(statusObj, field, newIntegerObj); |
| } |
| break; |
| } |
| case FrontendStatusExt1_1::hidl_discriminator::transmissionMode: { |
| jfieldID field = env->GetFieldID(clazz, "mTransmissionMode", "Ljava/lang/Integer;"); |
| auto transmissionMode = s.transmissionMode(); |
| jint intTransmissionMode; |
| bool valid = true; |
| switch(transmissionMode.getDiscriminator()) { |
| case FrontendTransmissionMode::hidl_discriminator::dvbt: { |
| intTransmissionMode = static_cast<jint>(transmissionMode.dvbt()); |
| break; |
| } |
| case FrontendTransmissionMode::hidl_discriminator::isdbt: { |
| intTransmissionMode = static_cast<jint>(transmissionMode.isdbt()); |
| break; |
| } |
| case FrontendTransmissionMode::hidl_discriminator::dtmb: { |
| intTransmissionMode = static_cast<jint>(transmissionMode.dtmb()); |
| break; |
| } |
| default: |
| valid = false; |
| break; |
| } |
| if (valid) { |
| jobject newIntegerObj = env->NewObject(intClazz, initInt, intTransmissionMode); |
| env->SetObjectField(statusObj, field, newIntegerObj); |
| } |
| break; |
| } |
| case FrontendStatusExt1_1::hidl_discriminator::uec: { |
| jfieldID field = env->GetFieldID(clazz, "mUec", "Ljava/lang/Integer;"); |
| jobject newIntegerObj = env->NewObject( |
| intClazz, initInt, static_cast<jint>(s.uec())); |
| env->SetObjectField(statusObj, field, newIntegerObj); |
| break; |
| } |
| case FrontendStatusExt1_1::hidl_discriminator::systemId: { |
| jfieldID field = env->GetFieldID(clazz, "mSystemId", "Ljava/lang/Integer;"); |
| jobject newIntegerObj = env->NewObject( |
| intClazz, initInt, static_cast<jint>(s.systemId())); |
| env->SetObjectField(statusObj, field, newIntegerObj); |
| break; |
| } |
| case FrontendStatusExt1_1::hidl_discriminator::interleaving: { |
| jfieldID field = env->GetFieldID(clazz, "mInterleaving", "[I"); |
| |
| std::vector<FrontendInterleaveMode> v = s.interleaving(); |
| jintArray valObj = env->NewIntArray(v.size()); |
| bool valid = false; |
| jint in[1]; |
| for (int i = 0; i < v.size(); i++) { |
| auto interleaving = v[i]; |
| switch(interleaving.getDiscriminator()) { |
| case FrontendInterleaveMode::hidl_discriminator::atsc3: { |
| in[0] = static_cast<jint>(interleaving.atsc3()); |
| env->SetIntArrayRegion(valObj, i, 1, in); |
| valid = true; |
| break; |
| } |
| case FrontendInterleaveMode::hidl_discriminator::dvbc: { |
| in[0] = static_cast<jint>(interleaving.dvbc()); |
| env->SetIntArrayRegion(valObj, i, 1, in); |
| valid = true; |
| break; |
| } |
| case FrontendInterleaveMode::hidl_discriminator::dtmb: { |
| in[0] = static_cast<jint>(interleaving.dtmb()); |
| env->SetIntArrayRegion(valObj, i, 1, in); |
| valid = true; |
| break; |
| } |
| default: |
| break; |
| } |
| } |
| if (valid) { |
| env->SetObjectField(statusObj, field, valObj); |
| } |
| break; |
| } |
| case FrontendStatusExt1_1::hidl_discriminator::isdbtSegment: { |
| jfieldID field = env->GetFieldID(clazz, "mIsdbtSegment", "[I"); |
| std::vector<uint8_t> v = s.isdbtSegment(); |
| |
| jintArray valObj = env->NewIntArray(v.size()); |
| env->SetIntArrayRegion(valObj, 0, v.size(), reinterpret_cast<jint*>(&v[0])); |
| |
| env->SetObjectField(statusObj, field, valObj); |
| break; |
| } |
| case FrontendStatusExt1_1::hidl_discriminator::tsDataRate: { |
| jfieldID field = env->GetFieldID(clazz, "mTsDataRate", "[I"); |
| std::vector<uint32_t> v = s.tsDataRate(); |
| |
| jintArray valObj = env->NewIntArray(v.size()); |
| env->SetIntArrayRegion(valObj, 0, v.size(), reinterpret_cast<jint*>(&v[0])); |
| |
| env->SetObjectField(statusObj, field, valObj); |
| break; |
| } |
| case FrontendStatusExt1_1::hidl_discriminator::rollOff: { |
| jfieldID field = env->GetFieldID(clazz, "mRollOff", "Ljava/lang/Integer;"); |
| auto rollOff = s.rollOff(); |
| jint intRollOff; |
| bool valid = true; |
| switch(rollOff.getDiscriminator()) { |
| case FrontendRollOff::hidl_discriminator::dvbs: { |
| intRollOff = static_cast<jint>(rollOff.dvbs()); |
| break; |
| } |
| case FrontendRollOff::hidl_discriminator::isdbs: { |
| intRollOff = static_cast<jint>(rollOff.isdbs()); |
| break; |
| } |
| case FrontendRollOff::hidl_discriminator::isdbs3: { |
| intRollOff = static_cast<jint>(rollOff.isdbs3()); |
| break; |
| } |
| default: |
| valid = false; |
| break; |
| } |
| if (valid) { |
| jobject newIntegerObj = env->NewObject(intClazz, initInt, intRollOff); |
| env->SetObjectField(statusObj, field, newIntegerObj); |
| } |
| break; |
| } |
| case FrontendStatusExt1_1::hidl_discriminator::isMiso: { |
| jfieldID field = env->GetFieldID(clazz, "mIsMisoEnabled", "Ljava/lang/Boolean;"); |
| jobject newBooleanObj = env->NewObject( |
| booleanClazz, initBoolean, static_cast<jboolean>(s.isMiso())); |
| env->SetObjectField(statusObj, field, newBooleanObj); |
| break; |
| } |
| case FrontendStatusExt1_1::hidl_discriminator::isLinear: { |
| jfieldID field = env->GetFieldID(clazz, "mIsLinear", "Ljava/lang/Boolean;"); |
| jobject newBooleanObj = env->NewObject( |
| booleanClazz, initBoolean, static_cast<jboolean>(s.isLinear())); |
| env->SetObjectField(statusObj, field, newBooleanObj); |
| break; |
| } |
| case FrontendStatusExt1_1::hidl_discriminator::isShortFrames: { |
| jfieldID field = env->GetFieldID(clazz, "mIsShortFrames", "Ljava/lang/Boolean;"); |
| jobject newBooleanObj = env->NewObject( |
| booleanClazz, initBoolean, static_cast<jboolean>(s.isShortFrames())); |
| env->SetObjectField(statusObj, field, newBooleanObj); |
| break; |
| } |
| default: { |
| break; |
| } |
| } |
| } |
| return statusObj; |
| } |
| |
| bool JTuner::isV1_1ExtendedStatusType(int type) { |
| return (type > static_cast<int>(FrontendStatusType::ATSC3_PLP_INFO) |
| && type <= static_cast<int>(FrontendStatusTypeExt1_1::IS_SHORT_FRAMES)); |
| } |
| |
| jint JTuner::closeFrontend() { |
| Result r = Result::SUCCESS; |
| |
| if (mFeClient != NULL) { |
| r = mFeClient->close(); |
| } |
| if (r == Result::SUCCESS) { |
| mFeClient = NULL; |
| } |
| return (jint) r; |
| } |
| |
| jint JTuner::closeDemux() { |
| Result r = Result::SUCCESS; |
| |
| if (mDemuxClient != NULL) { |
| r = mDemuxClient->close(); |
| } |
| if (r == Result::SUCCESS) { |
| mDemuxClient = NULL; |
| } |
| return (jint) r; |
| } |
| } // namespace android |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| using namespace android; |
| |
| static sp<JTuner> setTuner(JNIEnv *env, jobject thiz, const sp<JTuner> &tuner) { |
| sp<JTuner> old = (JTuner *)env->GetLongField(thiz, gFields.tunerContext); |
| |
| if (tuner != NULL) { |
| tuner->incStrong(thiz); |
| } |
| if (old != NULL) { |
| old->decStrong(thiz); |
| } |
| env->SetLongField(thiz, gFields.tunerContext, (jlong)tuner.get()); |
| |
| return old; |
| } |
| |
| static sp<JTuner> getTuner(JNIEnv *env, jobject thiz) { |
| return (JTuner *)env->GetLongField(thiz, gFields.tunerContext); |
| } |
| |
| static sp<DescramblerClient> getDescramblerClient(JNIEnv *env, jobject descrambler) { |
| return (DescramblerClient *)env->GetLongField(descrambler, gFields.descramblerContext); |
| } |
| |
| static DemuxPid getDemuxPid(int pidType, int pid) { |
| DemuxPid demuxPid; |
| if ((int)pidType == 1) { |
| demuxPid.tPid(static_cast<DemuxTpid>(pid)); |
| } else if ((int)pidType == 2) { |
| demuxPid.mmtpPid(static_cast<DemuxMmtpPid>(pid)); |
| } |
| return demuxPid; |
| } |
| |
| static uint32_t getFrontendSettingsFreq(JNIEnv *env, const jobject& settings) { |
| jclass clazz = env->FindClass("android/media/tv/tuner/frontend/FrontendSettings"); |
| jfieldID freqField = env->GetFieldID(clazz, "mFrequency", "I"); |
| uint32_t freq = static_cast<uint32_t>(env->GetIntField(settings, freqField)); |
| return freq; |
| } |
| |
| static uint32_t getFrontendSettingsEndFreq(JNIEnv *env, const jobject& settings) { |
| jclass clazz = env->FindClass("android/media/tv/tuner/frontend/FrontendSettings"); |
| jfieldID endFreqField = env->GetFieldID(clazz, "mEndFrequency", "I"); |
| uint32_t endFreq = static_cast<uint32_t>(env->GetIntField(settings, endFreqField)); |
| return endFreq; |
| } |
| |
| static FrontendSpectralInversion getFrontendSettingsSpectralInversion( |
| JNIEnv *env, const jobject& settings) { |
| jclass clazz = env->FindClass("android/media/tv/tuner/frontend/FrontendSettings"); |
| jfieldID inversionField = env->GetFieldID(clazz, "mSpectralInversion", "I"); |
| FrontendSpectralInversion inversion = |
| static_cast<FrontendSpectralInversion>(env->GetIntField(settings, inversionField)); |
| return inversion; |
| } |
| |
| static FrontendSettings getAnalogFrontendSettings(JNIEnv *env, const jobject& settings) { |
| FrontendSettings frontendSettings; |
| uint32_t freq = getFrontendSettingsFreq(env, settings); |
| jclass clazz = env->FindClass("android/media/tv/tuner/frontend/AnalogFrontendSettings"); |
| FrontendAnalogType analogType = |
| static_cast<FrontendAnalogType>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mSignalType", "I"))); |
| FrontendAnalogSifStandard sifStandard = |
| static_cast<FrontendAnalogSifStandard>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mSifStandard", "I"))); |
| FrontendAnalogSettings frontendAnalogSettings { |
| .frequency = freq, |
| .type = analogType, |
| .sifStandard = sifStandard, |
| }; |
| frontendSettings.analog(frontendAnalogSettings); |
| return frontendSettings; |
| } |
| |
| static void getAnalogFrontendSettingsExt1_1(JNIEnv *env, const jobject& settings, |
| FrontendSettingsExt1_1& settingsExt1_1) { |
| jclass clazz = env->FindClass("android/media/tv/tuner/frontend/AnalogFrontendSettings"); |
| FrontendAnalogAftFlag aftFlag = |
| static_cast<FrontendAnalogAftFlag>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mAftFlag", "I"))); |
| FrontendAnalogSettingsExt1_1 analogExt1_1 { |
| .aftFlag = aftFlag, |
| }; |
| settingsExt1_1.settingExt.analog(analogExt1_1); |
| } |
| |
| static hidl_vec<FrontendAtsc3PlpSettings> getAtsc3PlpSettings( |
| JNIEnv *env, const jobject& settings) { |
| jclass clazz = env->FindClass("android/media/tv/tuner/frontend/Atsc3FrontendSettings"); |
| jobjectArray plpSettings = |
| reinterpret_cast<jobjectArray>( |
| env->GetObjectField(settings, |
| env->GetFieldID( |
| clazz, |
| "mPlpSettings", |
| "[Landroid/media/tv/tuner/frontend/Atsc3PlpSettings;"))); |
| int len = env->GetArrayLength(plpSettings); |
| |
| jclass plpClazz = env->FindClass("android/media/tv/tuner/frontend/Atsc3PlpSettings"); |
| hidl_vec<FrontendAtsc3PlpSettings> plps = hidl_vec<FrontendAtsc3PlpSettings>(len); |
| // parse PLP settings |
| for (int i = 0; i < len; i++) { |
| jobject plp = env->GetObjectArrayElement(plpSettings, i); |
| uint8_t plpId = |
| static_cast<uint8_t>( |
| env->GetIntField(plp, env->GetFieldID(plpClazz, "mPlpId", "I"))); |
| FrontendAtsc3Modulation modulation = |
| static_cast<FrontendAtsc3Modulation>( |
| env->GetIntField(plp, env->GetFieldID(plpClazz, "mModulation", "I"))); |
| FrontendAtsc3TimeInterleaveMode interleaveMode = |
| static_cast<FrontendAtsc3TimeInterleaveMode>( |
| env->GetIntField( |
| plp, env->GetFieldID(plpClazz, "mInterleaveMode", "I"))); |
| FrontendAtsc3CodeRate codeRate = |
| static_cast<FrontendAtsc3CodeRate>( |
| env->GetIntField(plp, env->GetFieldID(plpClazz, "mCodeRate", "I"))); |
| FrontendAtsc3Fec fec = |
| static_cast<FrontendAtsc3Fec>( |
| env->GetIntField(plp, env->GetFieldID(plpClazz, "mFec", "I"))); |
| FrontendAtsc3PlpSettings frontendAtsc3PlpSettings { |
| .plpId = plpId, |
| .modulation = modulation, |
| .interleaveMode = interleaveMode, |
| .codeRate = codeRate, |
| .fec = fec, |
| }; |
| plps[i] = frontendAtsc3PlpSettings; |
| } |
| return plps; |
| } |
| |
| static FrontendSettings getAtsc3FrontendSettings(JNIEnv *env, const jobject& settings) { |
| FrontendSettings frontendSettings; |
| uint32_t freq = getFrontendSettingsFreq(env, settings); |
| jclass clazz = env->FindClass("android/media/tv/tuner/frontend/Atsc3FrontendSettings"); |
| |
| FrontendAtsc3Bandwidth bandwidth = |
| static_cast<FrontendAtsc3Bandwidth>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mBandwidth", "I"))); |
| FrontendAtsc3DemodOutputFormat demod = |
| static_cast<FrontendAtsc3DemodOutputFormat>( |
| env->GetIntField( |
| settings, env->GetFieldID(clazz, "mDemodOutputFormat", "I"))); |
| hidl_vec<FrontendAtsc3PlpSettings> plps = getAtsc3PlpSettings(env, settings); |
| FrontendAtsc3Settings frontendAtsc3Settings { |
| .frequency = freq, |
| .bandwidth = bandwidth, |
| .demodOutputFormat = demod, |
| .plpSettings = plps, |
| }; |
| frontendSettings.atsc3(frontendAtsc3Settings); |
| return frontendSettings; |
| } |
| |
| static FrontendSettings getAtscFrontendSettings(JNIEnv *env, const jobject& settings) { |
| FrontendSettings frontendSettings; |
| uint32_t freq = getFrontendSettingsFreq(env, settings); |
| jclass clazz = env->FindClass("android/media/tv/tuner/frontend/AtscFrontendSettings"); |
| FrontendAtscModulation modulation = |
| static_cast<FrontendAtscModulation>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mModulation", "I"))); |
| FrontendAtscSettings frontendAtscSettings { |
| .frequency = freq, |
| .modulation = modulation, |
| }; |
| frontendSettings.atsc(frontendAtscSettings); |
| return frontendSettings; |
| } |
| |
| static FrontendSettings getDvbcFrontendSettings(JNIEnv *env, const jobject& settings) { |
| FrontendSettings frontendSettings; |
| uint32_t freq = getFrontendSettingsFreq(env, settings); |
| jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbcFrontendSettings"); |
| FrontendDvbcModulation modulation = |
| static_cast<FrontendDvbcModulation>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mModulation", "I"))); |
| FrontendInnerFec innerFec = |
| static_cast<FrontendInnerFec>( |
| env->GetLongField(settings, env->GetFieldID(clazz, "mInnerFec", "J"))); |
| uint32_t symbolRate = |
| static_cast<uint32_t>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mSymbolRate", "I"))); |
| FrontendDvbcOuterFec outerFec = |
| static_cast<FrontendDvbcOuterFec>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mOuterFec", "I"))); |
| FrontendDvbcAnnex annex = |
| static_cast<FrontendDvbcAnnex>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mAnnex", "I"))); |
| FrontendDvbcSpectralInversion spectralInversion = |
| static_cast<FrontendDvbcSpectralInversion>( |
| env->GetIntField( |
| settings, env->GetFieldID(clazz, "mSpectralInversion", "I"))); |
| FrontendDvbcSettings frontendDvbcSettings { |
| .frequency = freq, |
| .modulation = modulation, |
| .fec = innerFec, |
| .symbolRate = symbolRate, |
| .outerFec = outerFec, |
| .annex = annex, |
| .spectralInversion = spectralInversion, |
| }; |
| frontendSettings.dvbc(frontendDvbcSettings); |
| return frontendSettings; |
| } |
| |
| static void getDvbcFrontendSettingsExt1_1(JNIEnv *env, const jobject& settings, |
| FrontendSettingsExt1_1& settingsExt1_1) { |
| jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbcFrontendSettings"); |
| FrontendCableTimeInterleaveMode interleaveMode = |
| static_cast<FrontendCableTimeInterleaveMode>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mInterleaveMode", "I"))); |
| FrontendDvbcBandwidth bandwidth = |
| static_cast<FrontendDvbcBandwidth>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mBandwidth", "I"))); |
| |
| FrontendDvbcSettingsExt1_1 dvbcExt1_1 { |
| .interleaveMode = interleaveMode, |
| .bandwidth = bandwidth, |
| }; |
| settingsExt1_1.settingExt.dvbc(dvbcExt1_1); |
| } |
| |
| static FrontendDvbsCodeRate getDvbsCodeRate(JNIEnv *env, const jobject& settings) { |
| jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbsFrontendSettings"); |
| jobject jcodeRate = |
| env->GetObjectField(settings, |
| env->GetFieldID( |
| clazz, |
| "mCodeRate", |
| "Landroid/media/tv/tuner/frontend/DvbsCodeRate;")); |
| |
| jclass codeRateClazz = env->FindClass("android/media/tv/tuner/frontend/DvbsCodeRate"); |
| FrontendInnerFec innerFec = |
| static_cast<FrontendInnerFec>( |
| env->GetLongField( |
| jcodeRate, env->GetFieldID(codeRateClazz, "mInnerFec", "J"))); |
| bool isLinear = |
| static_cast<bool>( |
| env->GetBooleanField( |
| jcodeRate, env->GetFieldID(codeRateClazz, "mIsLinear", "Z"))); |
| bool isShortFrames = |
| static_cast<bool>( |
| env->GetBooleanField( |
| jcodeRate, env->GetFieldID(codeRateClazz, "mIsShortFrames", "Z"))); |
| uint32_t bitsPer1000Symbol = |
| static_cast<uint32_t>( |
| env->GetIntField( |
| jcodeRate, env->GetFieldID( |
| codeRateClazz, "mBitsPer1000Symbol", "I"))); |
| FrontendDvbsCodeRate coderate { |
| .fec = innerFec, |
| .isLinear = isLinear, |
| .isShortFrames = isShortFrames, |
| .bitsPer1000Symbol = bitsPer1000Symbol, |
| }; |
| return coderate; |
| } |
| |
| static FrontendSettings getDvbsFrontendSettings(JNIEnv *env, const jobject& settings) { |
| FrontendSettings frontendSettings; |
| uint32_t freq = getFrontendSettingsFreq(env, settings); |
| jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbsFrontendSettings"); |
| |
| FrontendDvbsModulation modulation = |
| static_cast<FrontendDvbsModulation>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mModulation", "I"))); |
| uint32_t symbolRate = |
| static_cast<uint32_t>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mSymbolRate", "I"))); |
| FrontendDvbsRolloff rolloff = |
| static_cast<FrontendDvbsRolloff>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mRolloff", "I"))); |
| FrontendDvbsPilot pilot = |
| static_cast<FrontendDvbsPilot>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mPilot", "I"))); |
| uint32_t inputStreamId = |
| static_cast<uint32_t>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mInputStreamId", "I"))); |
| FrontendDvbsStandard standard = |
| static_cast<FrontendDvbsStandard>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mStandard", "I"))); |
| FrontendDvbsVcmMode vcmMode = |
| static_cast<FrontendDvbsVcmMode>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mVcmMode", "I"))); |
| |
| FrontendDvbsSettings frontendDvbsSettings { |
| .frequency = freq, |
| .modulation = modulation, |
| .symbolRate = symbolRate, |
| .rolloff = rolloff, |
| .pilot = pilot, |
| .inputStreamId = inputStreamId, |
| .standard = standard, |
| .vcmMode = vcmMode, |
| }; |
| |
| jobject jcodeRate = env->GetObjectField(settings, env->GetFieldID(clazz, "mCodeRate", |
| "Landroid/media/tv/tuner/frontend/DvbsCodeRate;")); |
| if (jcodeRate != NULL) { |
| frontendDvbsSettings.coderate = getDvbsCodeRate(env, settings); |
| } |
| |
| frontendSettings.dvbs(frontendDvbsSettings); |
| return frontendSettings; |
| } |
| |
| static void getDvbsFrontendSettingsExt1_1(JNIEnv *env, const jobject& settings, |
| FrontendSettingsExt1_1& settingsExt1_1) { |
| jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbsFrontendSettings"); |
| FrontendDvbsScanType scanType = |
| static_cast<FrontendDvbsScanType>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mScanType", "I"))); |
| bool isDiseqcRxMessage = static_cast<bool>(env->GetBooleanField( |
| settings, env->GetFieldID(clazz, "mIsDiseqcRxMessage", "Z"))); |
| |
| FrontendDvbsSettingsExt1_1 dvbsExt1_1 { |
| .scanType = scanType, |
| .isDiseqcRxMessage = isDiseqcRxMessage, |
| }; |
| settingsExt1_1.settingExt.dvbs(dvbsExt1_1); |
| } |
| |
| static FrontendSettings getDvbtFrontendSettings(JNIEnv *env, const jobject& settings) { |
| FrontendSettings frontendSettings; |
| uint32_t freq = getFrontendSettingsFreq(env, settings); |
| jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbtFrontendSettings"); |
| FrontendDvbtTransmissionMode transmissionMode = |
| static_cast<FrontendDvbtTransmissionMode>( |
| env->GetIntField( |
| settings, env->GetFieldID(clazz, "mTransmissionMode", "I"))); |
| FrontendDvbtBandwidth bandwidth = |
| static_cast<FrontendDvbtBandwidth>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mBandwidth", "I"))); |
| FrontendDvbtConstellation constellation = |
| static_cast<FrontendDvbtConstellation>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mConstellation", "I"))); |
| FrontendDvbtHierarchy hierarchy = |
| static_cast<FrontendDvbtHierarchy>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mHierarchy", "I"))); |
| FrontendDvbtCoderate hpCoderate = |
| static_cast<FrontendDvbtCoderate>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mHpCodeRate", "I"))); |
| FrontendDvbtCoderate lpCoderate = |
| static_cast<FrontendDvbtCoderate>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mLpCodeRate", "I"))); |
| FrontendDvbtGuardInterval guardInterval = |
| static_cast<FrontendDvbtGuardInterval>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mGuardInterval", "I"))); |
| bool isHighPriority = |
| static_cast<bool>( |
| env->GetBooleanField( |
| settings, env->GetFieldID(clazz, "mIsHighPriority", "Z"))); |
| FrontendDvbtStandard standard = |
| static_cast<FrontendDvbtStandard>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mStandard", "I"))); |
| bool isMiso = |
| static_cast<bool>( |
| env->GetBooleanField(settings, env->GetFieldID(clazz, "mIsMiso", "Z"))); |
| FrontendDvbtPlpMode plpMode = |
| static_cast<FrontendDvbtPlpMode>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mPlpMode", "I"))); |
| uint8_t plpId = |
| static_cast<uint8_t>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mPlpId", "I"))); |
| uint8_t plpGroupId = |
| static_cast<uint8_t>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mPlpGroupId", "I"))); |
| |
| FrontendDvbtSettings frontendDvbtSettings { |
| .frequency = freq, |
| .transmissionMode = transmissionMode, |
| .bandwidth = bandwidth, |
| .constellation = constellation, |
| .hierarchy = hierarchy, |
| .hpCoderate = hpCoderate, |
| .lpCoderate = lpCoderate, |
| .guardInterval = guardInterval, |
| .isHighPriority = isHighPriority, |
| .standard = standard, |
| .isMiso = isMiso, |
| .plpMode = plpMode, |
| .plpId = plpId, |
| .plpGroupId = plpGroupId, |
| }; |
| frontendSettings.dvbt(frontendDvbtSettings); |
| return frontendSettings; |
| } |
| |
| static void getDvbtFrontendSettingsExt1_1(JNIEnv *env, const jobject& settings, |
| FrontendSettingsExt1_1& settingsExt1_1) { |
| jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbtFrontendSettings"); |
| |
| FrontendDvbtSettingsExt1_1 dvbtExt1_1; |
| int transmissionMode = |
| env->GetIntField(settings, env->GetFieldID(clazz, "mTransmissionMode", "I")); |
| dvbtExt1_1.transmissionMode = static_cast< |
| ::android::hardware::tv::tuner::V1_1::FrontendDvbtTransmissionMode>( |
| transmissionMode); |
| |
| int constellation = |
| env->GetIntField(settings, env->GetFieldID(clazz, "mConstellation", "I")); |
| dvbtExt1_1.constellation = static_cast< |
| ::android::hardware::tv::tuner::V1_1::FrontendDvbtConstellation>(constellation); |
| |
| settingsExt1_1.settingExt.dvbt(dvbtExt1_1); |
| } |
| |
| static FrontendSettings getIsdbsFrontendSettings(JNIEnv *env, const jobject& settings) { |
| FrontendSettings frontendSettings; |
| uint32_t freq = getFrontendSettingsFreq(env, settings); |
| jclass clazz = env->FindClass("android/media/tv/tuner/frontend/IsdbsFrontendSettings"); |
| uint16_t streamId = |
| static_cast<uint16_t>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mStreamId", "I"))); |
| FrontendIsdbsStreamIdType streamIdType = |
| static_cast<FrontendIsdbsStreamIdType>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mStreamIdType", "I"))); |
| FrontendIsdbsModulation modulation = |
| static_cast<FrontendIsdbsModulation>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mModulation", "I"))); |
| FrontendIsdbsCoderate coderate = |
| static_cast<FrontendIsdbsCoderate>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mCodeRate", "I"))); |
| uint32_t symbolRate = |
| static_cast<uint32_t>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mSymbolRate", "I"))); |
| FrontendIsdbsRolloff rolloff = |
| static_cast<FrontendIsdbsRolloff>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mRolloff", "I"))); |
| |
| FrontendIsdbsSettings frontendIsdbsSettings { |
| .frequency = freq, |
| .streamId = streamId, |
| .streamIdType = streamIdType, |
| .modulation = modulation, |
| .coderate = coderate, |
| .symbolRate = symbolRate, |
| .rolloff = rolloff, |
| }; |
| frontendSettings.isdbs(frontendIsdbsSettings); |
| return frontendSettings; |
| } |
| |
| static FrontendSettings getIsdbs3FrontendSettings(JNIEnv *env, const jobject& settings) { |
| FrontendSettings frontendSettings; |
| uint32_t freq = getFrontendSettingsFreq(env, settings); |
| jclass clazz = env->FindClass("android/media/tv/tuner/frontend/Isdbs3FrontendSettings"); |
| uint16_t streamId = |
| static_cast<uint16_t>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mStreamId", "I"))); |
| FrontendIsdbsStreamIdType streamIdType = |
| static_cast<FrontendIsdbsStreamIdType>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mStreamIdType", "I"))); |
| FrontendIsdbs3Modulation modulation = |
| static_cast<FrontendIsdbs3Modulation>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mModulation", "I"))); |
| FrontendIsdbs3Coderate coderate = |
| static_cast<FrontendIsdbs3Coderate>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mCodeRate", "I"))); |
| uint32_t symbolRate = |
| static_cast<uint32_t>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mSymbolRate", "I"))); |
| FrontendIsdbs3Rolloff rolloff = |
| static_cast<FrontendIsdbs3Rolloff>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mRolloff", "I"))); |
| |
| FrontendIsdbs3Settings frontendIsdbs3Settings { |
| .frequency = freq, |
| .streamId = streamId, |
| .streamIdType = streamIdType, |
| .modulation = modulation, |
| .coderate = coderate, |
| .symbolRate = symbolRate, |
| .rolloff = rolloff, |
| }; |
| frontendSettings.isdbs3(frontendIsdbs3Settings); |
| return frontendSettings; |
| } |
| |
| static FrontendSettings getIsdbtFrontendSettings(JNIEnv *env, const jobject& settings) { |
| FrontendSettings frontendSettings; |
| uint32_t freq = getFrontendSettingsFreq(env, settings); |
| jclass clazz = env->FindClass("android/media/tv/tuner/frontend/IsdbtFrontendSettings"); |
| FrontendIsdbtModulation modulation = |
| static_cast<FrontendIsdbtModulation>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mModulation", "I"))); |
| FrontendIsdbtBandwidth bandwidth = |
| static_cast<FrontendIsdbtBandwidth>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mBandwidth", "I"))); |
| FrontendIsdbtMode mode = |
| static_cast<FrontendIsdbtMode>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mMode", "I"))); |
| FrontendIsdbtCoderate coderate = |
| static_cast<FrontendIsdbtCoderate>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mCodeRate", "I"))); |
| FrontendIsdbtGuardInterval guardInterval = |
| static_cast<FrontendIsdbtGuardInterval>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mGuardInterval", "I"))); |
| uint32_t serviceAreaId = |
| static_cast<uint32_t>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mServiceAreaId", "I"))); |
| |
| FrontendIsdbtSettings frontendIsdbtSettings { |
| .frequency = freq, |
| .modulation = modulation, |
| .bandwidth = bandwidth, |
| .mode = mode, |
| .coderate = coderate, |
| .guardInterval = guardInterval, |
| .serviceAreaId = serviceAreaId, |
| }; |
| frontendSettings.isdbt(frontendIsdbtSettings); |
| return frontendSettings; |
| } |
| |
| static void getDtmbFrontendSettings(JNIEnv *env, const jobject& settings, |
| FrontendSettingsExt1_1& settingsExt1_1) { |
| uint32_t freq = getFrontendSettingsFreq(env, settings); |
| jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DtmbFrontendSettings"); |
| FrontendDtmbModulation modulation = |
| static_cast<FrontendDtmbModulation>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mModulation", "I"))); |
| FrontendDtmbBandwidth bandwidth = |
| static_cast<FrontendDtmbBandwidth>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mBandwidth", "I"))); |
| FrontendDtmbTransmissionMode transmissionMode = |
| static_cast<FrontendDtmbTransmissionMode>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mTransmissionMode", "I"))); |
| FrontendDtmbCodeRate codeRate = |
| static_cast<FrontendDtmbCodeRate>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mCodeRate", "I"))); |
| FrontendDtmbGuardInterval guardInterval = |
| static_cast<FrontendDtmbGuardInterval>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mGuardInterval", "I"))); |
| FrontendDtmbTimeInterleaveMode interleaveMode = |
| static_cast<FrontendDtmbTimeInterleaveMode>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mTimeInterleaveMode", "I"))); |
| |
| FrontendDtmbSettings frontendDtmbSettings { |
| .frequency = freq, |
| .modulation = modulation, |
| .bandwidth = bandwidth, |
| .transmissionMode = transmissionMode, |
| .codeRate = codeRate, |
| .guardInterval = guardInterval, |
| .interleaveMode = interleaveMode, |
| }; |
| settingsExt1_1.settingExt.dtmb(frontendDtmbSettings); |
| } |
| |
| static FrontendSettings getFrontendSettings(JNIEnv *env, int type, jobject settings) { |
| ALOGD("getFrontendSettings %d", type); |
| |
| if (type == static_cast<int>(::android::hardware::tv::tuner::V1_1::FrontendType::DTMB)) { |
| return FrontendSettings(); |
| } |
| |
| FrontendType feType = static_cast<FrontendType>(type); |
| switch(feType) { |
| case FrontendType::ANALOG: |
| return getAnalogFrontendSettings(env, settings); |
| case FrontendType::ATSC3: |
| return getAtsc3FrontendSettings(env, settings); |
| case FrontendType::ATSC: |
| return getAtscFrontendSettings(env, settings); |
| case FrontendType::DVBC: |
| return getDvbcFrontendSettings(env, settings); |
| case FrontendType::DVBS: |
| return getDvbsFrontendSettings(env, settings); |
| case FrontendType::DVBT: |
| return getDvbtFrontendSettings(env, settings); |
| case FrontendType::ISDBS: |
| return getIsdbsFrontendSettings(env, settings); |
| case FrontendType::ISDBS3: |
| return getIsdbs3FrontendSettings(env, settings); |
| case FrontendType::ISDBT: |
| return getIsdbtFrontendSettings(env, settings); |
| default: |
| // should never happen because a type is associated with a subclass of |
| // FrontendSettings and not set by users |
| jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", |
| "Unsupported frontend type %d", type); |
| return FrontendSettings(); |
| } |
| } |
| |
| static FrontendSettingsExt1_1 getFrontendSettingsExt1_1( |
| JNIEnv *env, int type, jobject settings, int tunerVersion) { |
| ALOGD("getFrontendSettingsExt1_1 %d", type); |
| |
| FrontendSettingsExt1_1 settingsExt1_1 { |
| .endFrequency = static_cast<uint32_t>(Constant::INVALID_FRONTEND_SETTING_FREQUENCY), |
| .inversion = FrontendSpectralInversion::UNDEFINED, |
| }; |
| settingsExt1_1.settingExt.noinit(); |
| |
| if (tunerVersion < TUNER_VERSION_1_1) { |
| return settingsExt1_1; |
| } |
| |
| if (type == static_cast<int>(::android::hardware::tv::tuner::V1_1::FrontendType::DTMB)) { |
| getDtmbFrontendSettings(env, settings, settingsExt1_1); |
| } else { |
| FrontendType feType = static_cast<FrontendType>(type); |
| switch(feType) { |
| case FrontendType::DVBS: |
| getDvbsFrontendSettingsExt1_1(env, settings, settingsExt1_1); |
| break; |
| case FrontendType::DVBT: |
| getDvbtFrontendSettingsExt1_1(env, settings, settingsExt1_1); |
| break; |
| case FrontendType::ANALOG: |
| getAnalogFrontendSettingsExt1_1(env, settings, settingsExt1_1); |
| break; |
| case FrontendType::ATSC3: |
| break; |
| case FrontendType::ATSC: |
| break; |
| case FrontendType::DVBC: |
| getDvbcFrontendSettingsExt1_1(env, settings, settingsExt1_1); |
| break; |
| case FrontendType::ISDBS: |
| break; |
| case FrontendType::ISDBS3: |
| break; |
| case FrontendType::ISDBT: |
| break; |
| default: |
| // should never happen because a type is associated with a subclass of |
| // FrontendSettings and not set by users |
| jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", |
| "Unsupported frontend type %d", type); |
| return FrontendSettingsExt1_1(); |
| } |
| } |
| |
| uint32_t endFreq = getFrontendSettingsEndFreq(env, settings); |
| FrontendSpectralInversion inversion = getFrontendSettingsSpectralInversion(env, settings); |
| settingsExt1_1.endFrequency = endFreq; |
| settingsExt1_1.inversion = inversion; |
| |
| return settingsExt1_1; |
| } |
| |
| static sp<FilterClient> getFilterClient(JNIEnv *env, jobject filter) { |
| return (FilterClient *)env->GetLongField(filter, gFields.filterContext); |
| } |
| |
| static sp<LnbClient> getLnbClient(JNIEnv *env, jobject lnb) { |
| return (LnbClient *)env->GetLongField(lnb, gFields.lnbContext); |
| } |
| |
| static DvrSettings getDvrSettings(JNIEnv *env, jobject settings, bool isRecorder) { |
| DvrSettings dvrSettings; |
| jclass clazz = env->FindClass("android/media/tv/tuner/dvr/DvrSettings"); |
| uint32_t statusMask = |
| static_cast<uint32_t>(env->GetIntField( |
| settings, env->GetFieldID(clazz, "mStatusMask", "I"))); |
| uint32_t lowThreshold = |
| static_cast<uint32_t>(env->GetLongField( |
| settings, env->GetFieldID(clazz, "mLowThreshold", "J"))); |
| uint32_t highThreshold = |
| static_cast<uint32_t>(env->GetLongField( |
| settings, env->GetFieldID(clazz, "mHighThreshold", "J"))); |
| uint8_t packetSize = |
| static_cast<uint8_t>(env->GetLongField( |
| settings, env->GetFieldID(clazz, "mPacketSize", "J"))); |
| DataFormat dataFormat = |
| static_cast<DataFormat>(env->GetIntField( |
| settings, env->GetFieldID(clazz, "mDataFormat", "I"))); |
| if (isRecorder) { |
| RecordSettings recordSettings { |
| .statusMask = static_cast<unsigned char>(statusMask), |
| .lowThreshold = lowThreshold, |
| .highThreshold = highThreshold, |
| .dataFormat = dataFormat, |
| .packetSize = packetSize, |
| }; |
| dvrSettings.record(recordSettings); |
| } else { |
| PlaybackSettings PlaybackSettings { |
| .statusMask = statusMask, |
| .lowThreshold = lowThreshold, |
| .highThreshold = highThreshold, |
| .dataFormat = dataFormat, |
| .packetSize = packetSize, |
| }; |
| dvrSettings.playback(PlaybackSettings); |
| } |
| return dvrSettings; |
| } |
| |
| static sp<DvrClient> getDvrClient(JNIEnv *env, jobject dvr) { |
| bool isRecorder = |
| env->IsInstanceOf(dvr, env->FindClass("android/media/tv/tuner/dvr/DvrRecorder")); |
| jfieldID fieldId = |
| isRecorder ? gFields.dvrRecorderContext : gFields.dvrPlaybackContext; |
| return (DvrClient *)env->GetLongField(dvr, fieldId); |
| } |
| |
| static void android_media_tv_Tuner_native_init(JNIEnv *env) { |
| jclass clazz = env->FindClass("android/media/tv/tuner/Tuner"); |
| CHECK(clazz != NULL); |
| |
| gFields.tunerContext = env->GetFieldID(clazz, "mNativeContext", "J"); |
| CHECK(gFields.tunerContext != NULL); |
| |
| gFields.onFrontendEventID = env->GetMethodID(clazz, "onFrontendEvent", "(I)V"); |
| |
| jclass frontendClazz = env->FindClass("android/media/tv/tuner/Tuner$Frontend"); |
| gFields.frontendInitID = |
| env->GetMethodID(frontendClazz, "<init>", "(Landroid/media/tv/tuner/Tuner;I)V"); |
| |
| jclass lnbClazz = env->FindClass("android/media/tv/tuner/Lnb"); |
| gFields.lnbContext = env->GetFieldID(lnbClazz, "mNativeContext", "J"); |
| gFields.lnbInitID = env->GetMethodID(lnbClazz, "<init>", "()V"); |
| gFields.onLnbEventID = env->GetMethodID(lnbClazz, "onEvent", "(I)V"); |
| gFields.onLnbDiseqcMessageID = env->GetMethodID(lnbClazz, "onDiseqcMessage", "([B)V"); |
| |
| jclass filterClazz = env->FindClass("android/media/tv/tuner/filter/Filter"); |
| gFields.filterContext = env->GetFieldID(filterClazz, "mNativeContext", "J"); |
| gFields.filterInitID = |
| env->GetMethodID(filterClazz, "<init>", "(J)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"); |
| gFields.timeFilterInitID = env->GetMethodID(timeFilterClazz, "<init>", "()V"); |
| |
| jclass descramblerClazz = env->FindClass("android/media/tv/tuner/Descrambler"); |
| gFields.descramblerContext = env->GetFieldID(descramblerClazz, "mNativeContext", "J"); |
| gFields.descramblerInitID = env->GetMethodID(descramblerClazz, "<init>", "()V"); |
| |
| jclass dvrRecorderClazz = env->FindClass("android/media/tv/tuner/dvr/DvrRecorder"); |
| gFields.dvrRecorderContext = env->GetFieldID(dvrRecorderClazz, "mNativeContext", "J"); |
| gFields.dvrRecorderInitID = env->GetMethodID(dvrRecorderClazz, "<init>", "()V"); |
| gFields.onDvrRecordStatusID = |
| env->GetMethodID(dvrRecorderClazz, "onRecordStatusChanged", "(I)V"); |
| |
| jclass dvrPlaybackClazz = env->FindClass("android/media/tv/tuner/dvr/DvrPlayback"); |
| gFields.dvrPlaybackContext = env->GetFieldID(dvrPlaybackClazz, "mNativeContext", "J"); |
| gFields.dvrPlaybackInitID = env->GetMethodID(dvrPlaybackClazz, "<init>", "()V"); |
| gFields.onDvrPlaybackStatusID = |
| env->GetMethodID(dvrPlaybackClazz, "onPlaybackStatusChanged", "(I)V"); |
| |
| jclass mediaEventClazz = env->FindClass("android/media/tv/tuner/filter/MediaEvent"); |
| gFields.mediaEventContext = env->GetFieldID(mediaEventClazz, "mNativeContext", "J"); |
| |
| jclass linearBlockClazz = env->FindClass("android/media/MediaCodec$LinearBlock"); |
| gFields.linearBlockInitID = env->GetMethodID(linearBlockClazz, "<init>", "()V"); |
| gFields.linearBlockSetInternalStateID = |
| env->GetMethodID(linearBlockClazz, "setInternalStateLocked", "(JZ)V"); |
| } |
| |
| static void android_media_tv_Tuner_native_setup(JNIEnv *env, jobject thiz) { |
| sp<JTuner> tuner = new JTuner(env, thiz); |
| setTuner(env, thiz, tuner); |
| } |
| |
| static jint android_media_tv_Tuner_native_get_tuner_version(JNIEnv *env, jobject thiz) { |
| sp<JTuner> tuner = getTuner(env, thiz); |
| return tuner->getTunerVersion(); |
| } |
| |
| static jobject android_media_tv_Tuner_get_frontend_ids(JNIEnv *env, jobject thiz) { |
| sp<JTuner> tuner = getTuner(env, thiz); |
| return tuner->getFrontendIds(); |
| } |
| |
| static jobject android_media_tv_Tuner_open_frontend_by_handle( |
| JNIEnv *env, jobject thiz, jint handle) { |
| sp<JTuner> tuner = getTuner(env, thiz); |
| return tuner->openFrontendByHandle(handle); |
| } |
| |
| static int android_media_tv_Tuner_tune(JNIEnv *env, jobject thiz, jint type, jobject settings) { |
| sp<JTuner> tuner = getTuner(env, thiz); |
| FrontendSettings setting = getFrontendSettings(env, type, settings); |
| FrontendSettingsExt1_1 settingExt = getFrontendSettingsExt1_1( |
| env, type, settings, tuner->getTunerVersion()); |
| return tuner->tune(setting, settingExt); |
| } |
| |
| static int android_media_tv_Tuner_stop_tune(JNIEnv *env, jobject thiz) { |
| sp<JTuner> tuner = getTuner(env, thiz); |
| return tuner->stopTune(); |
| } |
| |
| static int android_media_tv_Tuner_scan( |
| JNIEnv *env, jobject thiz, jint settingsType, jobject settings, jint scanType) { |
| sp<JTuner> tuner = getTuner(env, thiz); |
| FrontendSettings setting = getFrontendSettings(env, settingsType, settings); |
| FrontendSettingsExt1_1 settingExt = getFrontendSettingsExt1_1( |
| env, settingsType, settings, tuner->getTunerVersion()); |
| return tuner->scan(setting, static_cast<FrontendScanType>(scanType), settingExt); |
| } |
| |
| static int android_media_tv_Tuner_stop_scan(JNIEnv *env, jobject thiz) { |
| sp<JTuner> tuner = getTuner(env, thiz); |
| return tuner->stopScan(); |
| } |
| |
| static int android_media_tv_Tuner_set_lnb(JNIEnv *env, jobject thiz, jobject lnb) { |
| sp<JTuner> tuner = getTuner(env, thiz); |
| sp<LnbClient> lnbClient = getLnbClient(env, lnb); |
| if (lnbClient == NULL) { |
| ALOGE("lnb is not initialized"); |
| return (int)Result::INVALID_STATE; |
| } |
| return tuner->setLnb(lnbClient); |
| } |
| |
| static int android_media_tv_Tuner_set_lna(JNIEnv *env, jobject thiz, jboolean enable) { |
| sp<JTuner> tuner = getTuner(env, thiz); |
| return tuner->setLna(enable); |
| } |
| |
| static jobject android_media_tv_Tuner_get_frontend_status( |
| JNIEnv* env, jobject thiz, jintArray types) { |
| sp<JTuner> tuner = getTuner(env, thiz); |
| return tuner->getFrontendStatus(types); |
| } |
| |
| static jobject android_media_tv_Tuner_get_av_sync_hw_id( |
| JNIEnv *env, jobject thiz, jobject filter) { |
| sp<FilterClient> filterClient = getFilterClient(env, filter); |
| if (filterClient == NULL) { |
| ALOGD("Failed to get sync ID. Filter client not found"); |
| return NULL; |
| } |
| sp<JTuner> tuner = getTuner(env, thiz); |
| return tuner->getAvSyncHwId(filterClient); |
| } |
| |
| static jobject android_media_tv_Tuner_get_av_sync_time(JNIEnv *env, jobject thiz, jint id) { |
| sp<JTuner> tuner = getTuner(env, thiz); |
| return tuner->getAvSyncTime(id); |
| } |
| |
| static int android_media_tv_Tuner_connect_cicam(JNIEnv *env, jobject thiz, jint id) { |
| sp<JTuner> tuner = getTuner(env, thiz); |
| return tuner->connectCiCam(id); |
| } |
| |
| static int android_media_tv_Tuner_link_cicam(JNIEnv *env, jobject thiz, jint id) { |
| sp<JTuner> tuner = getTuner(env, thiz); |
| return tuner->linkCiCam(id); |
| } |
| |
| static int android_media_tv_Tuner_disconnect_cicam(JNIEnv *env, jobject thiz) { |
| sp<JTuner> tuner = getTuner(env, thiz); |
| return tuner->disconnectCiCam(); |
| } |
| |
| static int android_media_tv_Tuner_unlink_cicam(JNIEnv *env, jobject thiz, jint id) { |
| sp<JTuner> tuner = getTuner(env, thiz); |
| return tuner->unlinkCiCam(id); |
| } |
| |
| static jobject android_media_tv_Tuner_get_frontend_info(JNIEnv *env, jobject thiz, jint id) { |
| sp<JTuner> tuner = getTuner(env, thiz); |
| return tuner->getFrontendInfo(id); |
| } |
| |
| static jobject android_media_tv_Tuner_open_lnb_by_handle(JNIEnv *env, jobject thiz, jint handle) { |
| sp<JTuner> tuner = getTuner(env, thiz); |
| return tuner->openLnbByHandle(handle); |
| } |
| |
| static jobject android_media_tv_Tuner_open_lnb_by_name(JNIEnv *env, jobject thiz, jstring name) { |
| sp<JTuner> tuner = getTuner(env, thiz); |
| return tuner->openLnbByName(name); |
| } |
| |
| |
| static jobject android_media_tv_Tuner_open_filter( |
| JNIEnv *env, jobject thiz, jint type, jint subType, jlong bufferSize) { |
| sp<JTuner> tuner = getTuner(env, thiz); |
| DemuxFilterMainType mainType = static_cast<DemuxFilterMainType>(type); |
| DemuxFilterType filterType { |
| .mainType = mainType, |
| }; |
| |
| switch(mainType) { |
| case DemuxFilterMainType::TS: |
| filterType.subType.tsFilterType(static_cast<DemuxTsFilterType>(subType)); |
| break; |
| case DemuxFilterMainType::MMTP: |
| filterType.subType.mmtpFilterType(static_cast<DemuxMmtpFilterType>(subType)); |
| break; |
| case DemuxFilterMainType::IP: |
| filterType.subType.ipFilterType(static_cast<DemuxIpFilterType>(subType)); |
| break; |
| case DemuxFilterMainType::TLV: |
| filterType.subType.tlvFilterType(static_cast<DemuxTlvFilterType>(subType)); |
| break; |
| case DemuxFilterMainType::ALP: |
| filterType.subType.alpFilterType(static_cast<DemuxAlpFilterType>(subType)); |
| break; |
| } |
| |
| return tuner->openFilter(filterType, bufferSize); |
| } |
| |
| static jobject android_media_tv_Tuner_open_time_filter(JNIEnv *env, jobject thiz) { |
| sp<JTuner> tuner = getTuner(env, thiz); |
| return tuner->openTimeFilter(); |
| } |
| |
| static DemuxFilterSectionBits getFilterSectionBits(JNIEnv *env, const jobject& settings) { |
| jclass clazz = env->FindClass("android/media/tv/tuner/filter/SectionSettingsWithSectionBits"); |
| jbyteArray jfilterBytes = static_cast<jbyteArray>( |
| env->GetObjectField(settings, env->GetFieldID(clazz, "mFilter", "[B"))); |
| jsize size = env->GetArrayLength(jfilterBytes); |
| std::vector<uint8_t> filterBytes(size); |
| env->GetByteArrayRegion( |
| jfilterBytes, 0, size, reinterpret_cast<jbyte*>(&filterBytes[0])); |
| |
| jbyteArray jmask = static_cast<jbyteArray>( |
| env->GetObjectField(settings, env->GetFieldID(clazz, "mMask", "[B"))); |
| size = env->GetArrayLength(jmask); |
| std::vector<uint8_t> mask(size); |
| env->GetByteArrayRegion(jmask, 0, size, reinterpret_cast<jbyte*>(&mask[0])); |
| |
| jbyteArray jmode = static_cast<jbyteArray>( |
| env->GetObjectField(settings, env->GetFieldID(clazz, "mMode", "[B"))); |
| size = env->GetArrayLength(jmode); |
| std::vector<uint8_t> mode(size); |
| env->GetByteArrayRegion(jmode, 0, size, reinterpret_cast<jbyte*>(&mode[0])); |
| |
| DemuxFilterSectionBits filterSectionBits { |
| .filter = filterBytes, |
| .mask = mask, |
| .mode = mode, |
| }; |
| return filterSectionBits; |
| } |
| |
| static DemuxFilterSectionSettings::Condition::TableInfo getFilterTableInfo( |
| JNIEnv *env, const jobject& settings) { |
| jclass clazz = env->FindClass("android/media/tv/tuner/filter/SectionSettingsWithTableInfo"); |
| uint16_t tableId = static_cast<uint16_t>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mTableId", "I"))); |
| uint16_t version = static_cast<uint16_t>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mVersion", "I"))); |
| DemuxFilterSectionSettings::Condition::TableInfo tableInfo { |
| .tableId = tableId, |
| .version = version, |
| }; |
| return tableInfo; |
| } |
| |
| static DemuxFilterSectionSettings getFilterSectionSettings(JNIEnv *env, const jobject& settings) { |
| jclass clazz = env->FindClass("android/media/tv/tuner/filter/SectionSettings"); |
| bool isCheckCrc = static_cast<bool>( |
| env->GetBooleanField(settings, env->GetFieldID(clazz, "mCrcEnabled", "Z"))); |
| bool isRepeat = static_cast<bool>( |
| env->GetBooleanField(settings, env->GetFieldID(clazz, "mIsRepeat", "Z"))); |
| bool isRaw = static_cast<bool>( |
| env->GetBooleanField(settings, env->GetFieldID(clazz, "mIsRaw", "Z"))); |
| |
| DemuxFilterSectionSettings filterSectionSettings { |
| .isCheckCrc = isCheckCrc, |
| .isRepeat = isRepeat, |
| .isRaw = isRaw, |
| }; |
| if (env->IsInstanceOf( |
| settings, |
| env->FindClass("android/media/tv/tuner/filter/SectionSettingsWithSectionBits"))) { |
| filterSectionSettings.condition.sectionBits(getFilterSectionBits(env, settings)); |
| } else if (env->IsInstanceOf( |
| settings, |
| env->FindClass("android/media/tv/tuner/filter/SectionSettingsWithTableInfo"))) { |
| filterSectionSettings.condition.tableInfo(getFilterTableInfo(env, settings)); |
| } |
| return filterSectionSettings; |
| } |
| |
| static DemuxFilterAvSettings getFilterAvSettings(JNIEnv *env, const jobject& settings) { |
| jclass clazz = env->FindClass("android/media/tv/tuner/filter/AvSettings"); |
| bool isPassthrough = static_cast<bool>( |
| env->GetBooleanField(settings, env->GetFieldID(clazz, "mIsPassthrough", "Z"))); |
| DemuxFilterAvSettings filterAvSettings { |
| .isPassthrough = isPassthrough, |
| }; |
| return filterAvSettings; |
| } |
| |
| static bool getAvStreamType(JNIEnv *env, jobject filterConfigObj, AvStreamType& type) { |
| jobject settingsObj = |
| env->GetObjectField( |
| filterConfigObj, |
| env->GetFieldID( |
| env->FindClass("android/media/tv/tuner/filter/FilterConfiguration"), |
| "mSettings", |
| "Landroid/media/tv/tuner/filter/Settings;")); |
| jclass clazz = env->FindClass("android/media/tv/tuner/filter/AvSettings"); |
| AvStreamType streamType; |
| AudioStreamType audioStreamType = static_cast<AudioStreamType>( |
| env->GetIntField(settingsObj, env->GetFieldID(clazz, "mAudioStreamType", "I"))); |
| if (audioStreamType != AudioStreamType::UNDEFINED) { |
| type.audio(audioStreamType); |
| return true; |
| } |
| VideoStreamType videoStreamType = static_cast<VideoStreamType>( |
| env->GetIntField(settingsObj, env->GetFieldID(clazz, "mVideoStreamType", "I"))); |
| if (videoStreamType != VideoStreamType::UNDEFINED) { |
| type.video(videoStreamType); |
| return true; |
| } |
| return false; |
| } |
| |
| static DemuxFilterPesDataSettings getFilterPesDataSettings(JNIEnv *env, const jobject& settings) { |
| jclass clazz = env->FindClass("android/media/tv/tuner/filter/PesSettings"); |
| uint16_t streamId = static_cast<uint16_t>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mStreamId", "I"))); |
| bool isRaw = static_cast<bool>( |
| env->GetBooleanField(settings, env->GetFieldID(clazz, "mIsRaw", "Z"))); |
| DemuxFilterPesDataSettings filterPesDataSettings { |
| .streamId = streamId, |
| .isRaw = isRaw, |
| }; |
| return filterPesDataSettings; |
| } |
| |
| static DemuxFilterRecordSettings getFilterRecordSettings(JNIEnv *env, const jobject& settings) { |
| jclass clazz = env->FindClass("android/media/tv/tuner/filter/RecordSettings"); |
| hidl_bitfield<DemuxTsIndex> tsIndexMask = static_cast<hidl_bitfield<DemuxTsIndex>>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mTsIndexMask", "I"))); |
| DemuxRecordScIndexType scIndexType = static_cast<DemuxRecordScIndexType>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mScIndexType", "I"))); |
| jint scIndexMask = env->GetIntField(settings, env->GetFieldID(clazz, "mScIndexMask", "I")); |
| |
| DemuxFilterRecordSettings filterRecordSettings { |
| .tsIndexMask = tsIndexMask, |
| .scIndexType = scIndexType, |
| }; |
| if (scIndexType == DemuxRecordScIndexType::SC) { |
| filterRecordSettings.scIndexMask.sc(static_cast<hidl_bitfield<DemuxScIndex>>(scIndexMask)); |
| } else if (scIndexType == DemuxRecordScIndexType::SC_HEVC) { |
| filterRecordSettings.scIndexMask.scHevc( |
| static_cast<hidl_bitfield<DemuxScHevcIndex>>(scIndexMask)); |
| } |
| return filterRecordSettings; |
| } |
| |
| static DemuxFilterDownloadSettings getFilterDownloadSettings(JNIEnv *env, const jobject& settings) { |
| jclass clazz = env->FindClass("android/media/tv/tuner/filter/DownloadSettings"); |
| uint32_t downloadId = static_cast<uint32_t>( |
| env->GetIntField(settings, env->GetFieldID(clazz, "mDownloadId", "I"))); |
| |
| DemuxFilterDownloadSettings filterDownloadSettings { |
| .downloadId = downloadId, |
| }; |
| return filterDownloadSettings; |
| } |
| |
| static DemuxIpAddress getDemuxIpAddress(JNIEnv *env, const jobject& config) { |
| jclass clazz = env->FindClass("android/media/tv/tuner/filter/IpFilterConfiguration"); |
| |
| jbyteArray jsrcIpAddress = static_cast<jbyteArray>( |
| env->GetObjectField(config, env->GetFieldID(clazz, "mSrcIpAddress", "[B"))); |
| jsize srcSize = env->GetArrayLength(jsrcIpAddress); |
| jbyteArray jdstIpAddress = static_cast<jbyteArray>( |
| env->GetObjectField(config, env->GetFieldID(clazz, "mDstIpAddress", "[B"))); |
| jsize dstSize = env->GetArrayLength(jdstIpAddress); |
| |
| DemuxIpAddress res; |
| |
| if (srcSize != dstSize) { |
| // should never happen. Validated on Java size. |
| jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", |
| "IP address lengths don't match. srcLength=%d, dstLength=%d", srcSize, dstSize); |
| return res; |
| } |
| |
| if (srcSize == IP_V4_LENGTH) { |
| uint8_t srcAddr[IP_V4_LENGTH]; |
| uint8_t dstAddr[IP_V4_LENGTH]; |
| env->GetByteArrayRegion( |
| jsrcIpAddress, 0, srcSize, reinterpret_cast<jbyte*>(srcAddr)); |
| env->GetByteArrayRegion( |
| jdstIpAddress, 0, dstSize, reinterpret_cast<jbyte*>(dstAddr)); |
| res.srcIpAddress.v4(srcAddr); |
| res.dstIpAddress.v4(dstAddr); |
| } else if (srcSize == IP_V6_LENGTH) { |
| uint8_t srcAddr[IP_V6_LENGTH]; |
| uint8_t dstAddr[IP_V6_LENGTH]; |
| env->GetByteArrayRegion( |
| jsrcIpAddress, 0, srcSize, reinterpret_cast<jbyte*>(srcAddr)); |
| env->GetByteArrayRegion( |
| jdstIpAddress, 0, dstSize, reinterpret_cast<jbyte*>(dstAddr)); |
| res.srcIpAddress.v6(srcAddr); |
| res.dstIpAddress.v6(dstAddr); |
| } else { |
| // should never happen. Validated on Java size. |
| jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", |
| "Invalid IP address length %d", srcSize); |
| return res; |
| } |
| |
| uint16_t srcPort = static_cast<uint16_t>( |
| env->GetIntField(config, env->GetFieldID(clazz, "mSrcPort", "I"))); |
| uint16_t dstPort = static_cast<uint16_t>( |
| env->GetIntField(config, env->GetFieldID(clazz, "mDstPort", "I"))); |
| |
| res.srcPort = srcPort; |
| res.dstPort = dstPort; |
| |
| return res; |
| } |
| |
| static DemuxFilterSettings getFilterConfiguration( |
| JNIEnv *env, int type, int subtype, jobject filterConfigObj) { |
| DemuxFilterSettings filterSettings; |
| jobject settingsObj = |
| env->GetObjectField( |
| filterConfigObj, |
| env->GetFieldID( |
| env->FindClass("android/media/tv/tuner/filter/FilterConfiguration"), |
| "mSettings", |
| "Landroid/media/tv/tuner/filter/Settings;")); |
| DemuxFilterMainType mainType = static_cast<DemuxFilterMainType>(type); |
| switch (mainType) { |
| case DemuxFilterMainType::TS: { |
| jclass clazz = env->FindClass("android/media/tv/tuner/filter/TsFilterConfiguration"); |
| uint16_t tpid = static_cast<uint16_t>( |
| env->GetIntField(filterConfigObj, env->GetFieldID(clazz, "mTpid", "I"))); |
| DemuxTsFilterSettings tsFilterSettings { |
| .tpid = tpid, |
| }; |
| |
| if (settingsObj != NULL) { |
| DemuxTsFilterType tsType = static_cast<DemuxTsFilterType>(subtype); |
| switch (tsType) { |
| case DemuxTsFilterType::SECTION: |
| tsFilterSettings.filterSettings.section( |
| getFilterSectionSettings(env, settingsObj)); |
| break; |
| case DemuxTsFilterType::AUDIO: |
| case DemuxTsFilterType::VIDEO: |
| tsFilterSettings.filterSettings.av(getFilterAvSettings(env, settingsObj)); |
| break; |
| case DemuxTsFilterType::PES: |
| tsFilterSettings.filterSettings.pesData( |
| getFilterPesDataSettings(env, settingsObj)); |
| break; |
| case DemuxTsFilterType::RECORD: |
| tsFilterSettings.filterSettings.record( |
| getFilterRecordSettings(env, settingsObj)); |
| break; |
| default: |
| break; |
| } |
| } |
| filterSettings.ts(tsFilterSettings); |
| break; |
| } |
| case DemuxFilterMainType::MMTP: { |
| jclass clazz = env->FindClass("android/media/tv/tuner/filter/MmtpFilterConfiguration"); |
| uint16_t mmtpPid = static_cast<uint16_t>( |
| env->GetIntField(filterConfigObj, env->GetFieldID(clazz, "mMmtpPid", "I"))); |
| DemuxMmtpFilterSettings mmtpFilterSettings { |
| .mmtpPid = mmtpPid, |
| }; |
| |
| if (settingsObj != NULL) { |
| DemuxMmtpFilterType mmtpType = static_cast<DemuxMmtpFilterType>(subtype); |
| switch (mmtpType) { |
| case DemuxMmtpFilterType::SECTION: |
| mmtpFilterSettings.filterSettings.section( |
| getFilterSectionSettings(env, settingsObj)); |
| break; |
| case DemuxMmtpFilterType::AUDIO: |
| case DemuxMmtpFilterType::VIDEO: |
| mmtpFilterSettings.filterSettings.av(getFilterAvSettings(env, settingsObj)); |
| break; |
| case DemuxMmtpFilterType::PES: |
| mmtpFilterSettings.filterSettings.pesData( |
| getFilterPesDataSettings(env, settingsObj)); |
| break; |
| case DemuxMmtpFilterType::RECORD: |
| mmtpFilterSettings.filterSettings.record( |
| getFilterRecordSettings(env, settingsObj)); |
| break; |
| case DemuxMmtpFilterType::DOWNLOAD: |
| mmtpFilterSettings.filterSettings.download( |
| getFilterDownloadSettings(env, settingsObj)); |
| break; |
| default: |
| break; |
| } |
| } |
| filterSettings.mmtp(mmtpFilterSettings); |
| break; |
| } |
| case DemuxFilterMainType::IP: { |
| DemuxIpAddress ipAddr = getDemuxIpAddress(env, filterConfigObj); |
| DemuxIpFilterSettings ipFilterSettings { |
| .ipAddr = ipAddr, |
| }; |
| |
| DemuxIpFilterType ipType = static_cast<DemuxIpFilterType>(subtype); |
| if (ipType == DemuxIpFilterType::SECTION && settingsObj != NULL) { |
| ipFilterSettings.filterSettings.section( |
| getFilterSectionSettings(env, settingsObj)); |
| } else if (ipType == DemuxIpFilterType::IP) { |
| jclass clazz = env->FindClass( |
| "android/media/tv/tuner/filter/IpFilterConfiguration"); |
| bool bPassthrough = static_cast<bool>( |
| env->GetBooleanField( |
| filterConfigObj, env->GetFieldID( |
| clazz, "mPassthrough", "Z"))); |
| ipFilterSettings.filterSettings.bPassthrough(bPassthrough); |
| } |
| filterSettings.ip(ipFilterSettings); |
| break; |
| } |
| case DemuxFilterMainType::TLV: { |
| jclass clazz = env->FindClass("android/media/tv/tuner/filter/TlvFilterConfiguration"); |
| uint8_t packetType = static_cast<uint8_t>( |
| env->GetIntField(filterConfigObj, env->GetFieldID(clazz, "mPacketType", "I"))); |
| bool isCompressedIpPacket = static_cast<bool>( |
| env->GetBooleanField( |
| filterConfigObj, env->GetFieldID(clazz, "mIsCompressedIpPacket", "Z"))); |
| |
| DemuxTlvFilterSettings tlvFilterSettings { |
| .packetType = packetType, |
| .isCompressedIpPacket = isCompressedIpPacket, |
| }; |
| |
| DemuxTlvFilterType tlvType = static_cast<DemuxTlvFilterType>(subtype); |
| if (tlvType == DemuxTlvFilterType::SECTION && settingsObj != NULL) { |
| tlvFilterSettings.filterSettings.section( |
| getFilterSectionSettings(env, settingsObj)); |
| } else if (tlvType == DemuxTlvFilterType::TLV) { |
| bool bPassthrough = static_cast<bool>( |
| env->GetBooleanField( |
| filterConfigObj, env->GetFieldID( |
| clazz, "mPassthrough", "Z"))); |
| tlvFilterSettings.filterSettings.bPassthrough(bPassthrough); |
| } |
| filterSettings.tlv(tlvFilterSettings); |
| break; |
| } |
| case DemuxFilterMainType::ALP: { |
| jclass clazz = env->FindClass("android/media/tv/tuner/filter/AlpFilterConfiguration"); |
| uint8_t packetType = static_cast<uint8_t>( |
| env->GetIntField(filterConfigObj, env->GetFieldID(clazz, "mPacketType", "I"))); |
| DemuxAlpLengthType lengthType = static_cast<DemuxAlpLengthType>( |
| env->GetIntField(filterConfigObj, env->GetFieldID(clazz, "mLengthType", "I"))); |
| DemuxAlpFilterSettings alpFilterSettings { |
| .packetType = packetType, |
| .lengthType = lengthType, |
| }; |
| |
| if (settingsObj != NULL) { |
| DemuxAlpFilterType alpType = static_cast<DemuxAlpFilterType>(subtype); |
| switch (alpType) { |
| case DemuxAlpFilterType::SECTION: |
| alpFilterSettings.filterSettings.section( |
| getFilterSectionSettings(env, settingsObj)); |
| break; |
| default: |
| break; |
| } |
| } |
| filterSettings.alp(alpFilterSettings); |
| break; |
| } |
| default: { |
| break; |
| } |
| } |
| return filterSettings; |
| } |
| |
| static Result configureIpFilterContextId( |
| JNIEnv *env, sp<FilterClient> filterClient, jobject ipFilterConfigObj) { |
| jclass clazz = env->FindClass( |
| "android/media/tv/tuner/filter/IpFilterConfiguration"); |
| uint32_t cid = env->GetIntField(ipFilterConfigObj, env->GetFieldID( |
| clazz, "mIpFilterContextId", "I")); |
| |
| return filterClient->configureIpFilterContextId(cid); |
| } |
| |
| static bool isAvFilterSettings(DemuxFilterSettings filterSettings) { |
| return (filterSettings.getDiscriminator() == DemuxFilterSettings::hidl_discriminator::ts |
| && filterSettings.ts().filterSettings.getDiscriminator() |
| == DemuxTsFilterSettings::FilterSettings::hidl_discriminator::av) |
| || |
| (filterSettings.getDiscriminator() == DemuxFilterSettings::hidl_discriminator::mmtp |
| && filterSettings.mmtp().filterSettings.getDiscriminator() |
| == DemuxMmtpFilterSettings::FilterSettings::hidl_discriminator::av); |
| } |
| |
| static jint android_media_tv_Tuner_configure_filter( |
| JNIEnv *env, jobject filter, int type, int subtype, jobject settings) { |
| ALOGD("configure filter type=%d, subtype=%d", type, subtype); |
| sp<FilterClient> filterClient = getFilterClient(env, filter); |
| if (filterClient == NULL) { |
| ALOGD("Failed to configure filter: filter not found"); |
| return (jint) Result::NOT_INITIALIZED; |
| } |
| DemuxFilterSettings filterSettings = getFilterConfiguration(env, type, subtype, settings); |
| Result res = filterClient->configure(filterSettings); |
| |
| if (res != Result::SUCCESS) { |
| return (jint) res; |
| } |
| |
| if (static_cast<DemuxFilterMainType>(type) == DemuxFilterMainType::IP) { |
| res = configureIpFilterContextId(env, filterClient, settings); |
| if (res != Result::SUCCESS) { |
| return (jint) res; |
| } |
| } |
| |
| AvStreamType streamType; |
| if (isAvFilterSettings(filterSettings) && getAvStreamType(env, settings, streamType)) { |
| res = filterClient->configureAvStreamType(streamType); |
| } |
| return (jint) res; |
| } |
| |
| static jint android_media_tv_Tuner_get_filter_id(JNIEnv* env, jobject filter) { |
| sp<FilterClient> filterClient = getFilterClient(env, filter); |
| if (filterClient == NULL) { |
| ALOGD("Failed to get filter ID: filter client not found"); |
| return (int) Result::NOT_INITIALIZED; |
| } |
| uint32_t id; |
| Result res = filterClient->getId(id); |
| if (res != Result::SUCCESS) { |
| return (jint) Constant::INVALID_FILTER_ID; |
| } |
| return (jint) id; |
| } |
| |
| static jlong android_media_tv_Tuner_get_filter_64bit_id(JNIEnv* env, jobject filter) { |
| sp<FilterClient> filterClient = getFilterClient(env, filter); |
| if (filterClient == NULL) { |
| ALOGD("Failed to get filter ID 64 bit: filter client not found"); |
| return (int) Result::NOT_INITIALIZED; |
| } |
| uint64_t id; |
| Result res = filterClient->getId64Bit(id); |
| return (res == Result::SUCCESS) ? |
| static_cast<jlong>(id) : static_cast<jlong>( |
| ::android::hardware::tv::tuner::V1_1::Constant64Bit::INVALID_FILTER_ID_64BIT); |
| } |
| |
| static jint android_media_tv_Tuner_configure_monitor_event( |
| JNIEnv* env, jobject filter, int monitorEventType) { |
| sp<FilterClient> filterClient = getFilterClient(env, filter); |
| if (filterClient == NULL) { |
| ALOGD("Failed to configure scrambling event: filter client not found"); |
| return (int) Result::NOT_INITIALIZED; |
| } |
| Result res = filterClient->configureMonitorEvent(monitorEventType); |
| return (jint) res; |
| } |
| |
| static jint android_media_tv_Tuner_set_filter_data_source( |
| JNIEnv* env, jobject filter, jobject srcFilter) { |
| sp<FilterClient> filterClient = getFilterClient(env, filter); |
| if (filterClient == NULL) { |
| ALOGD("Failed to set filter data source: filter client not found"); |
| return (int) Result::NOT_INITIALIZED; |
| } |
| Result res; |
| if (srcFilter == NULL) { |
| res = filterClient->setDataSource(NULL); |
| } else { |
| sp<FilterClient> srcClient = getFilterClient(env, srcFilter); |
| if (srcClient == NULL) { |
| ALOGD("Failed to set filter data source: src filter not found"); |
| return (jint) Result::INVALID_ARGUMENT; |
| } |
| res = filterClient->setDataSource(srcClient); |
| } |
| return (jint) res; |
| } |
| |
| static jint android_media_tv_Tuner_start_filter(JNIEnv *env, jobject filter) { |
| sp<FilterClient> filterClient = getFilterClient(env, filter); |
| if (filterClient == NULL) { |
| ALOGD("Failed to start filter: filter client not found"); |
| return (int) Result::NOT_INITIALIZED; |
| } |
| return (jint) filterClient->start(); |
| } |
| |
| static jint android_media_tv_Tuner_stop_filter(JNIEnv *env, jobject filter) { |
| sp<FilterClient> filterClient = getFilterClient(env, filter); |
| if (filterClient == NULL) { |
| ALOGD("Failed to stop filter: filter client not found"); |
| return (int) Result::NOT_INITIALIZED; |
| } |
| return (jint) filterClient->stop(); |
| } |
| |
| static jint android_media_tv_Tuner_flush_filter(JNIEnv *env, jobject filter) { |
| sp<FilterClient> filterClient = getFilterClient(env, filter); |
| if (filterClient == NULL) { |
| ALOGD("Failed to flush filter: filter client not found"); |
| return (int) Result::NOT_INITIALIZED; |
| } |
| return (jint) filterClient->flush(); |
| } |
| |
| static jint android_media_tv_Tuner_read_filter_fmq( |
| JNIEnv *env, jobject filter, jbyteArray buffer, jlong offset, jlong size) { |
| sp<FilterClient> filterClient = getFilterClient(env, filter); |
| if (filterClient == NULL) { |
| jniThrowException(env, "java/lang/IllegalStateException", |
| "Failed to read filter FMQ: filter client not found"); |
| return -1; |
| } |
| |
| jboolean isCopy; |
| jbyte *dst = env->GetByteArrayElements(buffer, &isCopy); |
| ALOGD("copyData, isCopy=%d", isCopy); |
| if (dst == nullptr) { |
| jniThrowRuntimeException(env, "Failed to GetByteArrayElements"); |
| return -1; |
| } |
| int realReadSize = filterClient->read(reinterpret_cast<int8_t*>(dst) + offset, size); |
| env->ReleaseByteArrayElements(buffer, dst, 0); |
| return (jint) realReadSize; |
| } |
| |
| static jint android_media_tv_Tuner_close_filter(JNIEnv *env, jobject filter) { |
| sp<FilterClient> filterClient = getFilterClient(env, filter); |
| if (filterClient == NULL) { |
| jniThrowException(env, "java/lang/IllegalStateException", |
| "Failed to close filter: filter client not found"); |
| return 0; |
| } |
| |
| return (jint) filterClient->close(); |
| } |
| |
| static sp<TimeFilterClient> getTimeFilterClient(JNIEnv *env, jobject filter) { |
| return (TimeFilterClient *)env->GetLongField(filter, gFields.timeFilterContext); |
| } |
| |
| static int android_media_tv_Tuner_time_filter_set_timestamp( |
| JNIEnv *env, jobject filter, jlong timestamp) { |
| sp<TimeFilterClient> timeFilterClient = getTimeFilterClient(env, filter); |
| if (timeFilterClient == NULL) { |
| ALOGD("Failed set timestamp: time filter client not found"); |
| return (int) Result::INVALID_STATE; |
| } |
| Result r = timeFilterClient->setTimeStamp(static_cast<uint64_t>(timestamp)); |
| return (int) r; |
| } |
| |
| static int android_media_tv_Tuner_time_filter_clear_timestamp(JNIEnv *env, jobject filter) { |
| sp<TimeFilterClient> timeFilterClient = getTimeFilterClient(env, filter); |
| if (timeFilterClient == NULL) { |
| ALOGD("Failed clear timestamp: time filter client not found"); |
| return (int) Result::INVALID_STATE; |
| } |
| Result r = timeFilterClient->clearTimeStamp(); |
| return (int) r; |
| } |
| |
| static jobject android_media_tv_Tuner_time_filter_get_timestamp(JNIEnv *env, jobject filter) { |
| sp<TimeFilterClient> timeFilterClient = getTimeFilterClient(env, filter); |
| if (timeFilterClient == NULL) { |
| ALOGD("Failed get timestamp: time filter client not found"); |
| return NULL; |
| } |
| uint64_t timestamp = timeFilterClient->getTimeStamp(); |
| if (timestamp == (long)Constant64Bit::INVALID_PRESENTATION_TIME_STAMP) { |
| return NULL; |
| } |
| |
| jclass longClazz = env->FindClass("java/lang/Long"); |
| jmethodID longInit = env->GetMethodID(longClazz, "<init>", "(J)V"); |
| |
| jobject longObj = env->NewObject(longClazz, longInit, static_cast<jlong>(timestamp)); |
| return longObj; |
| } |
| |
| static jobject android_media_tv_Tuner_time_filter_get_source_time(JNIEnv *env, jobject filter) { |
| sp<TimeFilterClient> timeFilterClient = getTimeFilterClient(env, filter); |
| if (timeFilterClient == NULL) { |
| ALOGD("Failed get source time: time filter client not found"); |
| return NULL; |
| } |
| uint64_t timestamp = timeFilterClient->getSourceTime(); |
| if (timestamp == (long)Constant64Bit::INVALID_PRESENTATION_TIME_STAMP) { |
| return NULL; |
| } |
| |
| jclass longClazz = env->FindClass("java/lang/Long"); |
| jmethodID longInit = env->GetMethodID(longClazz, "<init>", "(J)V"); |
| |
| jobject longObj = env->NewObject(longClazz, longInit, static_cast<jlong>(timestamp)); |
| return longObj; |
| } |
| |
| static int android_media_tv_Tuner_time_filter_close(JNIEnv *env, jobject filter) { |
| sp<TimeFilterClient> timeFilterClient = getTimeFilterClient(env, filter); |
| if (timeFilterClient == NULL) { |
| ALOGD("Failed close time filter: time filter client not found"); |
| return (int) Result::INVALID_STATE; |
| } |
| |
| Result r = timeFilterClient->close(); |
| if (r == Result::SUCCESS) { |
| timeFilterClient->decStrong(filter); |
| env->SetLongField(filter, gFields.timeFilterContext, 0); |
| } |
| return (int) r; |
| } |
| |
| static jobject android_media_tv_Tuner_open_descrambler(JNIEnv *env, jobject thiz, jint) { |
| sp<JTuner> tuner = getTuner(env, thiz); |
| return tuner->openDescrambler(); |
| } |
| |
| static jint android_media_tv_Tuner_descrambler_add_pid( |
| JNIEnv *env, jobject descrambler, jint pidType, jint pid, jobject filter) { |
| sp<DescramblerClient> descramblerClient = getDescramblerClient(env, descrambler); |
| if (descramblerClient == NULL) { |
| return (jint) Result::NOT_INITIALIZED; |
| } |
| sp<FilterClient> filterClient = (filter == NULL) ? NULL : getFilterClient(env, filter); |
| Result result = descramblerClient->addPid(getDemuxPid((int)pidType, (int)pid), filterClient); |
| return (jint) result; |
| } |
| |
| static jint android_media_tv_Tuner_descrambler_remove_pid( |
| JNIEnv *env, jobject descrambler, jint pidType, jint pid, jobject filter) { |
| sp<DescramblerClient> descramblerClient = getDescramblerClient(env, descrambler); |
| if (descramblerClient == NULL) { |
| return (jint) Result::NOT_INITIALIZED; |
| } |
| sp<FilterClient> filterClient = (filter == NULL) ? NULL : getFilterClient(env, filter); |
| Result result = descramblerClient->removePid(getDemuxPid((int)pidType, (int)pid), filterClient); |
| return (jint) result; |
| } |
| |
| static jint android_media_tv_Tuner_descrambler_set_key_token( |
| JNIEnv* env, jobject descrambler, jbyteArray keyToken) { |
| sp<DescramblerClient> descramblerClient = getDescramblerClient(env, descrambler); |
| if (descramblerClient == NULL) { |
| return (jint) Result::NOT_INITIALIZED; |
| } |
| int size = env->GetArrayLength(keyToken); |
| std::vector<uint8_t> v(size); |
| env->GetByteArrayRegion(keyToken, 0, size, reinterpret_cast<jbyte*>(&v[0])); |
| Result result = descramblerClient->setKeyToken(v); |
| return (jint) result; |
| } |
| |
| static jint android_media_tv_Tuner_close_descrambler(JNIEnv* env, jobject descrambler) { |
| sp<DescramblerClient> descramblerClient = getDescramblerClient(env, descrambler); |
| if (descramblerClient == NULL) { |
| return (jint) Result::NOT_INITIALIZED; |
| } |
| Result r = descramblerClient->close(); |
| if (r == Result::SUCCESS) { |
| descramblerClient->decStrong(descrambler); |
| } |
| return (jint) r; |
| } |
| |
| static jobject android_media_tv_Tuner_open_dvr_recorder( |
| JNIEnv* env, jobject thiz, jlong bufferSize) { |
| sp<JTuner> tuner = getTuner(env, thiz); |
| return tuner->openDvr(DvrType::RECORD, bufferSize); |
| } |
| |
| static jobject android_media_tv_Tuner_open_dvr_playback( |
| JNIEnv* env, jobject thiz, jlong bufferSize) { |
| sp<JTuner> tuner = getTuner(env, thiz); |
| return tuner->openDvr(DvrType::PLAYBACK, bufferSize); |
| } |
| |
| static jobject android_media_tv_Tuner_get_demux_caps(JNIEnv* env, jobject thiz) { |
| sp<JTuner> tuner = getTuner(env, thiz); |
| return tuner->getDemuxCaps(); |
| } |
| |
| static jint android_media_tv_Tuner_open_demux(JNIEnv* env, jobject thiz, jint handle) { |
| sp<JTuner> tuner = getTuner(env, thiz); |
| return (jint) tuner->openDemux(handle); |
| } |
| |
| static jint android_media_tv_Tuner_close_tuner(JNIEnv* env, jobject thiz) { |
| sp<JTuner> tuner = getTuner(env, thiz); |
| return (jint) tuner->close(); |
| } |
| |
| static jint android_media_tv_Tuner_close_demux(JNIEnv* env, jobject thiz, jint /* handle */) { |
| sp<JTuner> tuner = getTuner(env, thiz); |
| return tuner->closeDemux(); |
| } |
| |
| static jint android_media_tv_Tuner_close_frontend(JNIEnv* env, jobject thiz, jint /* handle */) { |
| sp<JTuner> tuner = getTuner(env, thiz); |
| return tuner->closeFrontend(); |
| } |
| |
| static jint android_media_tv_Tuner_attach_filter(JNIEnv *env, jobject dvr, jobject filter) { |
| sp<FilterClient> filterClient = getFilterClient(env, filter); |
| if (filterClient == NULL) { |
| return (jint) Result::INVALID_ARGUMENT; |
| } |
| sp<DvrClient> dvrClient = getDvrClient(env, dvr); |
| if (dvrClient == NULL) { |
| return (jint) Result::NOT_INITIALIZED; |
| } |
| Result result = dvrClient->attachFilter(filterClient); |
| return (jint) result; |
| } |
| |
| static jint android_media_tv_Tuner_detach_filter(JNIEnv *env, jobject dvr, jobject filter) { |
| sp<FilterClient> filterClient = getFilterClient(env, filter); |
| if (filterClient == NULL) { |
| return (jint) Result::INVALID_ARGUMENT; |
| } |
| sp<DvrClient> dvrClient = getDvrClient(env, dvr); |
| if (dvrClient == NULL) { |
| return (jint) Result::NOT_INITIALIZED; |
| } |
| Result result = dvrClient->detachFilter(filterClient); |
| return (jint) result; |
| } |
| |
| static jint android_media_tv_Tuner_configure_dvr(JNIEnv *env, jobject dvr, jobject settings) { |
| sp<DvrClient> dvrClient = getDvrClient(env, dvr); |
| if (dvrClient == NULL) { |
| ALOGD("Failed to configure dvr: dvr client not found"); |
| return (int)Result::NOT_INITIALIZED; |
| } |
| bool isRecorder = |
| env->IsInstanceOf(dvr, env->FindClass("android/media/tv/tuner/dvr/DvrRecorder")); |
| Result result = dvrClient->configure(getDvrSettings(env, settings, isRecorder)); |
| return (jint) result; |
| } |
| |
| static jint android_media_tv_Tuner_start_dvr(JNIEnv *env, jobject dvr) { |
| sp<DvrClient> dvrClient = getDvrClient(env, dvr); |
| if (dvrClient == NULL) { |
| ALOGD("Failed to start dvr: dvr client not found"); |
| return (jint) Result::NOT_INITIALIZED; |
| } |
| Result result = dvrClient->start(); |
| return (jint) result; |
| } |
| |
| static jint android_media_tv_Tuner_stop_dvr(JNIEnv *env, jobject dvr) { |
| sp<DvrClient> dvrClient = getDvrClient(env, dvr); |
| if (dvrClient == NULL) { |
| ALOGD("Failed to stop dvr: dvr client not found"); |
| return (jint) Result::NOT_INITIALIZED; |
| } |
| Result result = dvrClient->stop(); |
| return (jint) result; |
| } |
| |
| static jint android_media_tv_Tuner_flush_dvr(JNIEnv *env, jobject dvr) { |
| sp<DvrClient> dvrClient = getDvrClient(env, dvr); |
| if (dvrClient == NULL) { |
| ALOGD("Failed to flush dvr: dvr client not found"); |
| return (jint) Result::NOT_INITIALIZED; |
| } |
| Result result = dvrClient->flush(); |
| return (jint) result; |
| } |
| |
| static jint android_media_tv_Tuner_close_dvr(JNIEnv* env, jobject dvr) { |
| sp<DvrClient> dvrClient = getDvrClient(env, dvr); |
| if (dvrClient == NULL) { |
| ALOGD("Failed to close dvr: dvr client not found"); |
| return (jint) Result::NOT_INITIALIZED; |
| } |
| return (jint) dvrClient->close(); |
| } |
| |
| static jint android_media_tv_Tuner_lnb_set_voltage(JNIEnv* env, jobject lnb, jint voltage) { |
| sp<LnbClient> lnbClient = getLnbClient(env, lnb); |
| Result r = lnbClient->setVoltage(static_cast<LnbVoltage>(voltage)); |
| return (jint) r; |
| } |
| |
| static int android_media_tv_Tuner_lnb_set_tone(JNIEnv* env, jobject lnb, jint tone) { |
| sp<LnbClient> lnbClient = getLnbClient(env, lnb); |
| Result r = lnbClient->setTone(static_cast<LnbTone>(tone)); |
| return (jint) r; |
| } |
| |
| static int android_media_tv_Tuner_lnb_set_position(JNIEnv* env, jobject lnb, jint position) { |
| sp<LnbClient> lnbClient = getLnbClient(env, lnb); |
| Result r = lnbClient->setSatellitePosition(static_cast<LnbPosition>(position)); |
| return (jint) r; |
| } |
| |
| static int android_media_tv_Tuner_lnb_send_diseqc_msg(JNIEnv* env, jobject lnb, jbyteArray msg) { |
| sp<LnbClient> lnbClient = getLnbClient(env, lnb); |
| int size = env->GetArrayLength(msg); |
| std::vector<uint8_t> v(size); |
| env->GetByteArrayRegion(msg, 0, size, reinterpret_cast<jbyte*>(&v[0])); |
| Result r = lnbClient->sendDiseqcMessage(v); |
| return (jint) r; |
| } |
| |
| static int android_media_tv_Tuner_close_lnb(JNIEnv* env, jobject lnb) { |
| sp<LnbClient> lnbClient = getLnbClient(env, lnb); |
| Result r = lnbClient->close(); |
| if (r == Result::SUCCESS) { |
| lnbClient->decStrong(lnb); |
| env->SetLongField(lnb, gFields.lnbContext, 0); |
| } |
| return (jint) r; |
| } |
| |
| static void android_media_tv_Tuner_dvr_set_fd(JNIEnv *env, jobject dvr, jint fd) { |
| sp<DvrClient> dvrClient = getDvrClient(env, dvr); |
| if (dvrClient == NULL) { |
| ALOGD("Failed to set FD for dvr: dvr client not found"); |
| return; |
| } |
| dvrClient->setFd((int)fd); |
| ALOGD("set fd = %d", fd); |
| } |
| |
| static jlong android_media_tv_Tuner_read_dvr(JNIEnv *env, jobject dvr, jlong size) { |
| sp<DvrClient> dvrClient = getDvrClient(env, dvr); |
| if (dvrClient == NULL) { |
| jniThrowException(env, "java/lang/IllegalStateException", |
| "Failed to read dvr: dvr client not found"); |
| return -1; |
| } |
| |
| return (jlong) dvrClient->readFromFile(size); |
| } |
| |
| static jlong android_media_tv_Tuner_read_dvr_from_array( |
| JNIEnv* env, jobject dvr, jbyteArray buffer, jlong offset, jlong size) { |
| sp<DvrClient> dvrClient = getDvrClient(env, dvr); |
| if (dvrClient == NULL) { |
| ALOGW("Failed to read dvr: dvr client not found"); |
| return -1; |
| } |
| |
| jboolean isCopy; |
| jbyte *src = env->GetByteArrayElements(buffer, &isCopy); |
| if (src == nullptr) { |
| ALOGD("Failed to GetByteArrayElements"); |
| return -1; |
| } |
| long realSize = dvrClient->readFromBuffer(reinterpret_cast<signed char*>(src) + offset, size); |
| env->ReleaseByteArrayElements(buffer, src, 0); |
| return (jlong) realSize; |
| |
| } |
| |
| static jlong android_media_tv_Tuner_write_dvr(JNIEnv *env, jobject dvr, jlong size) { |
| sp<DvrClient> dvrClient = getDvrClient(env, dvr); |
| if (dvrClient == NULL) { |
| jniThrowException(env, "java/lang/IllegalStateException", |
| "Failed to write dvr: dvr client not found"); |
| return -1; |
| } |
| |
| return (jlong) dvrClient->writeToFile(size); |
| } |
| |
| static jlong android_media_tv_Tuner_write_dvr_to_array( |
| JNIEnv *env, jobject dvr, jbyteArray buffer, jlong offset, jlong size) { |
| sp<DvrClient> dvrClient = getDvrClient(env, dvr); |
| if (dvrClient == NULL) { |
| ALOGW("Failed to read dvr: dvr client not found"); |
| return -1; |
| } |
| |
| jboolean isCopy; |
| jbyte *dst = env->GetByteArrayElements(buffer, &isCopy); |
| ALOGD("copyData, isCopy=%d", isCopy); |
| if (dst == nullptr) { |
| jniThrowRuntimeException(env, "Failed to GetByteArrayElements"); |
| return -1; |
| } |
| |
| long realSize = dvrClient->writeToBuffer(reinterpret_cast<signed char*>(dst) + offset, size); |
| env->ReleaseByteArrayElements(buffer, dst, 0); |
| return (jlong) realSize; |
| } |
| |
| static sp<MediaEvent> getMediaEventSp(JNIEnv *env, jobject mediaEventObj) { |
| return (MediaEvent *)env->GetLongField(mediaEventObj, gFields.mediaEventContext); |
| } |
| |
| static jobject android_media_tv_Tuner_media_event_get_linear_block( |
| JNIEnv* env, jobject mediaEventObj) { |
| sp<MediaEvent> mediaEventSp = getMediaEventSp(env, mediaEventObj); |
| if (mediaEventSp == NULL) { |
| ALOGD("Failed get MediaEvent"); |
| return NULL; |
| } |
| android::Mutex::Autolock autoLock(mediaEventSp->mLock); |
| |
| return mediaEventSp->getLinearBlock(); |
| } |
| |
| static jobject android_media_tv_Tuner_media_event_get_audio_handle( |
| JNIEnv* env, jobject mediaEventObj) { |
| sp<MediaEvent> mediaEventSp = getMediaEventSp(env, mediaEventObj); |
| if (mediaEventSp == NULL) { |
| ALOGD("Failed get MediaEvent"); |
| return NULL; |
| } |
| |
| android::Mutex::Autolock autoLock(mediaEventSp->mLock); |
| uint64_t audioHandle = mediaEventSp->getAudioHandle(); |
| jclass longClazz = env->FindClass("java/lang/Long"); |
| jmethodID longInit = env->GetMethodID(longClazz, "<init>", "(J)V"); |
| |
| jobject longObj = env->NewObject(longClazz, longInit, static_cast<jlong>(audioHandle)); |
| return longObj; |
| } |
| |
| static void android_media_tv_Tuner_media_event_finalize(JNIEnv* env, jobject mediaEventObj) { |
| sp<MediaEvent> mediaEventSp = getMediaEventSp(env, mediaEventObj); |
| if (mediaEventSp == NULL) { |
| ALOGD("Failed get MediaEvent"); |
| return; |
| } |
| |
| android::Mutex::Autolock autoLock(mediaEventSp->mLock); |
| mediaEventSp->mAvHandleRefCnt--; |
| mediaEventSp->finalize(); |
| |
| mediaEventSp->decStrong(mediaEventObj); |
| } |
| |
| static const JNINativeMethod gTunerMethods[] = { |
| { "nativeInit", "()V", (void *)android_media_tv_Tuner_native_init }, |
| { "nativeSetup", "()V", (void *)android_media_tv_Tuner_native_setup }, |
| { "nativeGetTunerVersion", "()I", (void *)android_media_tv_Tuner_native_get_tuner_version }, |
| { "nativeGetFrontendIds", "()Ljava/util/List;", |
| (void *)android_media_tv_Tuner_get_frontend_ids }, |
| { "nativeOpenFrontendByHandle", "(I)Landroid/media/tv/tuner/Tuner$Frontend;", |
| (void *)android_media_tv_Tuner_open_frontend_by_handle }, |
| { "nativeTune", "(ILandroid/media/tv/tuner/frontend/FrontendSettings;)I", |
| (void *)android_media_tv_Tuner_tune }, |
| { "nativeStopTune", "()I", (void *)android_media_tv_Tuner_stop_tune }, |
| { "nativeScan", "(ILandroid/media/tv/tuner/frontend/FrontendSettings;I)I", |
| (void *)android_media_tv_Tuner_scan }, |
| { "nativeStopScan", "()I", (void *)android_media_tv_Tuner_stop_scan }, |
| { "nativeSetLnb", "(Landroid/media/tv/tuner/Lnb;)I", (void *)android_media_tv_Tuner_set_lnb }, |
| { "nativeSetLna", "(Z)I", (void *)android_media_tv_Tuner_set_lna }, |
| { "nativeGetFrontendStatus", "([I)Landroid/media/tv/tuner/frontend/FrontendStatus;", |
| (void *)android_media_tv_Tuner_get_frontend_status }, |
| { "nativeGetAvSyncHwId", "(Landroid/media/tv/tuner/filter/Filter;)Ljava/lang/Integer;", |
| (void *)android_media_tv_Tuner_get_av_sync_hw_id }, |
| { "nativeGetAvSyncTime", "(I)Ljava/lang/Long;", |
| (void *)android_media_tv_Tuner_get_av_sync_time }, |
| { "nativeConnectCiCam", "(I)I", (void *)android_media_tv_Tuner_connect_cicam }, |
| { "nativeLinkCiCam", "(I)I", |
| (void *)android_media_tv_Tuner_link_cicam }, |
| { "nativeUnlinkCiCam", "(I)I", |
| (void *)android_media_tv_Tuner_unlink_cicam }, |
| { "nativeDisconnectCiCam", "()I", (void *)android_media_tv_Tuner_disconnect_cicam }, |
| { "nativeGetFrontendInfo", "(I)Landroid/media/tv/tuner/frontend/FrontendInfo;", |
| (void *)android_media_tv_Tuner_get_frontend_info }, |
| { "nativeOpenFilter", "(IIJ)Landroid/media/tv/tuner/filter/Filter;", |
| (void *)android_media_tv_Tuner_open_filter }, |
| { "nativeOpenTimeFilter", "()Landroid/media/tv/tuner/filter/TimeFilter;", |
| (void *)android_media_tv_Tuner_open_time_filter }, |
| { "nativeOpenLnbByHandle", "(I)Landroid/media/tv/tuner/Lnb;", |
| (void *)android_media_tv_Tuner_open_lnb_by_handle }, |
| { "nativeOpenLnbByName", "(Ljava/lang/String;)Landroid/media/tv/tuner/Lnb;", |
| (void *)android_media_tv_Tuner_open_lnb_by_name }, |
| { "nativeOpenDescramblerByHandle", "(I)Landroid/media/tv/tuner/Descrambler;", |
| (void *)android_media_tv_Tuner_open_descrambler }, |
| { "nativeOpenDvrRecorder", "(J)Landroid/media/tv/tuner/dvr/DvrRecorder;", |
| (void *)android_media_tv_Tuner_open_dvr_recorder }, |
| { "nativeOpenDvrPlayback", "(J)Landroid/media/tv/tuner/dvr/DvrPlayback;", |
| (void *)android_media_tv_Tuner_open_dvr_playback }, |
| { "nativeGetDemuxCapabilities", "()Landroid/media/tv/tuner/DemuxCapabilities;", |
| (void *)android_media_tv_Tuner_get_demux_caps }, |
| { "nativeOpenDemuxByhandle", "(I)I", (void *)android_media_tv_Tuner_open_demux }, |
| { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_tuner }, |
| { "nativeCloseFrontend", "(I)I", (void *)android_media_tv_Tuner_close_frontend }, |
| { "nativeCloseDemux", "(I)I", (void *)android_media_tv_Tuner_close_demux }, |
| }; |
| |
| static const JNINativeMethod gFilterMethods[] = { |
| { "nativeConfigureFilter", "(IILandroid/media/tv/tuner/filter/FilterConfiguration;)I", |
| (void *)android_media_tv_Tuner_configure_filter }, |
| { "nativeGetId", "()I", (void *)android_media_tv_Tuner_get_filter_id }, |
| { "nativeGetId64Bit", "()J", |
| (void *)android_media_tv_Tuner_get_filter_64bit_id }, |
| { "nativeConfigureMonitorEvent", "(I)I", |
| (void *)android_media_tv_Tuner_configure_monitor_event }, |
| { "nativeSetDataSource", "(Landroid/media/tv/tuner/filter/Filter;)I", |
| (void *)android_media_tv_Tuner_set_filter_data_source }, |
| { "nativeStartFilter", "()I", (void *)android_media_tv_Tuner_start_filter }, |
| { "nativeStopFilter", "()I", (void *)android_media_tv_Tuner_stop_filter }, |
| { "nativeFlushFilter", "()I", (void *)android_media_tv_Tuner_flush_filter }, |
| { "nativeRead", "([BJJ)I", (void *)android_media_tv_Tuner_read_filter_fmq }, |
| { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_filter }, |
| }; |
| |
| static const JNINativeMethod gTimeFilterMethods[] = { |
| { "nativeSetTimestamp", "(J)I", (void *)android_media_tv_Tuner_time_filter_set_timestamp }, |
| { "nativeClearTimestamp", "()I", (void *)android_media_tv_Tuner_time_filter_clear_timestamp }, |
| { "nativeGetTimestamp", "()Ljava/lang/Long;", |
| (void *)android_media_tv_Tuner_time_filter_get_timestamp }, |
| { "nativeGetSourceTime", "()Ljava/lang/Long;", |
| (void *)android_media_tv_Tuner_time_filter_get_source_time }, |
| { "nativeClose", "()I", (void *)android_media_tv_Tuner_time_filter_close }, |
| }; |
| |
| static const JNINativeMethod gDescramblerMethods[] = { |
| { "nativeAddPid", "(IILandroid/media/tv/tuner/filter/Filter;)I", |
| (void *)android_media_tv_Tuner_descrambler_add_pid }, |
| { "nativeRemovePid", "(IILandroid/media/tv/tuner/filter/Filter;)I", |
| (void *)android_media_tv_Tuner_descrambler_remove_pid }, |
| { "nativeSetKeyToken", "([B)I", (void *)android_media_tv_Tuner_descrambler_set_key_token }, |
| { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_descrambler }, |
| }; |
| |
| static const JNINativeMethod gDvrRecorderMethods[] = { |
| { "nativeAttachFilter", "(Landroid/media/tv/tuner/filter/Filter;)I", |
| (void *)android_media_tv_Tuner_attach_filter }, |
| { "nativeDetachFilter", "(Landroid/media/tv/tuner/filter/Filter;)I", |
| (void *)android_media_tv_Tuner_detach_filter }, |
| { "nativeConfigureDvr", "(Landroid/media/tv/tuner/dvr/DvrSettings;)I", |
| (void *)android_media_tv_Tuner_configure_dvr }, |
| { "nativeStartDvr", "()I", (void *)android_media_tv_Tuner_start_dvr }, |
| { "nativeStopDvr", "()I", (void *)android_media_tv_Tuner_stop_dvr }, |
| { "nativeFlushDvr", "()I", (void *)android_media_tv_Tuner_flush_dvr }, |
| { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_dvr }, |
| { "nativeSetFileDescriptor", "(I)V", (void *)android_media_tv_Tuner_dvr_set_fd }, |
| { "nativeWrite", "(J)J", (void *)android_media_tv_Tuner_write_dvr }, |
| { "nativeWrite", "([BJJ)J", (void *)android_media_tv_Tuner_write_dvr_to_array }, |
| }; |
| |
| static const JNINativeMethod gDvrPlaybackMethods[] = { |
| { "nativeAttachFilter", "(Landroid/media/tv/tuner/filter/Filter;)I", |
| (void *)android_media_tv_Tuner_attach_filter }, |
| { "nativeDetachFilter", "(Landroid/media/tv/tuner/filter/Filter;)I", |
| (void *)android_media_tv_Tuner_detach_filter }, |
| { "nativeConfigureDvr", "(Landroid/media/tv/tuner/dvr/DvrSettings;)I", |
| (void *)android_media_tv_Tuner_configure_dvr }, |
| { "nativeStartDvr", "()I", (void *)android_media_tv_Tuner_start_dvr }, |
| { "nativeStopDvr", "()I", (void *)android_media_tv_Tuner_stop_dvr }, |
| { "nativeFlushDvr", "()I", (void *)android_media_tv_Tuner_flush_dvr }, |
| { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_dvr }, |
| { "nativeSetFileDescriptor", "(I)V", (void *)android_media_tv_Tuner_dvr_set_fd }, |
| { "nativeRead", "(J)J", (void *)android_media_tv_Tuner_read_dvr }, |
| { "nativeRead", "([BJJ)J", (void *)android_media_tv_Tuner_read_dvr_from_array }, |
| }; |
| |
| static const JNINativeMethod gLnbMethods[] = { |
| { "nativeSetVoltage", "(I)I", (void *)android_media_tv_Tuner_lnb_set_voltage }, |
| { "nativeSetTone", "(I)I", (void *)android_media_tv_Tuner_lnb_set_tone }, |
| { "nativeSetSatellitePosition", "(I)I", (void *)android_media_tv_Tuner_lnb_set_position }, |
| { "nativeSendDiseqcMessage", "([B)I", (void *)android_media_tv_Tuner_lnb_send_diseqc_msg }, |
| { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_lnb }, |
| }; |
| |
| static const JNINativeMethod gMediaEventMethods[] = { |
| { "nativeGetLinearBlock", "()Landroid/media/MediaCodec$LinearBlock;", |
| (void *)android_media_tv_Tuner_media_event_get_linear_block }, |
| { "nativeGetAudioHandle", "()Ljava/lang/Long;", |
| (void *)android_media_tv_Tuner_media_event_get_audio_handle }, |
| { "nativeFinalize", "()V", |
| (void *)android_media_tv_Tuner_media_event_finalize }, |
| }; |
| |
| static bool register_android_media_tv_Tuner(JNIEnv *env) { |
| if (AndroidRuntime::registerNativeMethods( |
| env, "android/media/tv/tuner/Tuner", gTunerMethods, NELEM(gTunerMethods)) != JNI_OK) { |
| ALOGE("Failed to register tuner native methods"); |
| return false; |
| } |
| if (AndroidRuntime::registerNativeMethods( |
| env, "android/media/tv/tuner/filter/Filter", |
| gFilterMethods, |
| NELEM(gFilterMethods)) != JNI_OK) { |
| ALOGE("Failed to register filter native methods"); |
| return false; |
| } |
| if (AndroidRuntime::registerNativeMethods( |
| env, "android/media/tv/tuner/filter/TimeFilter", |
| gTimeFilterMethods, |
| NELEM(gTimeFilterMethods)) != JNI_OK) { |
| ALOGE("Failed to register time filter native methods"); |
| return false; |
| } |
| if (AndroidRuntime::registerNativeMethods( |
| env, "android/media/tv/tuner/Descrambler", |
| gDescramblerMethods, |
| NELEM(gDescramblerMethods)) != JNI_OK) { |
| ALOGE("Failed to register descrambler native methods"); |
| return false; |
| } |
| if (AndroidRuntime::registerNativeMethods( |
| env, "android/media/tv/tuner/dvr/DvrRecorder", |
| gDvrRecorderMethods, |
| NELEM(gDvrRecorderMethods)) != JNI_OK) { |
| ALOGE("Failed to register dvr recorder native methods"); |
| return false; |
| } |
| if (AndroidRuntime::registerNativeMethods( |
| env, "android/media/tv/tuner/dvr/DvrPlayback", |
| gDvrPlaybackMethods, |
| NELEM(gDvrPlaybackMethods)) != JNI_OK) { |
| ALOGE("Failed to register dvr playback native methods"); |
| return false; |
| } |
| if (AndroidRuntime::registerNativeMethods( |
| env, "android/media/tv/tuner/Lnb", |
| gLnbMethods, |
| NELEM(gLnbMethods)) != JNI_OK) { |
| ALOGE("Failed to register lnb native methods"); |
| return false; |
| } |
| if (AndroidRuntime::registerNativeMethods( |
| env, "android/media/tv/tuner/filter/MediaEvent", |
| gMediaEventMethods, |
| NELEM(gMediaEventMethods)) != JNI_OK) { |
| ALOGE("Failed to register MediaEvent native methods"); |
| return false; |
| } |
| return true; |
| } |
| |
| jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) |
| { |
| JNIEnv* env = NULL; |
| jint result = -1; |
| |
| if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { |
| ALOGE("ERROR: GetEnv failed\n"); |
| return result; |
| } |
| assert(env != NULL); |
| |
| if (!register_android_media_tv_Tuner(env)) { |
| ALOGE("ERROR: Tuner native registration failed\n"); |
| return result; |
| } |
| return JNI_VERSION_1_4; |
| } |