From b83f823a1f8b5aa24917b817f939eaa40688ac16 Mon Sep 17 00:00:00 2001 From: shubang Date: Tue, 24 Mar 2020 18:04:35 -0700 Subject: [PATCH] Tuner JNI: getFrontendInfo Bug: 139308734 Test: mmm; Change-Id: I51256798ca8dd1a67d1c53a8839610289dd2e207 --- media/java/android/media/tv/tuner/Tuner.java | 3 + media/jni/android_media_tv_Tuner.cpp | 258 ++++++++++++++++++- media/jni/android_media_tv_Tuner.h | 1 + 3 files changed, 260 insertions(+), 2 deletions(-) diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java index 894882f07b5b3..3a4524742de95 100644 --- a/media/java/android/media/tv/tuner/Tuner.java +++ b/media/java/android/media/tv/tuner/Tuner.java @@ -602,6 +602,9 @@ public class Tuner implements AutoCloseable { */ @Nullable public FrontendStatus getFrontendStatus(@NonNull @FrontendStatusType int[] statusTypes) { + if (mFrontend == null) { + throw new IllegalStateException("frontend is not initialized"); + } return nativeGetFrontendStatus(statusTypes); } diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp index 9310d38c3bd14..b8fa234ddfe29 100644 --- a/media/jni/android_media_tv_Tuner.cpp +++ b/media/jni/android_media_tv_Tuner.cpp @@ -124,7 +124,11 @@ 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::ITuner; using ::android::hardware::tv::tuner::V1_0::LnbPosition; @@ -1419,6 +1423,254 @@ jobject JTuner::getDemuxCaps() { numBytesInSectionFilter, filterCaps, linkCaps, bTimeFilter); } +jobject JTuner::getFrontendStatus(jintArray types) { + if (mFe == NULL) { + return NULL; + } + JNIEnv *env = AndroidRuntime::getJNIEnv(); + jsize size = env->GetArrayLength(types); + std::vector v(size); + env->GetIntArrayRegion(types, 0, size, reinterpret_cast(&v[0])); + + Result res; + hidl_vec status; + mFe->getStatus(v, + [&](Result r, const hidl_vec& s) { + res = r; + status = s; + }); + if (res != Result::SUCCESS) { + return NULL; + } + + jclass clazz = env->FindClass("android/media/tv/tuner/frontend/FrontendStatus"); + jmethodID init = env->GetMethodID(clazz, "", "()V"); + jobject statusObj = env->NewObject(clazz, init); + + jclass intClazz = env->FindClass("java/lang/Integer"); + jmethodID initInt = env->GetMethodID(intClazz, "", "(I)V"); + jclass booleanClazz = env->FindClass("java/lang/Boolean"); + jmethodID initBoolean = env->GetMethodID(booleanClazz, "", "(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(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(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(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(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(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(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(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(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, "", "(J)V"); + jobject newLongObj = env->NewObject( + longClazz, initLong, static_cast(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(modulation.dvbc()); + break; + } + case FrontendModulationStatus::hidl_discriminator::dvbs: { + intModulation = static_cast(modulation.dvbs()); + break; + } + case FrontendModulationStatus::hidl_discriminator::isdbs: { + intModulation = static_cast(modulation.isdbs()); + break; + } + case FrontendModulationStatus::hidl_discriminator::isdbs3: { + intModulation = static_cast(modulation.isdbs3()); + break; + } + case FrontendModulationStatus::hidl_discriminator::isdbt: { + intModulation = static_cast(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(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(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(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(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(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(s.isLnaOn())); + env->SetObjectField(statusObj, field, newBooleanObj); + break; + } + case FrontendStatus::hidl_discriminator::isLayerError: { + jfieldID field = env->GetFieldID(clazz, "mIsLayerErrors", "[Z"); + hidl_vec 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(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(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(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(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, "", "(IZI)V"); + + hidl_vec 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; + } + } + } + + return statusObj; +} + } // namespace android //////////////////////////////////////////////////////////////////////////////// @@ -2048,8 +2300,10 @@ static int android_media_tv_Tuner_set_lna(JNIEnv *env, jobject thiz, jboolean en return tuner->setLna(enable); } -static jobject android_media_tv_Tuner_get_frontend_status(JNIEnv, jobject, jintArray) { - return NULL; +static jobject android_media_tv_Tuner_get_frontend_status( + JNIEnv* env, jobject thiz, jintArray types) { + sp tuner = getTuner(env, thiz); + return tuner->getFrontendStatus(types); } static jobject android_media_tv_Tuner_get_av_sync_hw_id( diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h index 18aac285e7c08..5550a96298a62 100644 --- a/media/jni/android_media_tv_Tuner.h +++ b/media/jni/android_media_tv_Tuner.h @@ -186,6 +186,7 @@ struct JTuner : public RefBase { jobject openDescrambler(); jobject openDvr(DvrType type, jlong bufferSize); jobject getDemuxCaps(); + jobject getFrontendStatus(jintArray types); protected: Result openDemux();