1 /*
2  * Copyright 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "TvTuner-JNI"
18 #include <utils/Log.h>
19 
20 #include "android_media_MediaCodecLinearBlock.h"
21 #include "android_media_tv_Tuner.h"
22 #include "android_runtime/AndroidRuntime.h"
23 
24 #include <android-base/logging.h>
25 #include <android/hardware/tv/tuner/1.0/ITuner.h>
26 #include <media/stagefright/foundation/ADebug.h>
27 #include <nativehelper/JNIHelp.h>
28 #include <nativehelper/ScopedLocalRef.h>
29 #include <utils/NativeHandle.h>
30 
31 #pragma GCC diagnostic ignored "-Wunused-function"
32 
33 using ::android::hardware::Void;
34 using ::android::hardware::hidl_bitfield;
35 using ::android::hardware::hidl_vec;
36 using ::android::hardware::tv::tuner::V1_0::AudioExtraMetaData;
37 using ::android::hardware::tv::tuner::V1_0::Constant;
38 using ::android::hardware::tv::tuner::V1_0::DataFormat;
39 using ::android::hardware::tv::tuner::V1_0::DemuxAlpFilterSettings;
40 using ::android::hardware::tv::tuner::V1_0::DemuxAlpFilterType;
41 using ::android::hardware::tv::tuner::V1_0::DemuxAlpLengthType;
42 using ::android::hardware::tv::tuner::V1_0::DemuxCapabilities;
43 using ::android::hardware::tv::tuner::V1_0::DemuxFilterAvSettings;
44 using ::android::hardware::tv::tuner::V1_0::DemuxFilterDownloadEvent;
45 using ::android::hardware::tv::tuner::V1_0::DemuxFilterDownloadSettings;
46 using ::android::hardware::tv::tuner::V1_0::DemuxFilterIpPayloadEvent;
47 using ::android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
48 using ::android::hardware::tv::tuner::V1_0::DemuxFilterMediaEvent;
49 using ::android::hardware::tv::tuner::V1_0::DemuxFilterMmtpRecordEvent;
50 using ::android::hardware::tv::tuner::V1_0::DemuxFilterPesDataSettings;
51 using ::android::hardware::tv::tuner::V1_0::DemuxFilterPesEvent;
52 using ::android::hardware::tv::tuner::V1_0::DemuxFilterRecordSettings;
53 using ::android::hardware::tv::tuner::V1_0::DemuxFilterSectionBits;
54 using ::android::hardware::tv::tuner::V1_0::DemuxFilterSectionEvent;
55 using ::android::hardware::tv::tuner::V1_0::DemuxFilterSectionSettings;
56 using ::android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
57 using ::android::hardware::tv::tuner::V1_0::DemuxFilterTemiEvent;
58 using ::android::hardware::tv::tuner::V1_0::DemuxFilterTsRecordEvent;
59 using ::android::hardware::tv::tuner::V1_0::DemuxIpAddress;
60 using ::android::hardware::tv::tuner::V1_0::DemuxIpFilterSettings;
61 using ::android::hardware::tv::tuner::V1_0::DemuxIpFilterType;
62 using ::android::hardware::tv::tuner::V1_0::DemuxMmtpFilterSettings;
63 using ::android::hardware::tv::tuner::V1_0::DemuxMmtpFilterType;
64 using ::android::hardware::tv::tuner::V1_0::DemuxMmtpPid;
65 using ::android::hardware::tv::tuner::V1_0::DemuxQueueNotifyBits;
66 using ::android::hardware::tv::tuner::V1_0::DemuxRecordScIndexType;
67 using ::android::hardware::tv::tuner::V1_0::DemuxScHevcIndex;
68 using ::android::hardware::tv::tuner::V1_0::DemuxScIndex;
69 using ::android::hardware::tv::tuner::V1_0::DemuxTlvFilterSettings;
70 using ::android::hardware::tv::tuner::V1_0::DemuxTlvFilterType;
71 using ::android::hardware::tv::tuner::V1_0::DemuxTpid;
72 using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterSettings;
73 using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
74 using ::android::hardware::tv::tuner::V1_0::DemuxTsIndex;
75 using ::android::hardware::tv::tuner::V1_0::DvrSettings;
76 using ::android::hardware::tv::tuner::V1_0::FrontendAnalogSettings;
77 using ::android::hardware::tv::tuner::V1_0::FrontendAnalogSifStandard;
78 using ::android::hardware::tv::tuner::V1_0::FrontendAnalogType;
79 using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3Bandwidth;
80 using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3CodeRate;
81 using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3DemodOutputFormat;
82 using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3Fec;
83 using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3Modulation;
84 using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3PlpSettings;
85 using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3Settings;
86 using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3TimeInterleaveMode;
87 using ::android::hardware::tv::tuner::V1_0::FrontendAtscSettings;
88 using ::android::hardware::tv::tuner::V1_0::FrontendAtscModulation;
89 using ::android::hardware::tv::tuner::V1_0::FrontendDvbcAnnex;
90 using ::android::hardware::tv::tuner::V1_0::FrontendDvbcModulation;
91 using ::android::hardware::tv::tuner::V1_0::FrontendDvbcOuterFec;
92 using ::android::hardware::tv::tuner::V1_0::FrontendDvbcSettings;
93 using ::android::hardware::tv::tuner::V1_0::FrontendDvbcSpectralInversion;
94 using ::android::hardware::tv::tuner::V1_0::FrontendDvbsCodeRate;
95 using ::android::hardware::tv::tuner::V1_0::FrontendDvbsModulation;
96 using ::android::hardware::tv::tuner::V1_0::FrontendDvbsPilot;
97 using ::android::hardware::tv::tuner::V1_0::FrontendDvbsRolloff;
98 using ::android::hardware::tv::tuner::V1_0::FrontendDvbsSettings;
99 using ::android::hardware::tv::tuner::V1_0::FrontendDvbsStandard;
100 using ::android::hardware::tv::tuner::V1_0::FrontendDvbsVcmMode;
101 using ::android::hardware::tv::tuner::V1_0::FrontendDvbtBandwidth;
102 using ::android::hardware::tv::tuner::V1_0::FrontendDvbtCoderate;
103 using ::android::hardware::tv::tuner::V1_0::FrontendDvbtConstellation;
104 using ::android::hardware::tv::tuner::V1_0::FrontendDvbtGuardInterval;
105 using ::android::hardware::tv::tuner::V1_0::FrontendDvbtHierarchy;
106 using ::android::hardware::tv::tuner::V1_0::FrontendDvbtPlpMode;
107 using ::android::hardware::tv::tuner::V1_0::FrontendDvbtSettings;
108 using ::android::hardware::tv::tuner::V1_0::FrontendDvbtStandard;
109 using ::android::hardware::tv::tuner::V1_0::FrontendDvbtTransmissionMode;
110 using ::android::hardware::tv::tuner::V1_0::FrontendInnerFec;
111 using ::android::hardware::tv::tuner::V1_0::FrontendIsdbs3Coderate;
112 using ::android::hardware::tv::tuner::V1_0::FrontendIsdbs3Modulation;
113 using ::android::hardware::tv::tuner::V1_0::FrontendIsdbs3Rolloff;
114 using ::android::hardware::tv::tuner::V1_0::FrontendIsdbs3Settings;
115 using ::android::hardware::tv::tuner::V1_0::FrontendIsdbsCoderate;
116 using ::android::hardware::tv::tuner::V1_0::FrontendIsdbsModulation;
117 using ::android::hardware::tv::tuner::V1_0::FrontendIsdbsRolloff;
118 using ::android::hardware::tv::tuner::V1_0::FrontendIsdbsSettings;
119 using ::android::hardware::tv::tuner::V1_0::FrontendIsdbsStreamIdType;
120 using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtBandwidth;
121 using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtCoderate;
122 using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtGuardInterval;
123 using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtMode;
124 using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtModulation;
125 using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtSettings;
126 using ::android::hardware::tv::tuner::V1_0::FrontendModulationStatus;
127 using ::android::hardware::tv::tuner::V1_0::FrontendScanAtsc3PlpInfo;
128 using ::android::hardware::tv::tuner::V1_0::FrontendStatus;
129 using ::android::hardware::tv::tuner::V1_0::FrontendStatusAtsc3PlpInfo;
130 using ::android::hardware::tv::tuner::V1_0::FrontendStatusType;
131 using ::android::hardware::tv::tuner::V1_0::FrontendType;
132 using ::android::hardware::tv::tuner::V1_0::ITuner;
133 using ::android::hardware::tv::tuner::V1_0::LnbPosition;
134 using ::android::hardware::tv::tuner::V1_0::LnbTone;
135 using ::android::hardware::tv::tuner::V1_0::LnbVoltage;
136 using ::android::hardware::tv::tuner::V1_0::PlaybackSettings;
137 using ::android::hardware::tv::tuner::V1_0::RecordSettings;
138 
139 struct fields_t {
140     jfieldID tunerContext;
141     jfieldID lnbContext;
142     jfieldID filterContext;
143     jfieldID timeFilterContext;
144     jfieldID descramblerContext;
145     jfieldID dvrRecorderContext;
146     jfieldID dvrPlaybackContext;
147     jfieldID mediaEventContext;
148     jmethodID frontendInitID;
149     jmethodID filterInitID;
150     jmethodID timeFilterInitID;
151     jmethodID dvrRecorderInitID;
152     jmethodID dvrPlaybackInitID;
153     jmethodID onFrontendEventID;
154     jmethodID onFilterStatusID;
155     jmethodID onFilterEventID;
156     jmethodID lnbInitID;
157     jmethodID onLnbEventID;
158     jmethodID onLnbDiseqcMessageID;
159     jmethodID onDvrRecordStatusID;
160     jmethodID onDvrPlaybackStatusID;
161     jmethodID descramblerInitID;
162     jmethodID linearBlockInitID;
163     jmethodID linearBlockSetInternalStateID;
164 };
165 
166 static fields_t gFields;
167 
168 
169 static int IP_V4_LENGTH = 4;
170 static int IP_V6_LENGTH = 16;
171 
DestroyCallback(const C2Buffer *,void * arg)172 void DestroyCallback(const C2Buffer * /* buf */, void *arg) {
173     android::sp<android::MediaEvent> event = (android::MediaEvent *)arg;
174     event->mAvHandleRefCnt--;
175     event->finalize();
176 }
177 
178 namespace android {
179 /////////////// LnbCallback ///////////////////////
LnbCallback(jobject lnbObj,LnbId id)180 LnbCallback::LnbCallback(jobject lnbObj, LnbId id) : mId(id) {
181     JNIEnv *env = AndroidRuntime::getJNIEnv();
182     mLnb = env->NewWeakGlobalRef(lnbObj);
183 }
184 
onEvent(LnbEventType lnbEventType)185 Return<void> LnbCallback::onEvent(LnbEventType lnbEventType) {
186     ALOGD("LnbCallback::onEvent, type=%d", lnbEventType);
187     JNIEnv *env = AndroidRuntime::getJNIEnv();
188     env->CallVoidMethod(
189             mLnb,
190             gFields.onLnbEventID,
191             (jint)lnbEventType);
192     return Void();
193 }
onDiseqcMessage(const hidl_vec<uint8_t> & diseqcMessage)194 Return<void> LnbCallback::onDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage) {
195     ALOGD("LnbCallback::onDiseqcMessage");
196     JNIEnv *env = AndroidRuntime::getJNIEnv();
197     jbyteArray array = env->NewByteArray(diseqcMessage.size());
198     env->SetByteArrayRegion(
199             array, 0, diseqcMessage.size(), reinterpret_cast<jbyte*>(diseqcMessage[0]));
200 
201     env->CallVoidMethod(
202             mLnb,
203             gFields.onLnbDiseqcMessageID,
204             array);
205     return Void();
206 }
207 
208 /////////////// Lnb ///////////////////////
209 
Lnb(sp<ILnb> sp,jobject obj)210 Lnb::Lnb(sp<ILnb> sp, jobject obj) : mLnbSp(sp) {
211     JNIEnv *env = AndroidRuntime::getJNIEnv();
212     mLnbObj = env->NewWeakGlobalRef(obj);
213 }
214 
~Lnb()215 Lnb::~Lnb() {
216     JNIEnv *env = AndroidRuntime::getJNIEnv();
217     env->DeleteWeakGlobalRef(mLnbObj);
218     mLnbObj = NULL;
219 }
220 
getILnb()221 sp<ILnb> Lnb::getILnb() {
222     return mLnbSp;
223 }
224 
225 /////////////// DvrCallback ///////////////////////
onRecordStatus(RecordStatus status)226 Return<void> DvrCallback::onRecordStatus(RecordStatus status) {
227     ALOGD("DvrCallback::onRecordStatus");
228     JNIEnv *env = AndroidRuntime::getJNIEnv();
229     env->CallVoidMethod(
230             mDvr,
231             gFields.onDvrRecordStatusID,
232             (jint) status);
233     return Void();
234 }
235 
onPlaybackStatus(PlaybackStatus status)236 Return<void> DvrCallback::onPlaybackStatus(PlaybackStatus status) {
237     ALOGD("DvrCallback::onPlaybackStatus");
238     JNIEnv *env = AndroidRuntime::getJNIEnv();
239     env->CallVoidMethod(
240             mDvr,
241             gFields.onDvrPlaybackStatusID,
242             (jint) status);
243     return Void();
244 }
245 
setDvr(const jobject dvr)246 void DvrCallback::setDvr(const jobject dvr) {
247     ALOGD("DvrCallback::setDvr");
248     JNIEnv *env = AndroidRuntime::getJNIEnv();
249     mDvr = env->NewWeakGlobalRef(dvr);
250 }
251 
~DvrCallback()252 DvrCallback::~DvrCallback() {
253     JNIEnv *env = AndroidRuntime::getJNIEnv();
254     if (mDvr != NULL) {
255         env->DeleteWeakGlobalRef(mDvr);
256         mDvr = NULL;
257     }
258 }
259 
260 /////////////// Dvr ///////////////////////
261 
Dvr(sp<IDvr> sp,jobject obj)262 Dvr::Dvr(sp<IDvr> sp, jobject obj) : mDvrSp(sp), mDvrMQEventFlag(nullptr) {
263     JNIEnv *env = AndroidRuntime::getJNIEnv();
264     mDvrObj = env->NewWeakGlobalRef(obj);
265 }
266 
~Dvr()267 Dvr::~Dvr() {
268     JNIEnv *env = AndroidRuntime::getJNIEnv();
269     env->DeleteWeakGlobalRef(mDvrObj);
270     mDvrObj = NULL;
271 }
272 
close()273 jint Dvr::close() {
274     Result r = mDvrSp->close();
275     if (r == Result::SUCCESS) {
276         EventFlag::deleteEventFlag(&mDvrMQEventFlag);
277     }
278     return (jint) r;
279 }
280 
getIDvr()281 sp<IDvr> Dvr::getIDvr() {
282     return mDvrSp;
283 }
284 
getDvrMQ()285 MQ& Dvr::getDvrMQ() {
286     return *mDvrMQ;
287 }
288 
289 /////////////// C2DataIdInfo ///////////////////////
290 
C2DataIdInfo(uint32_t index,uint64_t value)291 C2DataIdInfo::C2DataIdInfo(uint32_t index, uint64_t value) : C2Param(kParamSize, index) {
292     CHECK(isGlobal());
293     CHECK_EQ(C2Param::INFO, kind());
294     DummyInfo info{value};
295     memcpy(this + 1, static_cast<C2Param *>(&info) + 1, kParamSize - sizeof(C2Param));
296 }
297 
298 /////////////// MediaEvent ///////////////////////
299 
MediaEvent(sp<IFilter> iFilter,hidl_handle avHandle,uint64_t dataId,uint64_t dataLength,jobject obj)300 MediaEvent::MediaEvent(sp<IFilter> iFilter, hidl_handle avHandle,
301         uint64_t dataId, uint64_t dataLength, jobject obj) : mIFilter(iFilter),
302         mDataId(dataId), mDataLength(dataLength), mBuffer(nullptr),
303         mDataIdRefCnt(0), mAvHandleRefCnt(0), mIonHandle(nullptr) {
304     JNIEnv *env = AndroidRuntime::getJNIEnv();
305     mMediaEventObj = env->NewWeakGlobalRef(obj);
306     mAvHandle = native_handle_clone(avHandle.getNativeHandle());
307 }
308 
~MediaEvent()309 MediaEvent::~MediaEvent() {
310     JNIEnv *env = AndroidRuntime::getJNIEnv();
311     env->DeleteWeakGlobalRef(mMediaEventObj);
312     mMediaEventObj = NULL;
313     native_handle_delete(mAvHandle);
314     if (mIonHandle != NULL) {
315         delete mIonHandle;
316     }
317     std::shared_ptr<C2Buffer> pC2Buffer = mC2Buffer.lock();
318     if (pC2Buffer != NULL) {
319         pC2Buffer->unregisterOnDestroyNotify(&DestroyCallback, this);
320     }
321 }
322 
finalize()323 void MediaEvent::finalize() {
324     if (mAvHandleRefCnt == 0) {
325         mIFilter->releaseAvHandle(hidl_handle(mAvHandle), mDataIdRefCnt == 0 ? mDataId : 0);
326         native_handle_close(mAvHandle);
327     }
328 }
329 
getLinearBlock()330 jobject MediaEvent::getLinearBlock() {
331     ALOGD("MediaEvent::getLinearBlock");
332     if (mAvHandle == NULL) {
333         return NULL;
334     }
335     if (mLinearBlockObj != NULL) {
336         return mLinearBlockObj;
337     }
338     mIonHandle = new C2HandleIon(dup(mAvHandle->data[0]), mDataLength);
339     std::shared_ptr<C2LinearBlock> block = _C2BlockFactory::CreateLinearBlock(mIonHandle);
340 
341     JNIEnv *env = AndroidRuntime::getJNIEnv();
342     std::unique_ptr<JMediaCodecLinearBlock> context{new JMediaCodecLinearBlock};
343     context->mBlock = block;
344     std::shared_ptr<C2Buffer> pC2Buffer = context->toC2Buffer(0, mDataLength);
345     context->mBuffer = pC2Buffer;
346     mC2Buffer = pC2Buffer;
347     if (mAvHandle->numInts > 0) {
348         // use first int in the native_handle as the index
349         int index = mAvHandle->data[mAvHandle->numFds];
350         std::shared_ptr<C2Param> c2param = std::make_shared<C2DataIdInfo>(index, mDataId);
351         std::shared_ptr<C2Info> info(std::static_pointer_cast<C2Info>(c2param));
352         pC2Buffer->setInfo(info);
353     }
354     pC2Buffer->registerOnDestroyNotify(&DestroyCallback, this);
355     jobject linearBlock =
356             env->NewObject(
357                     env->FindClass("android/media/MediaCodec$LinearBlock"),
358                     gFields.linearBlockInitID);
359     env->CallVoidMethod(
360             linearBlock,
361             gFields.linearBlockSetInternalStateID,
362             (jlong)context.release(),
363             true);
364     mLinearBlockObj = env->NewWeakGlobalRef(linearBlock);
365     mAvHandleRefCnt++;
366     return mLinearBlockObj;
367 }
368 
getAudioHandle()369 uint64_t MediaEvent::getAudioHandle() {
370     mDataIdRefCnt++;
371     return mDataId;
372 }
373 
374 /////////////// FilterCallback ///////////////////////
375 
getSectionEvent(jobjectArray & arr,const std::vector<DemuxFilterEvent::Event> & events)376 jobjectArray FilterCallback::getSectionEvent(
377         jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) {
378     JNIEnv *env = AndroidRuntime::getJNIEnv();
379     jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/SectionEvent");
380     jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(IIII)V");
381 
382     for (int i = 0; i < events.size(); i++) {
383         auto event = events[i];
384         DemuxFilterSectionEvent sectionEvent = event.section();
385 
386         jint tableId = static_cast<jint>(sectionEvent.tableId);
387         jint version = static_cast<jint>(sectionEvent.version);
388         jint sectionNum = static_cast<jint>(sectionEvent.sectionNum);
389         jint dataLength = static_cast<jint>(sectionEvent.dataLength);
390 
391         jobject obj =
392                 env->NewObject(eventClazz, eventInit, tableId, version, sectionNum, dataLength);
393         env->SetObjectArrayElement(arr, i, obj);
394     }
395     return arr;
396 }
397 
getMediaEvent(jobjectArray & arr,const std::vector<DemuxFilterEvent::Event> & events)398 jobjectArray FilterCallback::getMediaEvent(
399         jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) {
400     JNIEnv *env = AndroidRuntime::getJNIEnv();
401     jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/MediaEvent");
402     jmethodID eventInit = env->GetMethodID(eventClazz,
403             "<init>",
404             "(IZJJJLandroid/media/MediaCodec$LinearBlock;"
405             "ZJIZLandroid/media/tv/tuner/filter/AudioDescriptor;)V");
406     jfieldID eventContext = env->GetFieldID(eventClazz, "mNativeContext", "J");
407 
408     for (int i = 0; i < events.size(); i++) {
409         auto event = events[i];
410         DemuxFilterMediaEvent mediaEvent = event.media();
411 
412         jobject audioDescriptor = NULL;
413         if (mediaEvent.extraMetaData.getDiscriminator()
414                 == DemuxFilterMediaEvent::ExtraMetaData::hidl_discriminator::audio) {
415             jclass adClazz = env->FindClass("android/media/tv/tuner/filter/AudioDescriptor");
416             jmethodID adInit = env->GetMethodID(adClazz, "<init>", "(BBCBBB)V");
417 
418             AudioExtraMetaData ad = mediaEvent.extraMetaData.audio();
419             jbyte adFade = static_cast<jbyte>(ad.adFade);
420             jbyte adPan = static_cast<jbyte>(ad.adPan);
421             jchar versionTextTag = static_cast<jchar>(ad.versionTextTag);
422             jbyte adGainCenter = static_cast<jbyte>(ad.adGainCenter);
423             jbyte adGainFront = static_cast<jbyte>(ad.adGainFront);
424             jbyte adGainSurround = static_cast<jbyte>(ad.adGainSurround);
425 
426             audioDescriptor =
427                     env->NewObject(adClazz, adInit, adFade, adPan, versionTextTag, adGainCenter,
428                             adGainFront, adGainSurround);
429         }
430 
431         jlong dataLength = static_cast<jlong>(mediaEvent.dataLength);
432 
433         jint streamId = static_cast<jint>(mediaEvent.streamId);
434         jboolean isPtsPresent = static_cast<jboolean>(mediaEvent.isPtsPresent);
435         jlong pts = static_cast<jlong>(mediaEvent.pts);
436         jlong offset = static_cast<jlong>(mediaEvent.offset);
437         jboolean isSecureMemory = static_cast<jboolean>(mediaEvent.isSecureMemory);
438         jlong avDataId = static_cast<jlong>(mediaEvent.avDataId);
439         jint mpuSequenceNumber = static_cast<jint>(mediaEvent.mpuSequenceNumber);
440         jboolean isPesPrivateData = static_cast<jboolean>(mediaEvent.isPesPrivateData);
441 
442         jobject obj =
443                 env->NewObject(eventClazz, eventInit, streamId, isPtsPresent, pts, dataLength,
444                 offset, NULL, isSecureMemory, avDataId, mpuSequenceNumber, isPesPrivateData,
445                 audioDescriptor);
446 
447         if (mediaEvent.avMemory.getNativeHandle() != NULL || mediaEvent.avDataId != 0) {
448             sp<MediaEvent> mediaEventSp =
449                            new MediaEvent(mIFilter, mediaEvent.avMemory,
450                                mediaEvent.avDataId, dataLength, obj);
451             mediaEventSp->mAvHandleRefCnt++;
452             env->SetLongField(obj, eventContext, (jlong) mediaEventSp.get());
453             mediaEventSp->incStrong(obj);
454         }
455 
456         env->SetObjectArrayElement(arr, i, obj);
457     }
458     return arr;
459 }
460 
getPesEvent(jobjectArray & arr,const std::vector<DemuxFilterEvent::Event> & events)461 jobjectArray FilterCallback::getPesEvent(
462         jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) {
463     JNIEnv *env = AndroidRuntime::getJNIEnv();
464     jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/PesEvent");
465     jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(III)V");
466 
467     for (int i = 0; i < events.size(); i++) {
468         auto event = events[i];
469         DemuxFilterPesEvent pesEvent = event.pes();
470 
471         jint streamId = static_cast<jint>(pesEvent.streamId);
472         jint dataLength = static_cast<jint>(pesEvent.dataLength);
473         jint mpuSequenceNumber = static_cast<jint>(pesEvent.mpuSequenceNumber);
474 
475         jobject obj =
476                 env->NewObject(eventClazz, eventInit, streamId, dataLength, mpuSequenceNumber);
477         env->SetObjectArrayElement(arr, i, obj);
478     }
479     return arr;
480 }
481 
getTsRecordEvent(jobjectArray & arr,const std::vector<DemuxFilterEvent::Event> & events)482 jobjectArray FilterCallback::getTsRecordEvent(
483         jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) {
484     JNIEnv *env = AndroidRuntime::getJNIEnv();
485     jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/TsRecordEvent");
486     jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(IIIJ)V");
487 
488     for (int i = 0; i < events.size(); i++) {
489         auto event = events[i];
490         DemuxFilterTsRecordEvent tsRecordEvent = event.tsRecord();
491         DemuxPid pid = tsRecordEvent.pid;
492 
493         jint jpid = static_cast<jint>(Constant::INVALID_TS_PID);
494 
495         if (pid.getDiscriminator() == DemuxPid::hidl_discriminator::tPid) {
496             jpid = static_cast<jint>(pid.tPid());
497         } else if (pid.getDiscriminator() == DemuxPid::hidl_discriminator::mmtpPid) {
498             jpid = static_cast<jint>(pid.mmtpPid());
499         }
500 
501         jint sc = 0;
502 
503         if (tsRecordEvent.scIndexMask.getDiscriminator()
504                 == DemuxFilterTsRecordEvent::ScIndexMask::hidl_discriminator::sc) {
505             sc = static_cast<jint>(tsRecordEvent.scIndexMask.sc());
506         } else if (tsRecordEvent.scIndexMask.getDiscriminator()
507                 == DemuxFilterTsRecordEvent::ScIndexMask::hidl_discriminator::scHevc) {
508             sc = static_cast<jint>(tsRecordEvent.scIndexMask.scHevc());
509         }
510 
511         jint ts = static_cast<jint>(tsRecordEvent.tsIndexMask);
512 
513         jlong byteNumber = static_cast<jlong>(tsRecordEvent.byteNumber);
514 
515         jobject obj =
516                 env->NewObject(eventClazz, eventInit, jpid, ts, sc, byteNumber);
517         env->SetObjectArrayElement(arr, i, obj);
518     }
519     return arr;
520 }
521 
getMmtpRecordEvent(jobjectArray & arr,const std::vector<DemuxFilterEvent::Event> & events)522 jobjectArray FilterCallback::getMmtpRecordEvent(
523         jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) {
524     JNIEnv *env = AndroidRuntime::getJNIEnv();
525     jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/MmtpRecordEvent");
526     jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(IJ)V");
527 
528     for (int i = 0; i < events.size(); i++) {
529         auto event = events[i];
530         DemuxFilterMmtpRecordEvent mmtpRecordEvent = event.mmtpRecord();
531 
532         jint scHevcIndexMask = static_cast<jint>(mmtpRecordEvent.scHevcIndexMask);
533         jlong byteNumber = static_cast<jlong>(mmtpRecordEvent.byteNumber);
534 
535         jobject obj =
536                 env->NewObject(eventClazz, eventInit, scHevcIndexMask, byteNumber);
537         env->SetObjectArrayElement(arr, i, obj);
538     }
539     return arr;
540 }
541 
getDownloadEvent(jobjectArray & arr,const std::vector<DemuxFilterEvent::Event> & events)542 jobjectArray FilterCallback::getDownloadEvent(
543         jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) {
544     JNIEnv *env = AndroidRuntime::getJNIEnv();
545     jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/DownloadEvent");
546     jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(IIIII)V");
547 
548     for (int i = 0; i < events.size(); i++) {
549         auto event = events[i];
550         DemuxFilterDownloadEvent downloadEvent = event.download();
551 
552         jint itemId = static_cast<jint>(downloadEvent.itemId);
553         jint mpuSequenceNumber = static_cast<jint>(downloadEvent.mpuSequenceNumber);
554         jint itemFragmentIndex = static_cast<jint>(downloadEvent.itemFragmentIndex);
555         jint lastItemFragmentIndex = static_cast<jint>(downloadEvent.lastItemFragmentIndex);
556         jint dataLength = static_cast<jint>(downloadEvent.dataLength);
557 
558         jobject obj =
559                 env->NewObject(eventClazz, eventInit, itemId, mpuSequenceNumber, itemFragmentIndex,
560                         lastItemFragmentIndex, dataLength);
561         env->SetObjectArrayElement(arr, i, obj);
562     }
563     return arr;
564 }
565 
getIpPayloadEvent(jobjectArray & arr,const std::vector<DemuxFilterEvent::Event> & events)566 jobjectArray FilterCallback::getIpPayloadEvent(
567         jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) {
568     JNIEnv *env = AndroidRuntime::getJNIEnv();
569     jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/IpPayloadEvent");
570     jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(I)V");
571 
572     for (int i = 0; i < events.size(); i++) {
573         auto event = events[i];
574         DemuxFilterIpPayloadEvent ipPayloadEvent = event.ipPayload();
575         jint dataLength = static_cast<jint>(ipPayloadEvent.dataLength);
576         jobject obj = env->NewObject(eventClazz, eventInit, dataLength);
577         env->SetObjectArrayElement(arr, i, obj);
578     }
579     return arr;
580 }
581 
getTemiEvent(jobjectArray & arr,const std::vector<DemuxFilterEvent::Event> & events)582 jobjectArray FilterCallback::getTemiEvent(
583         jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) {
584     JNIEnv *env = AndroidRuntime::getJNIEnv();
585     jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/TemiEvent");
586     jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(JB[B)V");
587 
588     for (int i = 0; i < events.size(); i++) {
589         auto event = events[i];
590         DemuxFilterTemiEvent temiEvent = event.temi();
591         jlong pts = static_cast<jlong>(temiEvent.pts);
592         jbyte descrTag = static_cast<jbyte>(temiEvent.descrTag);
593         std::vector<uint8_t> descrData = temiEvent.descrData;
594 
595         jbyteArray array = env->NewByteArray(descrData.size());
596         env->SetByteArrayRegion(
597                 array, 0, descrData.size(), reinterpret_cast<jbyte*>(&descrData[0]));
598 
599         jobject obj = env->NewObject(eventClazz, eventInit, pts, descrTag, array);
600         env->SetObjectArrayElement(arr, i, obj);
601     }
602     return arr;
603 }
604 
onFilterEvent(const DemuxFilterEvent & filterEvent)605 Return<void> FilterCallback::onFilterEvent(const DemuxFilterEvent& filterEvent) {
606     ALOGD("FilterCallback::onFilterEvent");
607 
608     JNIEnv *env = AndroidRuntime::getJNIEnv();
609 
610     std::vector<DemuxFilterEvent::Event> events = filterEvent.events;
611     jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/FilterEvent");
612     jobjectArray array = env->NewObjectArray(events.size(), eventClazz, NULL);
613 
614     if (!events.empty()) {
615         auto event = events[0];
616         switch (event.getDiscriminator()) {
617             case DemuxFilterEvent::Event::hidl_discriminator::media: {
618                 array = getMediaEvent(array, events);
619                 break;
620             }
621             case DemuxFilterEvent::Event::hidl_discriminator::section: {
622                 array = getSectionEvent(array, events);
623                 break;
624             }
625             case DemuxFilterEvent::Event::hidl_discriminator::pes: {
626                 array = getPesEvent(array, events);
627                 break;
628             }
629             case DemuxFilterEvent::Event::hidl_discriminator::tsRecord: {
630                 array = getTsRecordEvent(array, events);
631                 break;
632             }
633             case DemuxFilterEvent::Event::hidl_discriminator::mmtpRecord: {
634                 array = getMmtpRecordEvent(array, events);
635                 break;
636             }
637             case DemuxFilterEvent::Event::hidl_discriminator::download: {
638                 array = getDownloadEvent(array, events);
639                 break;
640             }
641             case DemuxFilterEvent::Event::hidl_discriminator::ipPayload: {
642                 array = getIpPayloadEvent(array, events);
643                 break;
644             }
645             case DemuxFilterEvent::Event::hidl_discriminator::temi: {
646                 array = getTemiEvent(array, events);
647                 break;
648             }
649             default: {
650                 break;
651             }
652         }
653     }
654     env->CallVoidMethod(
655             mFilter,
656             gFields.onFilterEventID,
657             array);
658     return Void();
659 }
660 
661 
onFilterStatus(const DemuxFilterStatus status)662 Return<void> FilterCallback::onFilterStatus(const DemuxFilterStatus status) {
663     ALOGD("FilterCallback::onFilterStatus");
664     JNIEnv *env = AndroidRuntime::getJNIEnv();
665     env->CallVoidMethod(
666             mFilter,
667             gFields.onFilterStatusID,
668             (jint)status);
669     return Void();
670 }
671 
setFilter(const sp<Filter> filter)672 void FilterCallback::setFilter(const sp<Filter> filter) {
673     ALOGD("FilterCallback::setFilter");
674     mFilter = filter->mFilterObj;
675     mIFilter = filter->mFilterSp;
676 }
677 
~FilterCallback()678 FilterCallback::~FilterCallback() {
679     JNIEnv *env = AndroidRuntime::getJNIEnv();
680     if (mFilter != NULL) {
681         env->DeleteWeakGlobalRef(mFilter);
682         mFilter = NULL;
683     }
684 }
685 
686 /////////////// Filter ///////////////////////
687 
Filter(sp<IFilter> sp,jobject obj)688 Filter::Filter(sp<IFilter> sp, jobject obj) : mFilterSp(sp) {
689     JNIEnv *env = AndroidRuntime::getJNIEnv();
690     mFilterObj = env->NewWeakGlobalRef(obj);
691 }
692 
~Filter()693 Filter::~Filter() {
694     JNIEnv *env = AndroidRuntime::getJNIEnv();
695 
696     env->DeleteWeakGlobalRef(mFilterObj);
697     mFilterObj = NULL;
698     EventFlag::deleteEventFlag(&mFilterMQEventFlag);
699 }
700 
close()701 int Filter::close() {
702     Result r = mFilterSp->close();
703     if (r == Result::SUCCESS) {
704         EventFlag::deleteEventFlag(&mFilterMQEventFlag);
705     }
706     return (int)r;
707 }
708 
getIFilter()709 sp<IFilter> Filter::getIFilter() {
710     return mFilterSp;
711 }
712 
713 /////////////// TimeFilter ///////////////////////
714 
TimeFilter(sp<ITimeFilter> sp,jobject obj)715 TimeFilter::TimeFilter(sp<ITimeFilter> sp, jobject obj) : mTimeFilterSp(sp) {
716     JNIEnv *env = AndroidRuntime::getJNIEnv();
717     mTimeFilterObj = env->NewWeakGlobalRef(obj);
718 }
719 
~TimeFilter()720 TimeFilter::~TimeFilter() {
721     ALOGD("~TimeFilter");
722     JNIEnv *env = AndroidRuntime::getJNIEnv();
723 
724     env->DeleteWeakGlobalRef(mTimeFilterObj);
725     mTimeFilterObj = NULL;
726 }
727 
getITimeFilter()728 sp<ITimeFilter> TimeFilter::getITimeFilter() {
729     return mTimeFilterSp;
730 }
731 
732 /////////////// FrontendCallback ///////////////////////
733 
FrontendCallback(jweak tunerObj,FrontendId id)734 FrontendCallback::FrontendCallback(jweak tunerObj, FrontendId id) : mObject(tunerObj), mId(id) {}
735 
onEvent(FrontendEventType frontendEventType)736 Return<void> FrontendCallback::onEvent(FrontendEventType frontendEventType) {
737     ALOGD("FrontendCallback::onEvent, type=%d", frontendEventType);
738     JNIEnv *env = AndroidRuntime::getJNIEnv();
739     env->CallVoidMethod(
740             mObject,
741             gFields.onFrontendEventID,
742             (jint)frontendEventType);
743     return Void();
744 }
745 
onScanMessage(FrontendScanMessageType type,const FrontendScanMessage & message)746 Return<void> FrontendCallback::onScanMessage(FrontendScanMessageType type, const FrontendScanMessage& message) {
747     ALOGD("FrontendCallback::onScanMessage, type=%d", type);
748     JNIEnv *env = AndroidRuntime::getJNIEnv();
749     jclass clazz = env->FindClass("android/media/tv/tuner/Tuner");
750     switch(type) {
751         case FrontendScanMessageType::LOCKED: {
752             if (message.isLocked()) {
753                 env->CallVoidMethod(
754                         mObject,
755                         env->GetMethodID(clazz, "onLocked", "()V"));
756             }
757             break;
758         }
759         case FrontendScanMessageType::END: {
760             if (message.isEnd()) {
761                 env->CallVoidMethod(
762                         mObject,
763                         env->GetMethodID(clazz, "onScanStopped", "()V"));
764             }
765             break;
766         }
767         case FrontendScanMessageType::PROGRESS_PERCENT: {
768             env->CallVoidMethod(
769                     mObject,
770                     env->GetMethodID(clazz, "onProgress", "(I)V"),
771                     (jint) message.progressPercent());
772             break;
773         }
774         case FrontendScanMessageType::FREQUENCY: {
775             std::vector<uint32_t> v = message.frequencies();
776             jintArray freqs = env->NewIntArray(v.size());
777             env->SetIntArrayRegion(freqs, 0, v.size(), reinterpret_cast<jint*>(&v[0]));
778 
779             env->CallVoidMethod(
780                     mObject,
781                     env->GetMethodID(clazz, "onFrequenciesReport", "([I)V"),
782                     freqs);
783             break;
784         }
785         case FrontendScanMessageType::SYMBOL_RATE: {
786             std::vector<uint32_t> v = message.symbolRates();
787             jintArray symbolRates = env->NewIntArray(v.size());
788             env->SetIntArrayRegion(symbolRates, 0, v.size(), reinterpret_cast<jint*>(&v[0]));
789 
790             env->CallVoidMethod(
791                     mObject,
792                     env->GetMethodID(clazz, "onSymbolRates", "([I)V"),
793                     symbolRates);
794             break;
795         }
796         case FrontendScanMessageType::HIERARCHY: {
797             env->CallVoidMethod(
798                     mObject,
799                     env->GetMethodID(clazz, "onHierarchy", "(I)V"),
800                     (jint) message.hierarchy());
801             break;
802         }
803         case FrontendScanMessageType::ANALOG_TYPE: {
804             env->CallVoidMethod(
805                     mObject,
806                     env->GetMethodID(clazz, "onSignalType", "(I)V"),
807                     (jint) message.analogType());
808             break;
809         }
810         case FrontendScanMessageType::PLP_IDS: {
811             std::vector<uint8_t> v = message.plpIds();
812             std::vector<jint> jintV(v.begin(), v.end());
813             jintArray plpIds = env->NewIntArray(v.size());
814             env->SetIntArrayRegion(plpIds, 0, jintV.size(), &jintV[0]);
815 
816             env->CallVoidMethod(
817                     mObject,
818                     env->GetMethodID(clazz, "onPlpIds", "([I)V"),
819                     plpIds);
820             break;
821         }
822         case FrontendScanMessageType::GROUP_IDS: {
823             std::vector<uint8_t> v = message.groupIds();
824             std::vector<jint> jintV(v.begin(), v.end());
825             jintArray groupIds = env->NewIntArray(v.size());
826             env->SetIntArrayRegion(groupIds, 0, jintV.size(), &jintV[0]);
827 
828             env->CallVoidMethod(
829                     mObject,
830                     env->GetMethodID(clazz, "onGroupIds", "([I)V"),
831                     groupIds);
832             break;
833         }
834         case FrontendScanMessageType::INPUT_STREAM_IDS: {
835             std::vector<uint16_t> v = message.inputStreamIds();
836             std::vector<jint> jintV(v.begin(), v.end());
837             jintArray streamIds = env->NewIntArray(v.size());
838             env->SetIntArrayRegion(streamIds, 0, jintV.size(), &jintV[0]);
839 
840             env->CallVoidMethod(
841                     mObject,
842                     env->GetMethodID(clazz, "onInputStreamIds", "([I)V"),
843                     streamIds);
844             break;
845         }
846         case FrontendScanMessageType::STANDARD: {
847             FrontendScanMessage::Standard std = message.std();
848             jint standard;
849             if (std.getDiscriminator() == FrontendScanMessage::Standard::hidl_discriminator::sStd) {
850                 standard = (jint) std.sStd();
851                 env->CallVoidMethod(
852                         mObject,
853                         env->GetMethodID(clazz, "onDvbsStandard", "(I)V"),
854                         standard);
855             } else if (std.getDiscriminator() == FrontendScanMessage::Standard::hidl_discriminator::tStd) {
856                 standard = (jint) std.tStd();
857                 env->CallVoidMethod(
858                         mObject,
859                         env->GetMethodID(clazz, "onDvbtStandard", "(I)V"),
860                         standard);
861             } else if (std.getDiscriminator() == FrontendScanMessage::Standard::hidl_discriminator::sifStd) {
862                 standard = (jint) std.sifStd();
863                 env->CallVoidMethod(
864                         mObject,
865                         env->GetMethodID(clazz, "onAnalogSifStandard", "(I)V"),
866                         standard);
867             }
868             break;
869         }
870         case FrontendScanMessageType::ATSC3_PLP_INFO: {
871             jclass plpClazz = env->FindClass("android/media/tv/tuner/frontend/Atsc3PlpInfo");
872             jmethodID init = env->GetMethodID(plpClazz, "<init>", "(IZ)V");
873             std::vector<FrontendScanAtsc3PlpInfo> plpInfos = message.atsc3PlpInfos();
874             jobjectArray array = env->NewObjectArray(plpInfos.size(), plpClazz, NULL);
875 
876             for (int i = 0; i < plpInfos.size(); i++) {
877                 auto info = plpInfos[i];
878                 jint plpId = (jint) info.plpId;
879                 jboolean lls = (jboolean) info.bLlsFlag;
880 
881                 jobject obj = env->NewObject(plpClazz, init, plpId, lls);
882                 env->SetObjectArrayElement(array, i, obj);
883             }
884             env->CallVoidMethod(
885                     mObject,
886                     env->GetMethodID(clazz, "onAtsc3PlpInfos", "([Landroid/media/tv/tuner/frontend/Atsc3PlpInfo;)V"),
887                     array);
888             break;
889         }
890     }
891     return Void();
892 }
893 
894 /////////////// Tuner ///////////////////////
895 
896 sp<ITuner> JTuner::mTuner;
897 
JTuner(JNIEnv * env,jobject thiz)898 JTuner::JTuner(JNIEnv *env, jobject thiz)
899     : mClass(NULL) {
900     jclass clazz = env->GetObjectClass(thiz);
901     CHECK(clazz != NULL);
902 
903     mClass = (jclass)env->NewGlobalRef(clazz);
904     mObject = env->NewWeakGlobalRef(thiz);
905     if (mTuner == NULL) {
906         mTuner = getTunerService();
907     }
908 }
909 
~JTuner()910 JTuner::~JTuner() {
911     if (mFe != NULL) {
912         mFe->close();
913     }
914     if (mDemux != NULL) {
915         mDemux->close();
916     }
917     JNIEnv *env = AndroidRuntime::getJNIEnv();
918 
919     env->DeleteWeakGlobalRef(mObject);
920     env->DeleteGlobalRef(mClass);
921     mTuner = NULL;
922     mClass = NULL;
923     mObject = NULL;
924 }
925 
getTunerService()926 sp<ITuner> JTuner::getTunerService() {
927     if (mTuner == nullptr) {
928         mTuner = ITuner::getService();
929 
930         if (mTuner == nullptr) {
931             ALOGW("Failed to get tuner service.");
932         }
933     }
934     return mTuner;
935 }
936 
getFrontendIds()937 jobject JTuner::getFrontendIds() {
938     ALOGD("JTuner::getFrontendIds()");
939     mTuner->getFrontendIds([&](Result, const hidl_vec<FrontendId>& frontendIds) {
940         mFeIds = frontendIds;
941     });
942     if (mFeIds.size() == 0) {
943         ALOGW("Frontend isn't available");
944         return NULL;
945     }
946 
947     JNIEnv *env = AndroidRuntime::getJNIEnv();
948     jclass arrayListClazz = env->FindClass("java/util/ArrayList");
949     jmethodID arrayListAdd = env->GetMethodID(arrayListClazz, "add", "(Ljava/lang/Object;)Z");
950     jobject obj = env->NewObject(arrayListClazz, env->GetMethodID(arrayListClazz, "<init>", "()V"));
951 
952     jclass integerClazz = env->FindClass("java/lang/Integer");
953     jmethodID intInit = env->GetMethodID(integerClazz, "<init>", "(I)V");
954 
955     for (int i=0; i < mFeIds.size(); i++) {
956        jobject idObj = env->NewObject(integerClazz, intInit, mFeIds[i]);
957        env->CallBooleanMethod(obj, arrayListAdd, idObj);
958     }
959     return obj;
960 }
961 
openFrontendById(int id)962 jobject JTuner::openFrontendById(int id) {
963     sp<IFrontend> fe;
964     Result res;
965     mTuner->openFrontendById(id, [&](Result r, const sp<IFrontend>& frontend) {
966         fe = frontend;
967         res = r;
968     });
969     if (res != Result::SUCCESS || fe == nullptr) {
970         ALOGE("Failed to open frontend");
971         return NULL;
972     }
973     mFe = fe;
974     mFeId = id;
975     if (mDemux != NULL) {
976         mDemux->setFrontendDataSource(mFeId);
977     }
978     sp<FrontendCallback> feCb = new FrontendCallback(mObject, id);
979     fe->setCallback(feCb);
980 
981     jint jId = (jint) id;
982 
983     JNIEnv *env = AndroidRuntime::getJNIEnv();
984     // TODO: add more fields to frontend
985     return env->NewObject(
986             env->FindClass("android/media/tv/tuner/Tuner$Frontend"),
987             gFields.frontendInitID,
988             mObject,
989             (jint) jId);
990 }
991 
closeFrontendById(int id)992 jint JTuner::closeFrontendById(int id) {
993     if (mFe != NULL && mFeId == id) {
994         Result r = mFe->close();
995         return (jint) r;
996     }
997     return (jint) Result::SUCCESS;
998 }
999 
getAnalogFrontendCaps(JNIEnv * env,FrontendInfo::FrontendCapabilities & caps)1000 jobject JTuner::getAnalogFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) {
1001     jclass clazz = env->FindClass("android/media/tv/tuner/frontend/AnalogFrontendCapabilities");
1002     jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(II)V");
1003 
1004     jint typeCap = caps.analogCaps().typeCap;
1005     jint sifStandardCap = caps.analogCaps().sifStandardCap;
1006     return env->NewObject(clazz, capsInit, typeCap, sifStandardCap);
1007 }
1008 
getAtsc3FrontendCaps(JNIEnv * env,FrontendInfo::FrontendCapabilities & caps)1009 jobject JTuner::getAtsc3FrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) {
1010     jclass clazz = env->FindClass("android/media/tv/tuner/frontend/Atsc3FrontendCapabilities");
1011     jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(IIIIII)V");
1012 
1013     jint bandwidthCap = caps.atsc3Caps().bandwidthCap;
1014     jint modulationCap = caps.atsc3Caps().modulationCap;
1015     jint timeInterleaveModeCap = caps.atsc3Caps().timeInterleaveModeCap;
1016     jint codeRateCap = caps.atsc3Caps().codeRateCap;
1017     jint fecCap = caps.atsc3Caps().fecCap;
1018     jint demodOutputFormatCap = caps.atsc3Caps().demodOutputFormatCap;
1019 
1020     return env->NewObject(clazz, capsInit, bandwidthCap, modulationCap, timeInterleaveModeCap,
1021             codeRateCap, fecCap, demodOutputFormatCap);
1022 }
1023 
getAtscFrontendCaps(JNIEnv * env,FrontendInfo::FrontendCapabilities & caps)1024 jobject JTuner::getAtscFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) {
1025     jclass clazz = env->FindClass("android/media/tv/tuner/frontend/AtscFrontendCapabilities");
1026     jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(I)V");
1027 
1028     jint modulationCap = caps.atscCaps().modulationCap;
1029 
1030     return env->NewObject(clazz, capsInit, modulationCap);
1031 }
1032 
getDvbcFrontendCaps(JNIEnv * env,FrontendInfo::FrontendCapabilities & caps)1033 jobject JTuner::getDvbcFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) {
1034     jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbcFrontendCapabilities");
1035     jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(III)V");
1036 
1037     jint modulationCap = caps.dvbcCaps().modulationCap;
1038     jint fecCap = caps.dvbcCaps().fecCap;
1039     jint annexCap = caps.dvbcCaps().annexCap;
1040 
1041     return env->NewObject(clazz, capsInit, modulationCap, fecCap, annexCap);
1042 }
1043 
getDvbsFrontendCaps(JNIEnv * env,FrontendInfo::FrontendCapabilities & caps)1044 jobject JTuner::getDvbsFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) {
1045     jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbsFrontendCapabilities");
1046     jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(IJI)V");
1047 
1048     jint modulationCap = caps.dvbsCaps().modulationCap;
1049     jlong innerfecCap = caps.dvbsCaps().innerfecCap;
1050     jint standard = caps.dvbsCaps().standard;
1051 
1052     return env->NewObject(clazz, capsInit, modulationCap, innerfecCap, standard);
1053 }
1054 
getDvbtFrontendCaps(JNIEnv * env,FrontendInfo::FrontendCapabilities & caps)1055 jobject JTuner::getDvbtFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) {
1056     jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbtFrontendCapabilities");
1057     jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(IIIIIIZZ)V");
1058 
1059     jint transmissionModeCap = caps.dvbtCaps().transmissionModeCap;
1060     jint bandwidthCap = caps.dvbtCaps().bandwidthCap;
1061     jint constellationCap = caps.dvbtCaps().constellationCap;
1062     jint coderateCap = caps.dvbtCaps().coderateCap;
1063     jint hierarchyCap = caps.dvbtCaps().hierarchyCap;
1064     jint guardIntervalCap = caps.dvbtCaps().guardIntervalCap;
1065     jboolean isT2Supported = caps.dvbtCaps().isT2Supported;
1066     jboolean isMisoSupported = caps.dvbtCaps().isMisoSupported;
1067 
1068     return env->NewObject(clazz, capsInit, transmissionModeCap, bandwidthCap, constellationCap,
1069             coderateCap, hierarchyCap, guardIntervalCap, isT2Supported, isMisoSupported);
1070 }
1071 
getIsdbs3FrontendCaps(JNIEnv * env,FrontendInfo::FrontendCapabilities & caps)1072 jobject JTuner::getIsdbs3FrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) {
1073     jclass clazz = env->FindClass("android/media/tv/tuner/frontend/Isdbs3FrontendCapabilities");
1074     jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(II)V");
1075 
1076     jint modulationCap = caps.isdbs3Caps().modulationCap;
1077     jint coderateCap = caps.isdbs3Caps().coderateCap;
1078 
1079     return env->NewObject(clazz, capsInit, modulationCap, coderateCap);
1080 }
1081 
getIsdbsFrontendCaps(JNIEnv * env,FrontendInfo::FrontendCapabilities & caps)1082 jobject JTuner::getIsdbsFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) {
1083     jclass clazz = env->FindClass("android/media/tv/tuner/frontend/IsdbsFrontendCapabilities");
1084     jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(II)V");
1085 
1086     jint modulationCap = caps.isdbsCaps().modulationCap;
1087     jint coderateCap = caps.isdbsCaps().coderateCap;
1088 
1089     return env->NewObject(clazz, capsInit, modulationCap, coderateCap);
1090 }
1091 
getIsdbtFrontendCaps(JNIEnv * env,FrontendInfo::FrontendCapabilities & caps)1092 jobject JTuner::getIsdbtFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) {
1093     jclass clazz = env->FindClass("android/media/tv/tuner/frontend/IsdbtFrontendCapabilities");
1094     jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(IIIII)V");
1095 
1096     jint modeCap = caps.isdbtCaps().modeCap;
1097     jint bandwidthCap = caps.isdbtCaps().bandwidthCap;
1098     jint modulationCap = caps.isdbtCaps().modulationCap;
1099     jint coderateCap = caps.isdbtCaps().coderateCap;
1100     jint guardIntervalCap = caps.isdbtCaps().guardIntervalCap;
1101 
1102     return env->NewObject(clazz, capsInit, modeCap, bandwidthCap, modulationCap, coderateCap,
1103             guardIntervalCap);
1104 }
1105 
getFrontendInfo(int id)1106 jobject JTuner::getFrontendInfo(int id) {
1107     FrontendInfo feInfo;
1108     Result res;
1109     mTuner->getFrontendInfo(id, [&](Result r, const FrontendInfo& info) {
1110         feInfo = info;
1111         res = r;
1112     });
1113     if (res != Result::SUCCESS) {
1114         return NULL;
1115     }
1116 
1117     JNIEnv *env = AndroidRuntime::getJNIEnv();
1118     jclass clazz = env->FindClass("android/media/tv/tuner/frontend/FrontendInfo");
1119     jmethodID infoInit = env->GetMethodID(clazz, "<init>",
1120             "(IIIIIIII[ILandroid/media/tv/tuner/frontend/FrontendCapabilities;)V");
1121 
1122     jint type = (jint) feInfo.type;
1123     jint minFrequency = feInfo.minFrequency;
1124     jint maxFrequency = feInfo.maxFrequency;
1125     jint minSymbolRate = feInfo.minSymbolRate;
1126     jint maxSymbolRate = feInfo.maxSymbolRate;
1127     jint acquireRange = feInfo.acquireRange;
1128     jint exclusiveGroupId = feInfo.exclusiveGroupId;
1129     jintArray statusCaps = env->NewIntArray(feInfo.statusCaps.size());
1130     env->SetIntArrayRegion(
1131             statusCaps, 0, feInfo.statusCaps.size(),
1132             reinterpret_cast<jint*>(&feInfo.statusCaps[0]));
1133     FrontendInfo::FrontendCapabilities caps = feInfo.frontendCaps;
1134 
1135     jobject jcaps = NULL;
1136     switch(feInfo.type) {
1137         case FrontendType::ANALOG:
1138             if (FrontendInfo::FrontendCapabilities::hidl_discriminator::analogCaps
1139                     == caps.getDiscriminator()) {
1140                 jcaps = getAnalogFrontendCaps(env, caps);
1141             }
1142             break;
1143         case FrontendType::ATSC3:
1144             if (FrontendInfo::FrontendCapabilities::hidl_discriminator::atsc3Caps
1145                     == caps.getDiscriminator()) {
1146                 jcaps = getAtsc3FrontendCaps(env, caps);
1147             }
1148             break;
1149         case FrontendType::ATSC:
1150             if (FrontendInfo::FrontendCapabilities::hidl_discriminator::atscCaps
1151                     == caps.getDiscriminator()) {
1152                 jcaps = getAtscFrontendCaps(env, caps);
1153             }
1154             break;
1155         case FrontendType::DVBC:
1156             if (FrontendInfo::FrontendCapabilities::hidl_discriminator::dvbcCaps
1157                     == caps.getDiscriminator()) {
1158                 jcaps = getDvbcFrontendCaps(env, caps);
1159             }
1160             break;
1161         case FrontendType::DVBS:
1162             if (FrontendInfo::FrontendCapabilities::hidl_discriminator::dvbsCaps
1163                     == caps.getDiscriminator()) {
1164                 jcaps = getDvbsFrontendCaps(env, caps);
1165             }
1166             break;
1167         case FrontendType::DVBT:
1168             if (FrontendInfo::FrontendCapabilities::hidl_discriminator::dvbtCaps
1169                     == caps.getDiscriminator()) {
1170                 jcaps = getDvbtFrontendCaps(env, caps);
1171             }
1172             break;
1173         case FrontendType::ISDBS:
1174             if (FrontendInfo::FrontendCapabilities::hidl_discriminator::isdbsCaps
1175                     == caps.getDiscriminator()) {
1176                 jcaps = getIsdbsFrontendCaps(env, caps);
1177             }
1178             break;
1179         case FrontendType::ISDBS3:
1180             if (FrontendInfo::FrontendCapabilities::hidl_discriminator::isdbs3Caps
1181                     == caps.getDiscriminator()) {
1182                 jcaps = getIsdbs3FrontendCaps(env, caps);
1183             }
1184             break;
1185         case FrontendType::ISDBT:
1186             if (FrontendInfo::FrontendCapabilities::hidl_discriminator::isdbtCaps
1187                     == caps.getDiscriminator()) {
1188                 jcaps = getIsdbtFrontendCaps(env, caps);
1189             }
1190             break;
1191         default:
1192             break;
1193     }
1194 
1195     return env->NewObject(
1196             clazz, infoInit, (jint) id, type, minFrequency, maxFrequency, minSymbolRate,
1197             maxSymbolRate, acquireRange, exclusiveGroupId, statusCaps, jcaps);
1198 }
1199 
getLnbIds()1200 jintArray JTuner::getLnbIds() {
1201     ALOGD("JTuner::getLnbIds()");
1202     Result res;
1203     hidl_vec<LnbId> lnbIds;
1204     mTuner->getLnbIds([&](Result r, const hidl_vec<LnbId>& ids) {
1205         lnbIds = ids;
1206         res = r;
1207     });
1208     if (res != Result::SUCCESS || lnbIds.size() == 0) {
1209         ALOGW("Lnb isn't available");
1210         return NULL;
1211     }
1212 
1213     mLnbIds = lnbIds;
1214     JNIEnv *env = AndroidRuntime::getJNIEnv();
1215 
1216     jintArray ids = env->NewIntArray(mLnbIds.size());
1217     env->SetIntArrayRegion(ids, 0, mLnbIds.size(), reinterpret_cast<jint*>(&mLnbIds[0]));
1218 
1219     return ids;
1220 }
1221 
openLnbById(int id)1222 jobject JTuner::openLnbById(int id) {
1223     sp<ILnb> iLnbSp;
1224     Result r;
1225     mTuner->openLnbById(id, [&](Result res, const sp<ILnb>& lnb) {
1226         r = res;
1227         iLnbSp = lnb;
1228     });
1229     if (r != Result::SUCCESS || iLnbSp == nullptr) {
1230         ALOGE("Failed to open lnb");
1231         return NULL;
1232     }
1233     mLnb = iLnbSp;
1234 
1235     JNIEnv *env = AndroidRuntime::getJNIEnv();
1236     jobject lnbObj = env->NewObject(
1237             env->FindClass("android/media/tv/tuner/Lnb"),
1238             gFields.lnbInitID,
1239             (jint) id);
1240 
1241     sp<LnbCallback> lnbCb = new LnbCallback(lnbObj, id);
1242     mLnb->setCallback(lnbCb);
1243 
1244     sp<Lnb> lnbSp = new Lnb(iLnbSp, lnbObj);
1245     lnbSp->incStrong(lnbObj);
1246     env->SetLongField(lnbObj, gFields.lnbContext, (jlong) lnbSp.get());
1247 
1248     return lnbObj;
1249 }
1250 
openLnbByName(jstring name)1251 jobject JTuner::openLnbByName(jstring name) {
1252     JNIEnv *env = AndroidRuntime::getJNIEnv();
1253     std::string lnbName(env->GetStringUTFChars(name, nullptr));
1254     sp<ILnb> iLnbSp;
1255     Result res;
1256     LnbId id;
1257     mTuner->openLnbByName(lnbName, [&](Result r, LnbId lnbId, const sp<ILnb>& lnb) {
1258         res = r;
1259         iLnbSp = lnb;
1260         id = lnbId;
1261     });
1262     if (res != Result::SUCCESS || iLnbSp == nullptr) {
1263         ALOGE("Failed to open lnb");
1264         return NULL;
1265     }
1266     mLnb = iLnbSp;
1267 
1268     jobject lnbObj = env->NewObject(
1269             env->FindClass("android/media/tv/tuner/Lnb"),
1270             gFields.lnbInitID,
1271             id);
1272 
1273     sp<LnbCallback> lnbCb = new LnbCallback(lnbObj, id);
1274     mLnb->setCallback(lnbCb);
1275 
1276     sp<Lnb> lnbSp = new Lnb(iLnbSp, lnbObj);
1277     lnbSp->incStrong(lnbObj);
1278     env->SetLongField(lnbObj, gFields.lnbContext, (jlong) lnbSp.get());
1279 
1280     return lnbObj;
1281 }
1282 
tune(const FrontendSettings & settings)1283 int JTuner::tune(const FrontendSettings& settings) {
1284     if (mFe == NULL) {
1285         ALOGE("frontend is not initialized");
1286         return (int)Result::INVALID_STATE;
1287     }
1288     Result result = mFe->tune(settings);
1289     return (int)result;
1290 }
1291 
stopTune()1292 int JTuner::stopTune() {
1293     if (mFe == NULL) {
1294         ALOGE("frontend is not initialized");
1295         return (int)Result::INVALID_STATE;
1296     }
1297     Result result = mFe->stopTune();
1298     return (int)result;
1299 }
1300 
scan(const FrontendSettings & settings,FrontendScanType scanType)1301 int JTuner::scan(const FrontendSettings& settings, FrontendScanType scanType) {
1302     if (mFe == NULL) {
1303         ALOGE("frontend is not initialized");
1304         return (int)Result::INVALID_STATE;
1305     }
1306     Result result = mFe->scan(settings, scanType);
1307     return (int)result;
1308 }
1309 
stopScan()1310 int JTuner::stopScan() {
1311     if (mFe == NULL) {
1312         ALOGE("frontend is not initialized");
1313         return (int)Result::INVALID_STATE;
1314     }
1315     Result result = mFe->stopScan();
1316     return (int)result;
1317 }
1318 
setLnb(int id)1319 int JTuner::setLnb(int id) {
1320     if (mFe == NULL) {
1321         ALOGE("frontend is not initialized");
1322         return (int)Result::INVALID_STATE;
1323     }
1324     Result result = mFe->setLnb(id);
1325     return (int)result;
1326 }
1327 
setLna(bool enable)1328 int JTuner::setLna(bool enable) {
1329     if (mFe == NULL) {
1330         ALOGE("frontend is not initialized");
1331         return (int)Result::INVALID_STATE;
1332     }
1333     Result result = mFe->setLna(enable);
1334     return (int)result;
1335 }
1336 
openDemux()1337 Result JTuner::openDemux() {
1338     if (mTuner == nullptr) {
1339         return Result::NOT_INITIALIZED;
1340     }
1341     if (mDemux != nullptr) {
1342         return Result::SUCCESS;
1343     }
1344     Result res;
1345     uint32_t id;
1346     sp<IDemux> demuxSp;
1347     mTuner->openDemux([&](Result r, uint32_t demuxId, const sp<IDemux>& demux) {
1348         demuxSp = demux;
1349         id = demuxId;
1350         res = r;
1351         ALOGD("open demux, id = %d", demuxId);
1352     });
1353     if (res == Result::SUCCESS) {
1354         mDemux = demuxSp;
1355         mDemuxId = id;
1356         if (mFe != NULL) {
1357             mDemux->setFrontendDataSource(mFeId);
1358         }
1359     }
1360     return res;
1361 }
1362 
close()1363 jint JTuner::close() {
1364     Result res = Result::SUCCESS;
1365     if (mFe != NULL) {
1366         res = mFe->close();
1367         if (res != Result::SUCCESS) {
1368             return (jint) res;
1369         }
1370     }
1371     if (mDemux != NULL) {
1372         res = mDemux->close();
1373         if (res != Result::SUCCESS) {
1374             return (jint) res;
1375         }
1376     }
1377     return (jint) res;
1378 }
1379 
getAvSyncHwId(sp<Filter> filter)1380 jobject JTuner::getAvSyncHwId(sp<Filter> filter) {
1381     if (mDemux == NULL) {
1382         return NULL;
1383     }
1384 
1385     uint32_t avSyncHwId;
1386     Result res;
1387     sp<IFilter> iFilterSp = filter->getIFilter();
1388     mDemux->getAvSyncHwId(iFilterSp,
1389             [&](Result r, uint32_t id) {
1390                 res = r;
1391                 avSyncHwId = id;
1392             });
1393     if (res == Result::SUCCESS) {
1394         JNIEnv *env = AndroidRuntime::getJNIEnv();
1395         jclass integerClazz = env->FindClass("java/lang/Integer");
1396         jmethodID intInit = env->GetMethodID(integerClazz, "<init>", "(I)V");
1397         return env->NewObject(integerClazz, intInit, avSyncHwId);
1398     }
1399     return NULL;
1400 }
1401 
getAvSyncTime(jint id)1402 jobject JTuner::getAvSyncTime(jint id) {
1403     if (mDemux == NULL) {
1404         return NULL;
1405     }
1406     uint64_t time;
1407     Result res;
1408     mDemux->getAvSyncTime(static_cast<uint32_t>(id),
1409             [&](Result r, uint64_t ts) {
1410                 res = r;
1411                 time = ts;
1412             });
1413     if (res == Result::SUCCESS) {
1414         JNIEnv *env = AndroidRuntime::getJNIEnv();
1415         jclass longClazz = env->FindClass("java/lang/Long");
1416         jmethodID longInit = env->GetMethodID(longClazz, "<init>", "(J)V");
1417         return env->NewObject(longClazz, longInit, static_cast<jlong>(time));
1418     }
1419     return NULL;
1420 }
1421 
connectCiCam(jint id)1422 int JTuner::connectCiCam(jint id) {
1423     if (mDemux == NULL) {
1424         Result r = openDemux();
1425         if (r != Result::SUCCESS) {
1426             return (int) r;
1427         }
1428     }
1429     Result r = mDemux->connectCiCam(static_cast<uint32_t>(id));
1430     return (int) r;
1431 }
1432 
disconnectCiCam()1433 int JTuner::disconnectCiCam() {
1434     if (mDemux == NULL) {
1435         Result r = openDemux();
1436         if (r != Result::SUCCESS) {
1437             return (int) r;
1438         }
1439     }
1440     Result r = mDemux->disconnectCiCam();
1441     return (int) r;
1442 }
1443 
openDescrambler()1444 jobject JTuner::openDescrambler() {
1445     ALOGD("JTuner::openDescrambler");
1446     if (mTuner == nullptr || mDemux == nullptr) {
1447         return NULL;
1448     }
1449     sp<IDescrambler> descramblerSp;
1450     Result res;
1451     mTuner->openDescrambler([&](Result r, const sp<IDescrambler>& descrambler) {
1452         res = r;
1453         descramblerSp = descrambler;
1454     });
1455 
1456     if (res != Result::SUCCESS || descramblerSp == NULL) {
1457         return NULL;
1458     }
1459 
1460     descramblerSp->setDemuxSource(mDemuxId);
1461 
1462     JNIEnv *env = AndroidRuntime::getJNIEnv();
1463     jobject descramblerObj =
1464             env->NewObject(
1465                     env->FindClass("android/media/tv/tuner/Descrambler"),
1466                     gFields.descramblerInitID);
1467 
1468     descramblerSp->incStrong(descramblerObj);
1469     env->SetLongField(descramblerObj, gFields.descramblerContext, (jlong)descramblerSp.get());
1470 
1471     return descramblerObj;
1472 }
1473 
openFilter(DemuxFilterType type,int bufferSize)1474 jobject JTuner::openFilter(DemuxFilterType type, int bufferSize) {
1475     if (mDemux == NULL) {
1476         if (openDemux() != Result::SUCCESS) {
1477             return NULL;
1478         }
1479     }
1480 
1481     sp<IFilter> iFilterSp;
1482     sp<FilterCallback> callback = new FilterCallback();
1483     Result res;
1484     mDemux->openFilter(type, bufferSize, callback,
1485             [&](Result r, const sp<IFilter>& filter) {
1486                 iFilterSp = filter;
1487                 res = r;
1488             });
1489     if (res != Result::SUCCESS || iFilterSp == NULL) {
1490         ALOGD("Failed to open filter, type = %d", type.mainType);
1491         return NULL;
1492     }
1493     int fId;
1494     iFilterSp->getId([&](Result, uint32_t filterId) {
1495         fId = filterId;
1496     });
1497 
1498     JNIEnv *env = AndroidRuntime::getJNIEnv();
1499     jobject filterObj =
1500             env->NewObject(
1501                     env->FindClass("android/media/tv/tuner/filter/Filter"),
1502                     gFields.filterInitID,
1503                     (jint) fId);
1504 
1505     sp<Filter> filterSp = new Filter(iFilterSp, filterObj);
1506     filterSp->incStrong(filterObj);
1507     env->SetLongField(filterObj, gFields.filterContext, (jlong)filterSp.get());
1508 
1509     callback->setFilter(filterSp);
1510 
1511     return filterObj;
1512 }
1513 
openTimeFilter()1514 jobject JTuner::openTimeFilter() {
1515     if (mDemux == NULL) {
1516         if (openDemux() != Result::SUCCESS) {
1517             return NULL;
1518         }
1519     }
1520     sp<ITimeFilter> iTimeFilterSp;
1521     Result res;
1522     mDemux->openTimeFilter(
1523             [&](Result r, const sp<ITimeFilter>& filter) {
1524                 iTimeFilterSp = filter;
1525                 res = r;
1526             });
1527 
1528     if (res != Result::SUCCESS || iTimeFilterSp == NULL) {
1529         return NULL;
1530     }
1531 
1532     JNIEnv *env = AndroidRuntime::getJNIEnv();
1533     jobject timeFilterObj =
1534             env->NewObject(
1535                     env->FindClass("android/media/tv/tuner/filter/TimeFilter"),
1536                     gFields.timeFilterInitID);
1537     sp<TimeFilter> timeFilterSp = new TimeFilter(iTimeFilterSp, timeFilterObj);
1538     timeFilterSp->incStrong(timeFilterObj);
1539     env->SetLongField(timeFilterObj, gFields.timeFilterContext, (jlong)timeFilterSp.get());
1540 
1541     return timeFilterObj;
1542 }
1543 
openDvr(DvrType type,jlong bufferSize)1544 jobject JTuner::openDvr(DvrType type, jlong bufferSize) {
1545     ALOGD("JTuner::openDvr");
1546     if (mDemux == NULL) {
1547         if (openDemux() != Result::SUCCESS) {
1548             return NULL;
1549         }
1550     }
1551     sp<IDvr> iDvrSp;
1552     sp<DvrCallback> callback = new DvrCallback();
1553     Result res;
1554     mDemux->openDvr(type, (uint32_t) bufferSize, callback,
1555             [&](Result r, const sp<IDvr>& dvr) {
1556                 res = r;
1557                 iDvrSp = dvr;
1558             });
1559 
1560     if (res != Result::SUCCESS || iDvrSp == NULL) {
1561         return NULL;
1562     }
1563 
1564     JNIEnv *env = AndroidRuntime::getJNIEnv();
1565     jobject dvrObj;
1566     if (type == DvrType::RECORD) {
1567         dvrObj =
1568                 env->NewObject(
1569                         env->FindClass("android/media/tv/tuner/dvr/DvrRecorder"),
1570                         gFields.dvrRecorderInitID,
1571                         mObject);
1572         sp<Dvr> dvrSp = new Dvr(iDvrSp, dvrObj);
1573         dvrSp->incStrong(dvrObj);
1574         env->SetLongField(dvrObj, gFields.dvrRecorderContext, (jlong)dvrSp.get());
1575     } else {
1576         dvrObj =
1577                 env->NewObject(
1578                         env->FindClass("android/media/tv/tuner/dvr/DvrPlayback"),
1579                         gFields.dvrPlaybackInitID,
1580                         mObject);
1581         sp<Dvr> dvrSp = new Dvr(iDvrSp, dvrObj);
1582         dvrSp->incStrong(dvrObj);
1583         env->SetLongField(dvrObj, gFields.dvrPlaybackContext, (jlong)dvrSp.get());
1584     }
1585 
1586     callback->setDvr(dvrObj);
1587 
1588     return dvrObj;
1589 }
1590 
getDemuxCaps()1591 jobject JTuner::getDemuxCaps() {
1592     DemuxCapabilities caps;
1593     Result res;
1594     mTuner->getDemuxCaps([&](Result r, const DemuxCapabilities& demuxCaps) {
1595         caps = demuxCaps;
1596         res = r;
1597     });
1598     if (res != Result::SUCCESS) {
1599         return NULL;
1600     }
1601     JNIEnv *env = AndroidRuntime::getJNIEnv();
1602     jclass clazz = env->FindClass("android/media/tv/tuner/DemuxCapabilities");
1603     jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(IIIIIIIIIJI[IZ)V");
1604 
1605     jint numDemux = caps.numDemux;
1606     jint numRecord = caps.numRecord;
1607     jint numPlayback = caps.numPlayback;
1608     jint numTsFilter = caps.numTsFilter;
1609     jint numSectionFilter = caps.numSectionFilter;
1610     jint numAudioFilter = caps.numAudioFilter;
1611     jint numVideoFilter = caps.numVideoFilter;
1612     jint numPesFilter = caps.numPesFilter;
1613     jint numPcrFilter = caps.numPcrFilter;
1614     jlong numBytesInSectionFilter = caps.numBytesInSectionFilter;
1615     jint filterCaps = static_cast<jint>(caps.filterCaps);
1616     jboolean bTimeFilter = caps.bTimeFilter;
1617 
1618     jintArray linkCaps = env->NewIntArray(caps.linkCaps.size());
1619     env->SetIntArrayRegion(
1620             linkCaps, 0, caps.linkCaps.size(), reinterpret_cast<jint*>(&caps.linkCaps[0]));
1621 
1622     return env->NewObject(clazz, capsInit, numDemux, numRecord, numPlayback, numTsFilter,
1623             numSectionFilter, numAudioFilter, numVideoFilter, numPesFilter, numPcrFilter,
1624             numBytesInSectionFilter, filterCaps, linkCaps, bTimeFilter);
1625 }
1626 
getFrontendStatus(jintArray types)1627 jobject JTuner::getFrontendStatus(jintArray types) {
1628     if (mFe == NULL) {
1629         return NULL;
1630     }
1631     JNIEnv *env = AndroidRuntime::getJNIEnv();
1632     jsize size = env->GetArrayLength(types);
1633     std::vector<FrontendStatusType> v(size);
1634     env->GetIntArrayRegion(types, 0, size, reinterpret_cast<jint*>(&v[0]));
1635 
1636     Result res;
1637     hidl_vec<FrontendStatus> status;
1638     mFe->getStatus(v,
1639             [&](Result r, const hidl_vec<FrontendStatus>& s) {
1640                 res = r;
1641                 status = s;
1642             });
1643     if (res != Result::SUCCESS) {
1644         return NULL;
1645     }
1646 
1647     jclass clazz = env->FindClass("android/media/tv/tuner/frontend/FrontendStatus");
1648     jmethodID init = env->GetMethodID(clazz, "<init>", "()V");
1649     jobject statusObj = env->NewObject(clazz, init);
1650 
1651     jclass intClazz = env->FindClass("java/lang/Integer");
1652     jmethodID initInt = env->GetMethodID(intClazz, "<init>", "(I)V");
1653     jclass booleanClazz = env->FindClass("java/lang/Boolean");
1654     jmethodID initBoolean = env->GetMethodID(booleanClazz, "<init>", "(Z)V");
1655 
1656     for (auto s : status) {
1657         switch(s.getDiscriminator()) {
1658             case FrontendStatus::hidl_discriminator::isDemodLocked: {
1659                 jfieldID field = env->GetFieldID(clazz, "mIsDemodLocked", "Ljava/lang/Boolean;");
1660                 jobject newBooleanObj = env->NewObject(
1661                         booleanClazz, initBoolean, static_cast<jboolean>(s.isDemodLocked()));
1662                 env->SetObjectField(statusObj, field, newBooleanObj);
1663                 break;
1664             }
1665             case FrontendStatus::hidl_discriminator::snr: {
1666                 jfieldID field = env->GetFieldID(clazz, "mSnr", "Ljava/lang/Integer;");
1667                 jobject newIntegerObj = env->NewObject(
1668                         intClazz, initInt, static_cast<jint>(s.snr()));
1669                 env->SetObjectField(statusObj, field, newIntegerObj);
1670                 break;
1671             }
1672             case FrontendStatus::hidl_discriminator::ber: {
1673                 jfieldID field = env->GetFieldID(clazz, "mBer", "Ljava/lang/Integer;");
1674                 jobject newIntegerObj = env->NewObject(
1675                         intClazz, initInt, static_cast<jint>(s.ber()));
1676                 env->SetObjectField(statusObj, field, newIntegerObj);
1677                 break;
1678             }
1679             case FrontendStatus::hidl_discriminator::per: {
1680                 jfieldID field = env->GetFieldID(clazz, "mPer", "Ljava/lang/Integer;");
1681                 jobject newIntegerObj = env->NewObject(
1682                         intClazz, initInt, static_cast<jint>(s.per()));
1683                 env->SetObjectField(statusObj, field, newIntegerObj);
1684                 break;
1685             }
1686             case FrontendStatus::hidl_discriminator::preBer: {
1687                 jfieldID field = env->GetFieldID(clazz, "mPerBer", "Ljava/lang/Integer;");
1688                 jobject newIntegerObj = env->NewObject(
1689                         intClazz, initInt, static_cast<jint>(s.preBer()));
1690                 env->SetObjectField(statusObj, field, newIntegerObj);
1691                 break;
1692             }
1693             case FrontendStatus::hidl_discriminator::signalQuality: {
1694                 jfieldID field = env->GetFieldID(clazz, "mSignalQuality", "Ljava/lang/Integer;");
1695                 jobject newIntegerObj = env->NewObject(
1696                         intClazz, initInt, static_cast<jint>(s.signalQuality()));
1697                 env->SetObjectField(statusObj, field, newIntegerObj);
1698                 break;
1699             }
1700             case FrontendStatus::hidl_discriminator::signalStrength: {
1701                 jfieldID field = env->GetFieldID(clazz, "mSignalStrength", "Ljava/lang/Integer;");
1702                 jobject newIntegerObj = env->NewObject(
1703                         intClazz, initInt, static_cast<jint>(s.signalStrength()));
1704                 env->SetObjectField(statusObj, field, newIntegerObj);
1705                 break;
1706             }
1707             case FrontendStatus::hidl_discriminator::symbolRate: {
1708                 jfieldID field = env->GetFieldID(clazz, "mSymbolRate", "Ljava/lang/Integer;");
1709                 jobject newIntegerObj = env->NewObject(
1710                         intClazz, initInt, static_cast<jint>(s.symbolRate()));
1711                 env->SetObjectField(statusObj, field, newIntegerObj);
1712                 break;
1713             }
1714             case FrontendStatus::hidl_discriminator::innerFec: {
1715                 jfieldID field = env->GetFieldID(clazz, "mInnerFec", "Ljava/lang/Long;");
1716                 jclass longClazz = env->FindClass("java/lang/Long");
1717                 jmethodID initLong = env->GetMethodID(longClazz, "<init>", "(J)V");
1718                 jobject newLongObj = env->NewObject(
1719                         longClazz, initLong, static_cast<jlong>(s.innerFec()));
1720                 env->SetObjectField(statusObj, field, newLongObj);
1721                 break;
1722             }
1723             case FrontendStatus::hidl_discriminator::modulation: {
1724                 jfieldID field = env->GetFieldID(clazz, "mModulation", "Ljava/lang/Integer;");
1725                 FrontendModulationStatus modulation = s.modulation();
1726                 jint intModulation;
1727                 bool valid = true;
1728                 switch(modulation.getDiscriminator()) {
1729                     case FrontendModulationStatus::hidl_discriminator::dvbc: {
1730                         intModulation = static_cast<jint>(modulation.dvbc());
1731                         break;
1732                     }
1733                     case FrontendModulationStatus::hidl_discriminator::dvbs: {
1734                         intModulation = static_cast<jint>(modulation.dvbs());
1735                         break;
1736                     }
1737                     case FrontendModulationStatus::hidl_discriminator::isdbs: {
1738                         intModulation = static_cast<jint>(modulation.isdbs());
1739                         break;
1740                     }
1741                     case FrontendModulationStatus::hidl_discriminator::isdbs3: {
1742                         intModulation = static_cast<jint>(modulation.isdbs3());
1743                         break;
1744                     }
1745                     case FrontendModulationStatus::hidl_discriminator::isdbt: {
1746                         intModulation = static_cast<jint>(modulation.isdbt());
1747                         break;
1748                     }
1749                     default: {
1750                         valid = false;
1751                         break;
1752                     }
1753                 }
1754                 if (valid) {
1755                     jobject newIntegerObj = env->NewObject(intClazz, initInt, intModulation);
1756                     env->SetObjectField(statusObj, field, newIntegerObj);
1757                 }
1758                 break;
1759             }
1760             case FrontendStatus::hidl_discriminator::inversion: {
1761                 jfieldID field = env->GetFieldID(clazz, "mInversion", "Ljava/lang/Integer;");
1762                 jobject newIntegerObj = env->NewObject(
1763                         intClazz, initInt, static_cast<jint>(s.inversion()));
1764                 env->SetObjectField(statusObj, field, newIntegerObj);
1765                 break;
1766             }
1767             case FrontendStatus::hidl_discriminator::lnbVoltage: {
1768                 jfieldID field = env->GetFieldID(clazz, "mLnbVoltage", "Ljava/lang/Integer;");
1769                 jobject newIntegerObj = env->NewObject(
1770                         intClazz, initInt, static_cast<jint>(s.lnbVoltage()));
1771                 env->SetObjectField(statusObj, field, newIntegerObj);
1772                 break;
1773             }
1774             case FrontendStatus::hidl_discriminator::plpId: {
1775                 jfieldID field = env->GetFieldID(clazz, "mPlpId", "Ljava/lang/Integer;");
1776                 jobject newIntegerObj = env->NewObject(
1777                         intClazz, initInt, static_cast<jint>(s.plpId()));
1778                 env->SetObjectField(statusObj, field, newIntegerObj);
1779                 break;
1780             }
1781             case FrontendStatus::hidl_discriminator::isEWBS: {
1782                 jfieldID field = env->GetFieldID(clazz, "mIsEwbs", "Ljava/lang/Boolean;");
1783                 jobject newBooleanObj = env->NewObject(
1784                         booleanClazz, initBoolean, static_cast<jboolean>(s.isEWBS()));
1785                 env->SetObjectField(statusObj, field, newBooleanObj);
1786                 break;
1787             }
1788             case FrontendStatus::hidl_discriminator::agc: {
1789                 jfieldID field = env->GetFieldID(clazz, "mAgc", "Ljava/lang/Integer;");
1790                 jobject newIntegerObj = env->NewObject(
1791                         intClazz, initInt, static_cast<jint>(s.agc()));
1792                 env->SetObjectField(statusObj, field, newIntegerObj);
1793                 break;
1794             }
1795             case FrontendStatus::hidl_discriminator::isLnaOn: {
1796                 jfieldID field = env->GetFieldID(clazz, "mIsLnaOn", "Ljava/lang/Boolean;");
1797                 jobject newBooleanObj = env->NewObject(
1798                         booleanClazz, initBoolean, static_cast<jboolean>(s.isLnaOn()));
1799                 env->SetObjectField(statusObj, field, newBooleanObj);
1800                 break;
1801             }
1802             case FrontendStatus::hidl_discriminator::isLayerError: {
1803                 jfieldID field = env->GetFieldID(clazz, "mIsLayerErrors", "[Z");
1804                 hidl_vec<bool> layerErr = s.isLayerError();
1805 
1806                 jbooleanArray valObj = env->NewBooleanArray(layerErr.size());
1807 
1808                 for (size_t i = 0; i < layerErr.size(); i++) {
1809                     jboolean x = layerErr[i];
1810                     env->SetBooleanArrayRegion(valObj, i, 1, &x);
1811                 }
1812                 env->SetObjectField(statusObj, field, valObj);
1813                 break;
1814             }
1815             case FrontendStatus::hidl_discriminator::mer: {
1816                 jfieldID field = env->GetFieldID(clazz, "mMer", "Ljava/lang/Integer;");
1817                 jobject newIntegerObj = env->NewObject(
1818                         intClazz, initInt, static_cast<jint>(s.mer()));
1819                 env->SetObjectField(statusObj, field, newIntegerObj);
1820                 break;
1821             }
1822             case FrontendStatus::hidl_discriminator::freqOffset: {
1823                 jfieldID field = env->GetFieldID(clazz, "mFreqOffset", "Ljava/lang/Integer;");
1824                 jobject newIntegerObj = env->NewObject(
1825                         intClazz, initInt, static_cast<jint>(s.freqOffset()));
1826                 env->SetObjectField(statusObj, field, newIntegerObj);
1827                 break;
1828             }
1829             case FrontendStatus::hidl_discriminator::hierarchy: {
1830                 jfieldID field = env->GetFieldID(clazz, "mHierarchy", "Ljava/lang/Integer;");
1831                 jobject newIntegerObj = env->NewObject(
1832                         intClazz, initInt, static_cast<jint>(s.hierarchy()));
1833                 env->SetObjectField(statusObj, field, newIntegerObj);
1834                 break;
1835             }
1836             case FrontendStatus::hidl_discriminator::isRfLocked: {
1837                 jfieldID field = env->GetFieldID(clazz, "mIsRfLocked", "Ljava/lang/Boolean;");
1838                 jobject newBooleanObj = env->NewObject(
1839                         booleanClazz, initBoolean, static_cast<jboolean>(s.isRfLocked()));
1840                 env->SetObjectField(statusObj, field, newBooleanObj);
1841                 break;
1842             }
1843             case FrontendStatus::hidl_discriminator::plpInfo: {
1844                 jfieldID field = env->GetFieldID(clazz, "mPlpInfo",
1845                         "[Landroid/media/tv/tuner/frontend/FrontendStatus$Atsc3PlpTuningInfo;");
1846                 jclass plpClazz = env->FindClass(
1847                         "android/media/tv/tuner/frontend/FrontendStatus$Atsc3PlpTuningInfo");
1848                 jmethodID initPlp = env->GetMethodID(plpClazz, "<init>", "(IZI)V");
1849 
1850                 hidl_vec<FrontendStatusAtsc3PlpInfo> plpInfos = s.plpInfo();
1851 
1852                 jobjectArray valObj = env->NewObjectArray(plpInfos.size(), plpClazz, NULL);
1853                 for (int i = 0; i < plpInfos.size(); i++) {
1854                     auto info = plpInfos[i];
1855                     jint plpId = (jint) info.plpId;
1856                     jboolean isLocked = (jboolean) info.isLocked;
1857                     jint uec = (jint) info.uec;
1858 
1859                     jobject plpObj = env->NewObject(plpClazz, initPlp, plpId, isLocked, uec);
1860                     env->SetObjectArrayElement(valObj, i, plpObj);
1861                 }
1862 
1863                 env->SetObjectField(statusObj, field, valObj);
1864                 break;
1865             }
1866             default: {
1867                 break;
1868             }
1869         }
1870     }
1871 
1872     return statusObj;
1873 }
1874 
closeFrontend()1875 jint JTuner::closeFrontend() {
1876     Result r = Result::SUCCESS;
1877     if (mFe != NULL) {
1878         r = mFe->close();
1879     }
1880     return (jint) r;
1881 }
1882 
closeDemux()1883 jint JTuner::closeDemux() {
1884     Result r = Result::SUCCESS;
1885     if (mDemux != NULL) {
1886         r = mDemux->close();
1887     }
1888     return (jint) r;
1889 }
1890 
1891 }  // namespace android
1892 
1893 ////////////////////////////////////////////////////////////////////////////////
1894 
1895 using namespace android;
1896 
setTuner(JNIEnv * env,jobject thiz,const sp<JTuner> & tuner)1897 static sp<JTuner> setTuner(JNIEnv *env, jobject thiz, const sp<JTuner> &tuner) {
1898     sp<JTuner> old = (JTuner *)env->GetLongField(thiz, gFields.tunerContext);
1899 
1900     if (tuner != NULL) {
1901         tuner->incStrong(thiz);
1902     }
1903     if (old != NULL) {
1904         old->decStrong(thiz);
1905     }
1906     env->SetLongField(thiz, gFields.tunerContext, (jlong)tuner.get());
1907 
1908     return old;
1909 }
1910 
getTuner(JNIEnv * env,jobject thiz)1911 static sp<JTuner> getTuner(JNIEnv *env, jobject thiz) {
1912     return (JTuner *)env->GetLongField(thiz, gFields.tunerContext);
1913 }
1914 
getDescrambler(JNIEnv * env,jobject descrambler)1915 static sp<IDescrambler> getDescrambler(JNIEnv *env, jobject descrambler) {
1916     return (IDescrambler *)env->GetLongField(descrambler, gFields.descramblerContext);
1917 }
1918 
getResourceIdFromHandle(jint handle)1919 static uint32_t getResourceIdFromHandle(jint handle) {
1920     return (handle & 0x00ff0000) >> 16;
1921 }
1922 
getDemuxPid(int pidType,int pid)1923 static DemuxPid getDemuxPid(int pidType, int pid) {
1924     DemuxPid demuxPid;
1925     if ((int)pidType == 1) {
1926         demuxPid.tPid(static_cast<DemuxTpid>(pid));
1927     } else if ((int)pidType == 2) {
1928         demuxPid.mmtpPid(static_cast<DemuxMmtpPid>(pid));
1929     }
1930     return demuxPid;
1931 }
1932 
getFrontendSettingsFreq(JNIEnv * env,const jobject & settings)1933 static uint32_t getFrontendSettingsFreq(JNIEnv *env, const jobject& settings) {
1934     jclass clazz = env->FindClass("android/media/tv/tuner/frontend/FrontendSettings");
1935     jfieldID freqField = env->GetFieldID(clazz, "mFrequency", "I");
1936     uint32_t freq = static_cast<uint32_t>(env->GetIntField(settings, freqField));
1937     return freq;
1938 }
1939 
getAnalogFrontendSettings(JNIEnv * env,const jobject & settings)1940 static FrontendSettings getAnalogFrontendSettings(JNIEnv *env, const jobject& settings) {
1941     FrontendSettings frontendSettings;
1942     uint32_t freq = getFrontendSettingsFreq(env, settings);
1943     jclass clazz = env->FindClass("android/media/tv/tuner/frontend/AnalogFrontendSettings");
1944     FrontendAnalogType analogType =
1945             static_cast<FrontendAnalogType>(
1946                     env->GetIntField(settings, env->GetFieldID(clazz, "mSignalType", "I")));
1947     FrontendAnalogSifStandard sifStandard =
1948             static_cast<FrontendAnalogSifStandard>(
1949                     env->GetIntField(settings, env->GetFieldID(clazz, "mSifStandard", "I")));
1950     FrontendAnalogSettings frontendAnalogSettings {
1951             .frequency = freq,
1952             .type = analogType,
1953             .sifStandard = sifStandard,
1954     };
1955     frontendSettings.analog(frontendAnalogSettings);
1956     return frontendSettings;
1957 }
1958 
getAtsc3PlpSettings(JNIEnv * env,const jobject & settings)1959 static hidl_vec<FrontendAtsc3PlpSettings> getAtsc3PlpSettings(
1960         JNIEnv *env, const jobject& settings) {
1961     jclass clazz = env->FindClass("android/media/tv/tuner/frontend/Atsc3FrontendSettings");
1962     jobjectArray plpSettings =
1963             reinterpret_cast<jobjectArray>(
1964                     env->GetObjectField(settings,
1965                             env->GetFieldID(
1966                                     clazz,
1967                                     "mPlpSettings",
1968                                     "[Landroid/media/tv/tuner/frontend/Atsc3PlpSettings;")));
1969     int len = env->GetArrayLength(plpSettings);
1970 
1971     jclass plpClazz = env->FindClass("android/media/tv/tuner/frontend/Atsc3PlpSettings");
1972     hidl_vec<FrontendAtsc3PlpSettings> plps = hidl_vec<FrontendAtsc3PlpSettings>(len);
1973     // parse PLP settings
1974     for (int i = 0; i < len; i++) {
1975         jobject plp = env->GetObjectArrayElement(plpSettings, i);
1976         uint8_t plpId =
1977                 static_cast<uint8_t>(
1978                         env->GetIntField(plp, env->GetFieldID(plpClazz, "mPlpId", "I")));
1979         FrontendAtsc3Modulation modulation =
1980                 static_cast<FrontendAtsc3Modulation>(
1981                         env->GetIntField(plp, env->GetFieldID(plpClazz, "mModulation", "I")));
1982         FrontendAtsc3TimeInterleaveMode interleaveMode =
1983                 static_cast<FrontendAtsc3TimeInterleaveMode>(
1984                         env->GetIntField(
1985                                 plp, env->GetFieldID(plpClazz, "mInterleaveMode", "I")));
1986         FrontendAtsc3CodeRate codeRate =
1987                 static_cast<FrontendAtsc3CodeRate>(
1988                         env->GetIntField(plp, env->GetFieldID(plpClazz, "mCodeRate", "I")));
1989         FrontendAtsc3Fec fec =
1990                 static_cast<FrontendAtsc3Fec>(
1991                         env->GetIntField(plp, env->GetFieldID(plpClazz, "mFec", "I")));
1992         FrontendAtsc3PlpSettings frontendAtsc3PlpSettings {
1993                 .plpId = plpId,
1994                 .modulation = modulation,
1995                 .interleaveMode = interleaveMode,
1996                 .codeRate = codeRate,
1997                 .fec = fec,
1998         };
1999         plps[i] = frontendAtsc3PlpSettings;
2000     }
2001     return plps;
2002 }
2003 
getAtsc3FrontendSettings(JNIEnv * env,const jobject & settings)2004 static FrontendSettings getAtsc3FrontendSettings(JNIEnv *env, const jobject& settings) {
2005     FrontendSettings frontendSettings;
2006     uint32_t freq = getFrontendSettingsFreq(env, settings);
2007     jclass clazz = env->FindClass("android/media/tv/tuner/frontend/Atsc3FrontendSettings");
2008 
2009     FrontendAtsc3Bandwidth bandwidth =
2010             static_cast<FrontendAtsc3Bandwidth>(
2011                     env->GetIntField(settings, env->GetFieldID(clazz, "mBandwidth", "I")));
2012     FrontendAtsc3DemodOutputFormat demod =
2013             static_cast<FrontendAtsc3DemodOutputFormat>(
2014                     env->GetIntField(
2015                             settings, env->GetFieldID(clazz, "mDemodOutputFormat", "I")));
2016     hidl_vec<FrontendAtsc3PlpSettings> plps = getAtsc3PlpSettings(env, settings);
2017     FrontendAtsc3Settings frontendAtsc3Settings {
2018             .frequency = freq,
2019             .bandwidth = bandwidth,
2020             .demodOutputFormat = demod,
2021             .plpSettings = plps,
2022     };
2023     frontendSettings.atsc3(frontendAtsc3Settings);
2024     return frontendSettings;
2025 }
2026 
getAtscFrontendSettings(JNIEnv * env,const jobject & settings)2027 static FrontendSettings getAtscFrontendSettings(JNIEnv *env, const jobject& settings) {
2028     FrontendSettings frontendSettings;
2029     uint32_t freq = getFrontendSettingsFreq(env, settings);
2030     jclass clazz = env->FindClass("android/media/tv/tuner/frontend/AtscFrontendSettings");
2031     FrontendAtscModulation modulation =
2032             static_cast<FrontendAtscModulation>(
2033                     env->GetIntField(settings, env->GetFieldID(clazz, "mModulation", "I")));
2034     FrontendAtscSettings frontendAtscSettings {
2035             .frequency = freq,
2036             .modulation = modulation,
2037     };
2038     frontendSettings.atsc(frontendAtscSettings);
2039     return frontendSettings;
2040 }
2041 
getDvbcFrontendSettings(JNIEnv * env,const jobject & settings)2042 static FrontendSettings getDvbcFrontendSettings(JNIEnv *env, const jobject& settings) {
2043     FrontendSettings frontendSettings;
2044     uint32_t freq = getFrontendSettingsFreq(env, settings);
2045     jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbcFrontendSettings");
2046     FrontendDvbcModulation modulation =
2047             static_cast<FrontendDvbcModulation>(
2048                     env->GetIntField(settings, env->GetFieldID(clazz, "mModulation", "I")));
2049     FrontendInnerFec innerFec =
2050             static_cast<FrontendInnerFec>(
2051                     env->GetLongField(settings, env->GetFieldID(clazz, "mFec", "J")));
2052     uint32_t symbolRate =
2053             static_cast<uint32_t>(
2054                     env->GetIntField(settings, env->GetFieldID(clazz, "mSymbolRate", "I")));
2055     FrontendDvbcOuterFec outerFec =
2056             static_cast<FrontendDvbcOuterFec>(
2057                     env->GetIntField(settings, env->GetFieldID(clazz, "mOuterFec", "I")));
2058     FrontendDvbcAnnex annex =
2059             static_cast<FrontendDvbcAnnex>(
2060                     env->GetByteField(settings, env->GetFieldID(clazz, "mAnnex", "B")));
2061     FrontendDvbcSpectralInversion spectralInversion =
2062             static_cast<FrontendDvbcSpectralInversion>(
2063                     env->GetIntField(
2064                             settings, env->GetFieldID(clazz, "mSpectralInversion", "I")));
2065     FrontendDvbcSettings frontendDvbcSettings {
2066             .frequency = freq,
2067             .modulation = modulation,
2068             .fec = innerFec,
2069             .symbolRate = symbolRate,
2070             .outerFec = outerFec,
2071             .annex = annex,
2072             .spectralInversion = spectralInversion,
2073     };
2074     frontendSettings.dvbc(frontendDvbcSettings);
2075     return frontendSettings;
2076 }
2077 
getDvbsCodeRate(JNIEnv * env,const jobject & settings)2078 static FrontendDvbsCodeRate getDvbsCodeRate(JNIEnv *env, const jobject& settings) {
2079     jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbsFrontendSettings");
2080     jobject jcodeRate =
2081             env->GetObjectField(settings,
2082                     env->GetFieldID(
2083                             clazz,
2084                             "mCodeRate",
2085                             "Landroid/media/tv/tuner/frontend/DvbsCodeRate;"));
2086 
2087     jclass codeRateClazz = env->FindClass("android/media/tv/tuner/frontend/DvbsCodeRate");
2088     FrontendInnerFec innerFec =
2089             static_cast<FrontendInnerFec>(
2090                     env->GetLongField(
2091                             jcodeRate, env->GetFieldID(codeRateClazz, "mInnerFec", "J")));
2092     bool isLinear =
2093             static_cast<bool>(
2094                     env->GetBooleanField(
2095                             jcodeRate, env->GetFieldID(codeRateClazz, "mIsLinear", "Z")));
2096     bool isShortFrames =
2097             static_cast<bool>(
2098                     env->GetBooleanField(
2099                             jcodeRate, env->GetFieldID(codeRateClazz, "mIsShortFrames", "Z")));
2100     uint32_t bitsPer1000Symbol =
2101             static_cast<uint32_t>(
2102                     env->GetIntField(
2103                             jcodeRate, env->GetFieldID(
2104                                     codeRateClazz, "mBitsPer1000Symbol", "I")));
2105     FrontendDvbsCodeRate coderate {
2106             .fec = innerFec,
2107             .isLinear = isLinear,
2108             .isShortFrames = isShortFrames,
2109             .bitsPer1000Symbol = bitsPer1000Symbol,
2110     };
2111     return coderate;
2112 }
2113 
getDvbsFrontendSettings(JNIEnv * env,const jobject & settings)2114 static FrontendSettings getDvbsFrontendSettings(JNIEnv *env, const jobject& settings) {
2115     FrontendSettings frontendSettings;
2116     uint32_t freq = getFrontendSettingsFreq(env, settings);
2117     jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbsFrontendSettings");
2118 
2119 
2120     FrontendDvbsModulation modulation =
2121             static_cast<FrontendDvbsModulation>(
2122                     env->GetIntField(settings, env->GetFieldID(clazz, "mModulation", "I")));
2123     uint32_t symbolRate =
2124             static_cast<uint32_t>(
2125                     env->GetIntField(settings, env->GetFieldID(clazz, "mSymbolRate", "I")));
2126     FrontendDvbsRolloff rolloff =
2127             static_cast<FrontendDvbsRolloff>(
2128                     env->GetIntField(settings, env->GetFieldID(clazz, "mRolloff", "I")));
2129     FrontendDvbsPilot pilot =
2130             static_cast<FrontendDvbsPilot>(
2131                     env->GetIntField(settings, env->GetFieldID(clazz, "mPilot", "I")));
2132     uint32_t inputStreamId =
2133             static_cast<uint32_t>(
2134                     env->GetIntField(settings, env->GetFieldID(clazz, "mInputStreamId", "I")));
2135     FrontendDvbsStandard standard =
2136             static_cast<FrontendDvbsStandard>(
2137                     env->GetIntField(settings, env->GetFieldID(clazz, "mStandard", "I")));
2138     FrontendDvbsVcmMode vcmMode =
2139             static_cast<FrontendDvbsVcmMode>(
2140                     env->GetIntField(settings, env->GetFieldID(clazz, "mVcmMode", "I")));
2141     FrontendDvbsCodeRate coderate = getDvbsCodeRate(env, settings);
2142 
2143     FrontendDvbsSettings frontendDvbsSettings {
2144             .frequency = freq,
2145             .modulation = modulation,
2146             .coderate = coderate,
2147             .symbolRate = symbolRate,
2148             .rolloff = rolloff,
2149             .pilot = pilot,
2150             .inputStreamId = inputStreamId,
2151             .standard = standard,
2152             .vcmMode = vcmMode,
2153     };
2154     frontendSettings.dvbs(frontendDvbsSettings);
2155     return frontendSettings;
2156 }
2157 
getDvbtFrontendSettings(JNIEnv * env,const jobject & settings)2158 static FrontendSettings getDvbtFrontendSettings(JNIEnv *env, const jobject& settings) {
2159     FrontendSettings frontendSettings;
2160     uint32_t freq = getFrontendSettingsFreq(env, settings);
2161     jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbtFrontendSettings");
2162     FrontendDvbtTransmissionMode transmissionMode =
2163             static_cast<FrontendDvbtTransmissionMode>(
2164                     env->GetIntField(
2165                             settings, env->GetFieldID(clazz, "mTransmissionMode", "I")));
2166     FrontendDvbtBandwidth bandwidth =
2167             static_cast<FrontendDvbtBandwidth>(
2168                     env->GetIntField(settings, env->GetFieldID(clazz, "mBandwidth", "I")));
2169     FrontendDvbtConstellation constellation =
2170             static_cast<FrontendDvbtConstellation>(
2171                     env->GetIntField(settings, env->GetFieldID(clazz, "mConstellation", "I")));
2172     FrontendDvbtHierarchy hierarchy =
2173             static_cast<FrontendDvbtHierarchy>(
2174                     env->GetIntField(settings, env->GetFieldID(clazz, "mHierarchy", "I")));
2175     FrontendDvbtCoderate hpCoderate =
2176             static_cast<FrontendDvbtCoderate>(
2177                     env->GetIntField(settings, env->GetFieldID(clazz, "mHpCodeRate", "I")));
2178     FrontendDvbtCoderate lpCoderate =
2179             static_cast<FrontendDvbtCoderate>(
2180                     env->GetIntField(settings, env->GetFieldID(clazz, "mLpCodeRate", "I")));
2181     FrontendDvbtGuardInterval guardInterval =
2182             static_cast<FrontendDvbtGuardInterval>(
2183                     env->GetIntField(settings, env->GetFieldID(clazz, "mGuardInterval", "I")));
2184     bool isHighPriority =
2185             static_cast<bool>(
2186                     env->GetBooleanField(
2187                             settings, env->GetFieldID(clazz, "mIsHighPriority", "Z")));
2188     FrontendDvbtStandard standard =
2189             static_cast<FrontendDvbtStandard>(
2190                     env->GetIntField(settings, env->GetFieldID(clazz, "mStandard", "I")));
2191     bool isMiso =
2192             static_cast<bool>(
2193                     env->GetBooleanField(settings, env->GetFieldID(clazz, "mIsMiso", "Z")));
2194     FrontendDvbtPlpMode plpMode =
2195             static_cast<FrontendDvbtPlpMode>(
2196                     env->GetIntField(settings, env->GetFieldID(clazz, "mPlpMode", "I")));
2197     uint8_t plpId =
2198             static_cast<uint8_t>(
2199                     env->GetIntField(settings, env->GetFieldID(clazz, "mPlpId", "I")));
2200     uint8_t plpGroupId =
2201             static_cast<uint8_t>(
2202                     env->GetIntField(settings, env->GetFieldID(clazz, "mPlpGroupId", "I")));
2203 
2204     FrontendDvbtSettings frontendDvbtSettings {
2205             .frequency = freq,
2206             .transmissionMode = transmissionMode,
2207             .bandwidth = bandwidth,
2208             .constellation = constellation,
2209             .hierarchy = hierarchy,
2210             .hpCoderate = hpCoderate,
2211             .lpCoderate = lpCoderate,
2212             .guardInterval = guardInterval,
2213             .isHighPriority = isHighPriority,
2214             .standard = standard,
2215             .isMiso = isMiso,
2216             .plpMode = plpMode,
2217             .plpId = plpId,
2218             .plpGroupId = plpGroupId,
2219     };
2220     frontendSettings.dvbt(frontendDvbtSettings);
2221     return frontendSettings;
2222 }
2223 
getIsdbsFrontendSettings(JNIEnv * env,const jobject & settings)2224 static FrontendSettings getIsdbsFrontendSettings(JNIEnv *env, const jobject& settings) {
2225     FrontendSettings frontendSettings;
2226     uint32_t freq = getFrontendSettingsFreq(env, settings);
2227     jclass clazz = env->FindClass("android/media/tv/tuner/frontend/IsdbsFrontendSettings");
2228     uint16_t streamId =
2229             static_cast<uint16_t>(
2230                     env->GetIntField(settings, env->GetFieldID(clazz, "mStreamId", "I")));
2231     FrontendIsdbsStreamIdType streamIdType =
2232             static_cast<FrontendIsdbsStreamIdType>(
2233                     env->GetIntField(settings, env->GetFieldID(clazz, "mStreamIdType", "I")));
2234     FrontendIsdbsModulation modulation =
2235             static_cast<FrontendIsdbsModulation>(
2236                     env->GetIntField(settings, env->GetFieldID(clazz, "mModulation", "I")));
2237     FrontendIsdbsCoderate coderate =
2238             static_cast<FrontendIsdbsCoderate>(
2239                     env->GetIntField(settings, env->GetFieldID(clazz, "mCodeRate", "I")));
2240     uint32_t symbolRate =
2241             static_cast<uint32_t>(
2242                     env->GetIntField(settings, env->GetFieldID(clazz, "mSymbolRate", "I")));
2243     FrontendIsdbsRolloff rolloff =
2244             static_cast<FrontendIsdbsRolloff>(
2245                     env->GetIntField(settings, env->GetFieldID(clazz, "mRolloff", "I")));
2246 
2247     FrontendIsdbsSettings frontendIsdbsSettings {
2248             .frequency = freq,
2249             .streamId = streamId,
2250             .streamIdType = streamIdType,
2251             .modulation = modulation,
2252             .coderate = coderate,
2253             .symbolRate = symbolRate,
2254             .rolloff = rolloff,
2255     };
2256     frontendSettings.isdbs(frontendIsdbsSettings);
2257     return frontendSettings;
2258 }
2259 
getIsdbs3FrontendSettings(JNIEnv * env,const jobject & settings)2260 static FrontendSettings getIsdbs3FrontendSettings(JNIEnv *env, const jobject& settings) {
2261     FrontendSettings frontendSettings;
2262     uint32_t freq = getFrontendSettingsFreq(env, settings);
2263     jclass clazz = env->FindClass("android/media/tv/tuner/frontend/Isdbs3FrontendSettings");
2264     uint16_t streamId =
2265             static_cast<uint16_t>(
2266                     env->GetIntField(settings, env->GetFieldID(clazz, "mStreamId", "I")));
2267     FrontendIsdbsStreamIdType streamIdType =
2268             static_cast<FrontendIsdbsStreamIdType>(
2269                     env->GetIntField(settings, env->GetFieldID(clazz, "mStreamIdType", "I")));
2270     FrontendIsdbs3Modulation modulation =
2271             static_cast<FrontendIsdbs3Modulation>(
2272                     env->GetIntField(settings, env->GetFieldID(clazz, "mModulation", "I")));
2273     FrontendIsdbs3Coderate coderate =
2274             static_cast<FrontendIsdbs3Coderate>(
2275                     env->GetIntField(settings, env->GetFieldID(clazz, "mCodeRate", "I")));
2276     uint32_t symbolRate =
2277             static_cast<uint32_t>(
2278                     env->GetIntField(settings, env->GetFieldID(clazz, "mSymbolRate", "I")));
2279     FrontendIsdbs3Rolloff rolloff =
2280             static_cast<FrontendIsdbs3Rolloff>(
2281                     env->GetIntField(settings, env->GetFieldID(clazz, "mRolloff", "I")));
2282 
2283     FrontendIsdbs3Settings frontendIsdbs3Settings {
2284             .frequency = freq,
2285             .streamId = streamId,
2286             .streamIdType = streamIdType,
2287             .modulation = modulation,
2288             .coderate = coderate,
2289             .symbolRate = symbolRate,
2290             .rolloff = rolloff,
2291     };
2292     frontendSettings.isdbs3(frontendIsdbs3Settings);
2293     return frontendSettings;
2294 }
2295 
getIsdbtFrontendSettings(JNIEnv * env,const jobject & settings)2296 static FrontendSettings getIsdbtFrontendSettings(JNIEnv *env, const jobject& settings) {
2297     FrontendSettings frontendSettings;
2298     uint32_t freq = getFrontendSettingsFreq(env, settings);
2299     jclass clazz = env->FindClass("android/media/tv/tuner/frontend/IsdbtFrontendSettings");
2300     FrontendIsdbtModulation modulation =
2301             static_cast<FrontendIsdbtModulation>(
2302                     env->GetIntField(settings, env->GetFieldID(clazz, "mModulation", "I")));
2303     FrontendIsdbtBandwidth bandwidth =
2304             static_cast<FrontendIsdbtBandwidth>(
2305                     env->GetIntField(settings, env->GetFieldID(clazz, "mBandwidth", "I")));
2306     FrontendIsdbtMode mode =
2307             static_cast<FrontendIsdbtMode>(
2308                     env->GetIntField(settings, env->GetFieldID(clazz, "mMode", "I")));
2309     FrontendIsdbtCoderate coderate =
2310             static_cast<FrontendIsdbtCoderate>(
2311                     env->GetIntField(settings, env->GetFieldID(clazz, "mCodeRate", "I")));
2312     FrontendIsdbtGuardInterval guardInterval =
2313             static_cast<FrontendIsdbtGuardInterval>(
2314                     env->GetIntField(settings, env->GetFieldID(clazz, "mGuardInterval", "I")));
2315     uint32_t serviceAreaId =
2316             static_cast<uint32_t>(
2317                     env->GetIntField(settings, env->GetFieldID(clazz, "mServiceAreaId", "I")));
2318 
2319     FrontendIsdbtSettings frontendIsdbtSettings {
2320             .frequency = freq,
2321             .modulation = modulation,
2322             .bandwidth = bandwidth,
2323             .mode = mode,
2324             .coderate = coderate,
2325             .guardInterval = guardInterval,
2326             .serviceAreaId = serviceAreaId,
2327     };
2328     frontendSettings.isdbt(frontendIsdbtSettings);
2329     return frontendSettings;
2330 }
2331 
getFrontendSettings(JNIEnv * env,int type,jobject settings)2332 static FrontendSettings getFrontendSettings(JNIEnv *env, int type, jobject settings) {
2333     ALOGD("getFrontendSettings %d", type);
2334 
2335     FrontendType feType = static_cast<FrontendType>(type);
2336     switch(feType) {
2337         case FrontendType::ANALOG:
2338             return getAnalogFrontendSettings(env, settings);
2339         case FrontendType::ATSC3:
2340             return getAtsc3FrontendSettings(env, settings);
2341         case FrontendType::ATSC:
2342             return getAtscFrontendSettings(env, settings);
2343         case FrontendType::DVBC:
2344             return getDvbcFrontendSettings(env, settings);
2345         case FrontendType::DVBS:
2346             return getDvbsFrontendSettings(env, settings);
2347         case FrontendType::DVBT:
2348             return getDvbtFrontendSettings(env, settings);
2349         case FrontendType::ISDBS:
2350             return getIsdbsFrontendSettings(env, settings);
2351         case FrontendType::ISDBS3:
2352             return getIsdbs3FrontendSettings(env, settings);
2353         case FrontendType::ISDBT:
2354             return getIsdbtFrontendSettings(env, settings);
2355         default:
2356             // should never happen because a type is associated with a subclass of
2357             // FrontendSettings and not set by users
2358             jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
2359                 "Unsupported frontend type %d", type);
2360             return FrontendSettings();
2361     }
2362 }
2363 
getFilter(JNIEnv * env,jobject filter)2364 static sp<Filter> getFilter(JNIEnv *env, jobject filter) {
2365     return (Filter *)env->GetLongField(filter, gFields.filterContext);
2366 }
2367 
getDvrSettings(JNIEnv * env,jobject settings,bool isRecorder)2368 static DvrSettings getDvrSettings(JNIEnv *env, jobject settings, bool isRecorder) {
2369     DvrSettings dvrSettings;
2370     jclass clazz = env->FindClass("android/media/tv/tuner/dvr/DvrSettings");
2371     uint32_t statusMask =
2372             static_cast<uint32_t>(env->GetIntField(
2373                     settings, env->GetFieldID(clazz, "mStatusMask", "I")));
2374     uint32_t lowThreshold =
2375             static_cast<uint32_t>(env->GetLongField(
2376                     settings, env->GetFieldID(clazz, "mLowThreshold", "J")));
2377     uint32_t highThreshold =
2378             static_cast<uint32_t>(env->GetLongField(
2379                     settings, env->GetFieldID(clazz, "mHighThreshold", "J")));
2380     uint8_t packetSize =
2381             static_cast<uint8_t>(env->GetLongField(
2382                     settings, env->GetFieldID(clazz, "mPacketSize", "J")));
2383     DataFormat dataFormat =
2384             static_cast<DataFormat>(env->GetIntField(
2385                     settings, env->GetFieldID(clazz, "mDataFormat", "I")));
2386     if (isRecorder) {
2387         RecordSettings recordSettings {
2388                 .statusMask = static_cast<unsigned char>(statusMask),
2389                 .lowThreshold = lowThreshold,
2390                 .highThreshold = highThreshold,
2391                 .dataFormat = dataFormat,
2392                 .packetSize = packetSize,
2393         };
2394         dvrSettings.record(recordSettings);
2395     } else {
2396         PlaybackSettings PlaybackSettings {
2397                 .statusMask = statusMask,
2398                 .lowThreshold = lowThreshold,
2399                 .highThreshold = highThreshold,
2400                 .dataFormat = dataFormat,
2401                 .packetSize = packetSize,
2402         };
2403         dvrSettings.playback(PlaybackSettings);
2404     }
2405     return dvrSettings;
2406 }
2407 
getDvr(JNIEnv * env,jobject dvr)2408 static sp<Dvr> getDvr(JNIEnv *env, jobject dvr) {
2409     bool isRecorder =
2410             env->IsInstanceOf(dvr, env->FindClass("android/media/tv/tuner/dvr/DvrRecorder"));
2411     jfieldID fieldId =
2412             isRecorder ? gFields.dvrRecorderContext : gFields.dvrPlaybackContext;
2413     return (Dvr *)env->GetLongField(dvr, fieldId);
2414 }
2415 
android_media_tv_Tuner_native_init(JNIEnv * env)2416 static void android_media_tv_Tuner_native_init(JNIEnv *env) {
2417     jclass clazz = env->FindClass("android/media/tv/tuner/Tuner");
2418     CHECK(clazz != NULL);
2419 
2420     gFields.tunerContext = env->GetFieldID(clazz, "mNativeContext", "J");
2421     CHECK(gFields.tunerContext != NULL);
2422 
2423     gFields.onFrontendEventID = env->GetMethodID(clazz, "onFrontendEvent", "(I)V");
2424 
2425     jclass frontendClazz = env->FindClass("android/media/tv/tuner/Tuner$Frontend");
2426     gFields.frontendInitID =
2427             env->GetMethodID(frontendClazz, "<init>", "(Landroid/media/tv/tuner/Tuner;I)V");
2428 
2429     jclass lnbClazz = env->FindClass("android/media/tv/tuner/Lnb");
2430     gFields.lnbContext = env->GetFieldID(lnbClazz, "mNativeContext", "J");
2431     gFields.lnbInitID = env->GetMethodID(lnbClazz, "<init>", "(I)V");
2432     gFields.onLnbEventID = env->GetMethodID(lnbClazz, "onEvent", "(I)V");
2433     gFields.onLnbDiseqcMessageID = env->GetMethodID(lnbClazz, "onDiseqcMessage", "([B)V");
2434 
2435     jclass filterClazz = env->FindClass("android/media/tv/tuner/filter/Filter");
2436     gFields.filterContext = env->GetFieldID(filterClazz, "mNativeContext", "J");
2437     gFields.filterInitID =
2438             env->GetMethodID(filterClazz, "<init>", "(I)V");
2439     gFields.onFilterStatusID =
2440             env->GetMethodID(filterClazz, "onFilterStatus", "(I)V");
2441     gFields.onFilterEventID =
2442             env->GetMethodID(filterClazz, "onFilterEvent",
2443                     "([Landroid/media/tv/tuner/filter/FilterEvent;)V");
2444 
2445     jclass timeFilterClazz = env->FindClass("android/media/tv/tuner/filter/TimeFilter");
2446     gFields.timeFilterContext = env->GetFieldID(timeFilterClazz, "mNativeContext", "J");
2447     gFields.timeFilterInitID = env->GetMethodID(timeFilterClazz, "<init>", "()V");
2448 
2449     jclass descramblerClazz = env->FindClass("android/media/tv/tuner/Descrambler");
2450     gFields.descramblerContext = env->GetFieldID(descramblerClazz, "mNativeContext", "J");
2451     gFields.descramblerInitID = env->GetMethodID(descramblerClazz, "<init>", "()V");
2452 
2453     jclass dvrRecorderClazz = env->FindClass("android/media/tv/tuner/dvr/DvrRecorder");
2454     gFields.dvrRecorderContext = env->GetFieldID(dvrRecorderClazz, "mNativeContext", "J");
2455     gFields.dvrRecorderInitID = env->GetMethodID(dvrRecorderClazz, "<init>", "()V");
2456     gFields.onDvrRecordStatusID =
2457             env->GetMethodID(dvrRecorderClazz, "onRecordStatusChanged", "(I)V");
2458 
2459     jclass dvrPlaybackClazz = env->FindClass("android/media/tv/tuner/dvr/DvrPlayback");
2460     gFields.dvrPlaybackContext = env->GetFieldID(dvrPlaybackClazz, "mNativeContext", "J");
2461     gFields.dvrPlaybackInitID = env->GetMethodID(dvrPlaybackClazz, "<init>", "()V");
2462     gFields.onDvrPlaybackStatusID =
2463             env->GetMethodID(dvrPlaybackClazz, "onPlaybackStatusChanged", "(I)V");
2464 
2465     jclass mediaEventClazz = env->FindClass("android/media/tv/tuner/filter/MediaEvent");
2466     gFields.mediaEventContext = env->GetFieldID(mediaEventClazz, "mNativeContext", "J");
2467 
2468     jclass linearBlockClazz = env->FindClass("android/media/MediaCodec$LinearBlock");
2469     gFields.linearBlockInitID = env->GetMethodID(linearBlockClazz, "<init>", "()V");
2470     gFields.linearBlockSetInternalStateID =
2471             env->GetMethodID(linearBlockClazz, "setInternalStateLocked", "(JZ)V");
2472 }
2473 
android_media_tv_Tuner_native_setup(JNIEnv * env,jobject thiz)2474 static void android_media_tv_Tuner_native_setup(JNIEnv *env, jobject thiz) {
2475     sp<JTuner> tuner = new JTuner(env, thiz);
2476     setTuner(env,thiz, tuner);
2477 }
2478 
android_media_tv_Tuner_get_frontend_ids(JNIEnv * env,jobject thiz)2479 static jobject android_media_tv_Tuner_get_frontend_ids(JNIEnv *env, jobject thiz) {
2480     sp<JTuner> tuner = getTuner(env, thiz);
2481     return tuner->getFrontendIds();
2482 }
2483 
android_media_tv_Tuner_open_frontend_by_handle(JNIEnv * env,jobject thiz,jint handle)2484 static jobject android_media_tv_Tuner_open_frontend_by_handle(
2485         JNIEnv *env, jobject thiz, jint handle) {
2486     sp<JTuner> tuner = getTuner(env, thiz);
2487     uint32_t id = getResourceIdFromHandle(handle);
2488     return tuner->openFrontendById(id);
2489 }
2490 
android_media_tv_Tuner_close_frontend_by_handle(JNIEnv * env,jobject thiz,jint handle)2491 static jint android_media_tv_Tuner_close_frontend_by_handle(
2492         JNIEnv *env, jobject thiz, jint handle) {
2493     sp<JTuner> tuner = getTuner(env, thiz);
2494     uint32_t id = getResourceIdFromHandle(handle);
2495     return tuner->closeFrontendById(id);
2496 }
2497 
android_media_tv_Tuner_tune(JNIEnv * env,jobject thiz,jint type,jobject settings)2498 static int android_media_tv_Tuner_tune(JNIEnv *env, jobject thiz, jint type, jobject settings) {
2499     sp<JTuner> tuner = getTuner(env, thiz);
2500     return tuner->tune(getFrontendSettings(env, type, settings));
2501 }
2502 
android_media_tv_Tuner_stop_tune(JNIEnv * env,jobject thiz)2503 static int android_media_tv_Tuner_stop_tune(JNIEnv *env, jobject thiz) {
2504     sp<JTuner> tuner = getTuner(env, thiz);
2505     return tuner->stopTune();
2506 }
2507 
android_media_tv_Tuner_scan(JNIEnv * env,jobject thiz,jint settingsType,jobject settings,jint scanType)2508 static int android_media_tv_Tuner_scan(
2509         JNIEnv *env, jobject thiz, jint settingsType, jobject settings, jint scanType) {
2510     sp<JTuner> tuner = getTuner(env, thiz);
2511     return tuner->scan(getFrontendSettings(
2512             env, settingsType, settings), static_cast<FrontendScanType>(scanType));
2513 }
2514 
android_media_tv_Tuner_stop_scan(JNIEnv * env,jobject thiz)2515 static int android_media_tv_Tuner_stop_scan(JNIEnv *env, jobject thiz) {
2516     sp<JTuner> tuner = getTuner(env, thiz);
2517     return tuner->stopScan();
2518 }
2519 
android_media_tv_Tuner_set_lnb(JNIEnv * env,jobject thiz,jint id)2520 static int android_media_tv_Tuner_set_lnb(JNIEnv *env, jobject thiz, jint id) {
2521     sp<JTuner> tuner = getTuner(env, thiz);
2522     return tuner->setLnb(id);
2523 }
2524 
android_media_tv_Tuner_set_lna(JNIEnv * env,jobject thiz,jboolean enable)2525 static int android_media_tv_Tuner_set_lna(JNIEnv *env, jobject thiz, jboolean enable) {
2526     sp<JTuner> tuner = getTuner(env, thiz);
2527     return tuner->setLna(enable);
2528 }
2529 
android_media_tv_Tuner_get_frontend_status(JNIEnv * env,jobject thiz,jintArray types)2530 static jobject android_media_tv_Tuner_get_frontend_status(
2531         JNIEnv* env, jobject thiz, jintArray types) {
2532     sp<JTuner> tuner = getTuner(env, thiz);
2533     return tuner->getFrontendStatus(types);
2534 }
2535 
android_media_tv_Tuner_get_av_sync_hw_id(JNIEnv * env,jobject thiz,jobject filter)2536 static jobject android_media_tv_Tuner_get_av_sync_hw_id(
2537         JNIEnv *env, jobject thiz, jobject filter) {
2538     sp<Filter> filterSp = getFilter(env, filter);
2539     if (filterSp == NULL) {
2540         ALOGD("Failed to get sync ID. Filter not found");
2541         return NULL;
2542     }
2543     sp<JTuner> tuner = getTuner(env, thiz);
2544     return tuner->getAvSyncHwId(filterSp);
2545 }
2546 
android_media_tv_Tuner_get_av_sync_time(JNIEnv * env,jobject thiz,jint id)2547 static jobject android_media_tv_Tuner_get_av_sync_time(JNIEnv *env, jobject thiz, jint id) {
2548     sp<JTuner> tuner = getTuner(env, thiz);
2549     return tuner->getAvSyncTime(id);
2550 }
2551 
android_media_tv_Tuner_connect_cicam(JNIEnv * env,jobject thiz,jint id)2552 static int android_media_tv_Tuner_connect_cicam(JNIEnv *env, jobject thiz, jint id) {
2553     sp<JTuner> tuner = getTuner(env, thiz);
2554     return tuner->connectCiCam(id);
2555 }
2556 
android_media_tv_Tuner_disconnect_cicam(JNIEnv * env,jobject thiz)2557 static int android_media_tv_Tuner_disconnect_cicam(JNIEnv *env, jobject thiz) {
2558     sp<JTuner> tuner = getTuner(env, thiz);
2559     return tuner->disconnectCiCam();
2560 }
2561 
android_media_tv_Tuner_get_frontend_info(JNIEnv * env,jobject thiz,jint id)2562 static jobject android_media_tv_Tuner_get_frontend_info(JNIEnv *env, jobject thiz, jint id) {
2563     sp<JTuner> tuner = getTuner(env, thiz);
2564     return tuner->getFrontendInfo(id);
2565 }
2566 
android_media_tv_Tuner_get_lnb_ids(JNIEnv * env,jobject thiz)2567 static jintArray android_media_tv_Tuner_get_lnb_ids(JNIEnv *env, jobject thiz) {
2568     sp<JTuner> tuner = getTuner(env, thiz);
2569     return tuner->getLnbIds();
2570 }
2571 
android_media_tv_Tuner_open_lnb_by_handle(JNIEnv * env,jobject thiz,jint handle)2572 static jobject android_media_tv_Tuner_open_lnb_by_handle(JNIEnv *env, jobject thiz, jint handle) {
2573     sp<JTuner> tuner = getTuner(env, thiz);
2574     uint32_t id = getResourceIdFromHandle(handle);
2575     return tuner->openLnbById(id);
2576 }
2577 
android_media_tv_Tuner_open_lnb_by_name(JNIEnv * env,jobject thiz,jstring name)2578 static jobject android_media_tv_Tuner_open_lnb_by_name(JNIEnv *env, jobject thiz, jstring name) {
2579     sp<JTuner> tuner = getTuner(env, thiz);
2580     return tuner->openLnbByName(name);
2581 }
2582 
2583 
android_media_tv_Tuner_open_filter(JNIEnv * env,jobject thiz,jint type,jint subType,jlong bufferSize)2584 static jobject android_media_tv_Tuner_open_filter(
2585         JNIEnv *env, jobject thiz, jint type, jint subType, jlong bufferSize) {
2586     sp<JTuner> tuner = getTuner(env, thiz);
2587     DemuxFilterMainType mainType = static_cast<DemuxFilterMainType>(type);
2588     DemuxFilterType filterType {
2589         .mainType = mainType,
2590     };
2591 
2592     switch(mainType) {
2593         case DemuxFilterMainType::TS:
2594             filterType.subType.tsFilterType(static_cast<DemuxTsFilterType>(subType));
2595             break;
2596         case DemuxFilterMainType::MMTP:
2597             filterType.subType.mmtpFilterType(static_cast<DemuxMmtpFilterType>(subType));
2598             break;
2599         case DemuxFilterMainType::IP:
2600             filterType.subType.ipFilterType(static_cast<DemuxIpFilterType>(subType));
2601             break;
2602         case DemuxFilterMainType::TLV:
2603             filterType.subType.tlvFilterType(static_cast<DemuxTlvFilterType>(subType));
2604             break;
2605         case DemuxFilterMainType::ALP:
2606             filterType.subType.alpFilterType(static_cast<DemuxAlpFilterType>(subType));
2607             break;
2608     }
2609 
2610     return tuner->openFilter(filterType, bufferSize);
2611 }
2612 
android_media_tv_Tuner_open_time_filter(JNIEnv * env,jobject thiz)2613 static jobject android_media_tv_Tuner_open_time_filter(JNIEnv *env, jobject thiz) {
2614     sp<JTuner> tuner = getTuner(env, thiz);
2615     return tuner->openTimeFilter();
2616 }
2617 
getFilterSectionBits(JNIEnv * env,const jobject & settings)2618 static DemuxFilterSectionBits getFilterSectionBits(JNIEnv *env, const jobject& settings) {
2619     jclass clazz = env->FindClass("android/media/tv/tuner/filter/SectionSettingsWithSectionBits");
2620     jbyteArray jfilterBytes = static_cast<jbyteArray>(
2621             env->GetObjectField(settings, env->GetFieldID(clazz, "mFilter", "[B")));
2622     jsize size = env->GetArrayLength(jfilterBytes);
2623     std::vector<uint8_t> filterBytes(size);
2624     env->GetByteArrayRegion(
2625             jfilterBytes, 0, size, reinterpret_cast<jbyte*>(&filterBytes[0]));
2626 
2627     jbyteArray jmask = static_cast<jbyteArray>(
2628             env->GetObjectField(settings, env->GetFieldID(clazz, "mMask", "[B")));
2629     size = env->GetArrayLength(jmask);
2630     std::vector<uint8_t> mask(size);
2631     env->GetByteArrayRegion(jmask, 0, size, reinterpret_cast<jbyte*>(&mask[0]));
2632 
2633     jbyteArray jmode = static_cast<jbyteArray>(
2634             env->GetObjectField(settings, env->GetFieldID(clazz, "mMode", "[B")));
2635     size = env->GetArrayLength(jmode);
2636     std::vector<uint8_t> mode(size);
2637     env->GetByteArrayRegion(jmode, 0, size, reinterpret_cast<jbyte*>(&mode[0]));
2638 
2639     DemuxFilterSectionBits filterSectionBits {
2640         .filter = filterBytes,
2641         .mask = mask,
2642         .mode = mode,
2643     };
2644     return filterSectionBits;
2645 }
2646 
getFilterTableInfo(JNIEnv * env,const jobject & settings)2647 static DemuxFilterSectionSettings::Condition::TableInfo getFilterTableInfo(
2648         JNIEnv *env, const jobject& settings) {
2649     jclass clazz = env->FindClass("android/media/tv/tuner/filter/SectionSettingsWithTableInfo");
2650     uint16_t tableId = static_cast<uint16_t>(
2651             env->GetIntField(settings, env->GetFieldID(clazz, "mTableId", "I")));
2652     uint16_t version = static_cast<uint16_t>(
2653             env->GetIntField(settings, env->GetFieldID(clazz, "mVersion", "I")));
2654     DemuxFilterSectionSettings::Condition::TableInfo tableInfo {
2655         .tableId = tableId,
2656         .version = version,
2657     };
2658     return tableInfo;
2659 }
2660 
getFilterSectionSettings(JNIEnv * env,const jobject & settings)2661 static DemuxFilterSectionSettings getFilterSectionSettings(JNIEnv *env, const jobject& settings) {
2662     jclass clazz = env->FindClass("android/media/tv/tuner/filter/SectionSettings");
2663     bool isCheckCrc = static_cast<bool>(
2664             env->GetBooleanField(settings, env->GetFieldID(clazz, "mCrcEnabled", "Z")));
2665     bool isRepeat = static_cast<bool>(
2666             env->GetBooleanField(settings, env->GetFieldID(clazz, "mIsRepeat", "Z")));
2667     bool isRaw = static_cast<bool>(
2668             env->GetBooleanField(settings, env->GetFieldID(clazz, "mIsRaw", "Z")));
2669 
2670     DemuxFilterSectionSettings filterSectionSettings {
2671         .isCheckCrc = isCheckCrc,
2672         .isRepeat = isRepeat,
2673         .isRaw = isRaw,
2674     };
2675     if (env->IsInstanceOf(
2676             settings,
2677             env->FindClass("android/media/tv/tuner/filter/SectionSettingsWithSectionBits"))) {
2678         filterSectionSettings.condition.sectionBits(getFilterSectionBits(env, settings));
2679     } else if (env->IsInstanceOf(
2680             settings,
2681             env->FindClass("android/media/tv/tuner/filter/SectionSettingsWithTableInfo"))) {
2682         filterSectionSettings.condition.tableInfo(getFilterTableInfo(env, settings));
2683     }
2684     return filterSectionSettings;
2685 }
2686 
getFilterAvSettings(JNIEnv * env,const jobject & settings)2687 static DemuxFilterAvSettings getFilterAvSettings(JNIEnv *env, const jobject& settings) {
2688     jclass clazz = env->FindClass("android/media/tv/tuner/filter/AvSettings");
2689     bool isPassthrough = static_cast<bool>(
2690             env->GetBooleanField(settings, env->GetFieldID(clazz, "mIsPassthrough", "Z")));
2691     DemuxFilterAvSettings filterAvSettings {
2692         .isPassthrough = isPassthrough,
2693     };
2694     return filterAvSettings;
2695 }
2696 
getFilterPesDataSettings(JNIEnv * env,const jobject & settings)2697 static DemuxFilterPesDataSettings getFilterPesDataSettings(JNIEnv *env, const jobject& settings) {
2698     jclass clazz = env->FindClass("android/media/tv/tuner/filter/PesSettings");
2699     uint16_t streamId = static_cast<uint16_t>(
2700             env->GetIntField(settings, env->GetFieldID(clazz, "mStreamId", "I")));
2701     bool isRaw = static_cast<bool>(
2702             env->GetBooleanField(settings, env->GetFieldID(clazz, "mIsRaw", "Z")));
2703     DemuxFilterPesDataSettings filterPesDataSettings {
2704         .streamId = streamId,
2705         .isRaw = isRaw,
2706     };
2707     return filterPesDataSettings;
2708 }
2709 
getFilterRecordSettings(JNIEnv * env,const jobject & settings)2710 static DemuxFilterRecordSettings getFilterRecordSettings(JNIEnv *env, const jobject& settings) {
2711     jclass clazz = env->FindClass("android/media/tv/tuner/filter/RecordSettings");
2712     hidl_bitfield<DemuxTsIndex> tsIndexMask = static_cast<hidl_bitfield<DemuxTsIndex>>(
2713             env->GetIntField(settings, env->GetFieldID(clazz, "mTsIndexMask", "I")));
2714     DemuxRecordScIndexType scIndexType = static_cast<DemuxRecordScIndexType>(
2715             env->GetIntField(settings, env->GetFieldID(clazz, "mScIndexType", "I")));
2716     jint scIndexMask = env->GetIntField(settings, env->GetFieldID(clazz, "mScIndexMask", "I"));
2717 
2718     DemuxFilterRecordSettings filterRecordSettings {
2719         .tsIndexMask = tsIndexMask,
2720         .scIndexType = scIndexType,
2721     };
2722     if (scIndexType == DemuxRecordScIndexType::SC) {
2723         filterRecordSettings.scIndexMask.sc(static_cast<hidl_bitfield<DemuxScIndex>>(scIndexMask));
2724     } else if (scIndexType == DemuxRecordScIndexType::SC_HEVC) {
2725         filterRecordSettings.scIndexMask.scHevc(
2726                 static_cast<hidl_bitfield<DemuxScHevcIndex>>(scIndexMask));
2727     }
2728     return filterRecordSettings;
2729 }
2730 
getFilterDownloadSettings(JNIEnv * env,const jobject & settings)2731 static DemuxFilterDownloadSettings getFilterDownloadSettings(JNIEnv *env, const jobject& settings) {
2732     jclass clazz = env->FindClass("android/media/tv/tuner/filter/DownloadSettings");
2733     uint32_t downloadId = static_cast<uint32_t>(
2734             env->GetIntField(settings, env->GetFieldID(clazz, "mDownloadId", "I")));
2735 
2736     DemuxFilterDownloadSettings filterDownloadSettings {
2737         .downloadId = downloadId,
2738     };
2739     return filterDownloadSettings;
2740 }
2741 
getDemuxIpAddress(JNIEnv * env,const jobject & config)2742 static DemuxIpAddress getDemuxIpAddress(JNIEnv *env, const jobject& config) {
2743     jclass clazz = env->FindClass("android/media/tv/tuner/filter/IpFilterConfiguration");
2744 
2745     jbyteArray jsrcIpAddress = static_cast<jbyteArray>(
2746             env->GetObjectField(config, env->GetFieldID(clazz, "mSrcIpAddress", "[B")));
2747     jsize srcSize = env->GetArrayLength(jsrcIpAddress);
2748     jbyteArray jdstIpAddress = static_cast<jbyteArray>(
2749             env->GetObjectField(config, env->GetFieldID(clazz, "mDstIpAddress", "[B")));
2750     jsize dstSize = env->GetArrayLength(jdstIpAddress);
2751 
2752     DemuxIpAddress res;
2753 
2754     if (srcSize != dstSize) {
2755         // should never happen. Validated on Java size.
2756         jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
2757             "IP address lengths don't match. srcLength=%d, dstLength=%d", srcSize, dstSize);
2758         return res;
2759     }
2760 
2761     if (srcSize == IP_V4_LENGTH) {
2762         uint8_t srcAddr[IP_V4_LENGTH];
2763         uint8_t dstAddr[IP_V4_LENGTH];
2764         env->GetByteArrayRegion(
2765                 jsrcIpAddress, 0, srcSize, reinterpret_cast<jbyte*>(srcAddr));
2766         env->GetByteArrayRegion(
2767                 jdstIpAddress, 0, dstSize, reinterpret_cast<jbyte*>(dstAddr));
2768         res.srcIpAddress.v4(srcAddr);
2769         res.dstIpAddress.v4(dstAddr);
2770     } else if (srcSize == IP_V6_LENGTH) {
2771         uint8_t srcAddr[IP_V6_LENGTH];
2772         uint8_t dstAddr[IP_V6_LENGTH];
2773         env->GetByteArrayRegion(
2774                 jsrcIpAddress, 0, srcSize, reinterpret_cast<jbyte*>(srcAddr));
2775         env->GetByteArrayRegion(
2776                 jdstIpAddress, 0, dstSize, reinterpret_cast<jbyte*>(dstAddr));
2777         res.srcIpAddress.v6(srcAddr);
2778         res.dstIpAddress.v6(dstAddr);
2779     } else {
2780         // should never happen. Validated on Java size.
2781         jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
2782             "Invalid IP address length %d", srcSize);
2783         return res;
2784     }
2785 
2786     uint16_t srcPort = static_cast<uint16_t>(
2787             env->GetIntField(config, env->GetFieldID(clazz, "mSrcPort", "I")));
2788     uint16_t dstPort = static_cast<uint16_t>(
2789             env->GetIntField(config, env->GetFieldID(clazz, "mDstPort", "I")));
2790 
2791     res.srcPort = srcPort;
2792     res.dstPort = dstPort;
2793 
2794     return res;
2795 }
2796 
getFilterConfiguration(JNIEnv * env,int type,int subtype,jobject filterConfigObj)2797 static DemuxFilterSettings getFilterConfiguration(
2798         JNIEnv *env, int type, int subtype, jobject filterConfigObj) {
2799     DemuxFilterSettings filterSettings;
2800     jobject settingsObj =
2801             env->GetObjectField(
2802                     filterConfigObj,
2803                     env->GetFieldID(
2804                             env->FindClass("android/media/tv/tuner/filter/FilterConfiguration"),
2805                             "mSettings",
2806                             "Landroid/media/tv/tuner/filter/Settings;"));
2807     DemuxFilterMainType mainType = static_cast<DemuxFilterMainType>(type);
2808     switch (mainType) {
2809         case DemuxFilterMainType::TS: {
2810             jclass clazz = env->FindClass("android/media/tv/tuner/filter/TsFilterConfiguration");
2811             uint16_t tpid = static_cast<uint16_t>(
2812                     env->GetIntField(filterConfigObj, env->GetFieldID(clazz, "mTpid", "I")));
2813             DemuxTsFilterSettings tsFilterSettings {
2814                 .tpid = tpid,
2815             };
2816 
2817             DemuxTsFilterType tsType = static_cast<DemuxTsFilterType>(subtype);
2818             switch (tsType) {
2819                 case DemuxTsFilterType::SECTION:
2820                     tsFilterSettings.filterSettings.section(
2821                             getFilterSectionSettings(env, settingsObj));
2822                     break;
2823                 case DemuxTsFilterType::AUDIO:
2824                 case DemuxTsFilterType::VIDEO:
2825                     tsFilterSettings.filterSettings.av(getFilterAvSettings(env, settingsObj));
2826                     break;
2827                 case DemuxTsFilterType::PES:
2828                     tsFilterSettings.filterSettings.pesData(
2829                             getFilterPesDataSettings(env, settingsObj));
2830                     break;
2831                 case DemuxTsFilterType::RECORD:
2832                     tsFilterSettings.filterSettings.record(
2833                             getFilterRecordSettings(env, settingsObj));
2834                     break;
2835                 default:
2836                     break;
2837             }
2838             filterSettings.ts(tsFilterSettings);
2839             break;
2840         }
2841         case DemuxFilterMainType::MMTP: {
2842             jclass clazz = env->FindClass("android/media/tv/tuner/filter/MmtpFilterConfiguration");
2843             uint16_t mmtpPid = static_cast<uint16_t>(
2844                     env->GetIntField(filterConfigObj, env->GetFieldID(clazz, "mMmtpPid", "I")));
2845             DemuxMmtpFilterSettings mmtpFilterSettings {
2846                 .mmtpPid = mmtpPid,
2847             };
2848             DemuxMmtpFilterType mmtpType = static_cast<DemuxMmtpFilterType>(subtype);
2849             switch (mmtpType) {
2850                 case DemuxMmtpFilterType::SECTION:
2851                     mmtpFilterSettings.filterSettings.section(
2852                             getFilterSectionSettings(env, settingsObj));
2853                     break;
2854                 case DemuxMmtpFilterType::AUDIO:
2855                 case DemuxMmtpFilterType::VIDEO:
2856                     mmtpFilterSettings.filterSettings.av(getFilterAvSettings(env, settingsObj));
2857                     break;
2858                 case DemuxMmtpFilterType::PES:
2859                     mmtpFilterSettings.filterSettings.pesData(
2860                             getFilterPesDataSettings(env, settingsObj));
2861                     break;
2862                 case DemuxMmtpFilterType::RECORD:
2863                     mmtpFilterSettings.filterSettings.record(
2864                             getFilterRecordSettings(env, settingsObj));
2865                     break;
2866                 case DemuxMmtpFilterType::DOWNLOAD:
2867                     mmtpFilterSettings.filterSettings.download(
2868                             getFilterDownloadSettings(env, settingsObj));
2869                     break;
2870                 default:
2871                     break;
2872             }
2873             filterSettings.mmtp(mmtpFilterSettings);
2874             break;
2875         }
2876         case DemuxFilterMainType::IP: {
2877             DemuxIpAddress ipAddr = getDemuxIpAddress(env, filterConfigObj);
2878 
2879             DemuxIpFilterSettings ipFilterSettings {
2880                 .ipAddr = ipAddr,
2881             };
2882             DemuxIpFilterType ipType = static_cast<DemuxIpFilterType>(subtype);
2883             switch (ipType) {
2884                 case DemuxIpFilterType::SECTION: {
2885                     ipFilterSettings.filterSettings.section(
2886                             getFilterSectionSettings(env, settingsObj));
2887                     break;
2888                 }
2889                 case DemuxIpFilterType::IP: {
2890                     jclass clazz = env->FindClass(
2891                             "android/media/tv/tuner/filter/IpFilterConfiguration");
2892                     bool bPassthrough = static_cast<bool>(
2893                             env->GetBooleanField(
2894                                     filterConfigObj, env->GetFieldID(
2895                                             clazz, "mPassthrough", "Z")));
2896                     ipFilterSettings.filterSettings.bPassthrough(bPassthrough);
2897                     break;
2898                 }
2899                 default: {
2900                     break;
2901                 }
2902             }
2903             filterSettings.ip(ipFilterSettings);
2904             break;
2905         }
2906         case DemuxFilterMainType::TLV: {
2907             jclass clazz = env->FindClass("android/media/tv/tuner/filter/TlvFilterConfiguration");
2908             uint8_t packetType = static_cast<uint8_t>(
2909                     env->GetIntField(filterConfigObj, env->GetFieldID(clazz, "mPacketType", "I")));
2910             bool isCompressedIpPacket = static_cast<bool>(
2911                     env->GetBooleanField(
2912                             filterConfigObj, env->GetFieldID(clazz, "mIsCompressedIpPacket", "Z")));
2913 
2914             DemuxTlvFilterSettings tlvFilterSettings {
2915                 .packetType = packetType,
2916                 .isCompressedIpPacket = isCompressedIpPacket,
2917             };
2918             DemuxTlvFilterType tlvType = static_cast<DemuxTlvFilterType>(subtype);
2919             switch (tlvType) {
2920                 case DemuxTlvFilterType::SECTION: {
2921                     tlvFilterSettings.filterSettings.section(
2922                             getFilterSectionSettings(env, settingsObj));
2923                     break;
2924                 }
2925                 case DemuxTlvFilterType::TLV: {
2926                     bool bPassthrough = static_cast<bool>(
2927                             env->GetBooleanField(
2928                                     filterConfigObj, env->GetFieldID(
2929                                             clazz, "mPassthrough", "Z")));
2930                     tlvFilterSettings.filterSettings.bPassthrough(bPassthrough);
2931                     break;
2932                 }
2933                 default: {
2934                     break;
2935                 }
2936             }
2937             filterSettings.tlv(tlvFilterSettings);
2938             break;
2939         }
2940         case DemuxFilterMainType::ALP: {
2941             jclass clazz = env->FindClass("android/media/tv/tuner/filter/AlpFilterConfiguration");
2942             uint8_t packetType = static_cast<uint8_t>(
2943                     env->GetIntField(filterConfigObj, env->GetFieldID(clazz, "mPacketType", "I")));
2944             DemuxAlpLengthType lengthType = static_cast<DemuxAlpLengthType>(
2945                     env->GetIntField(filterConfigObj, env->GetFieldID(clazz, "mLengthType", "I")));
2946             DemuxAlpFilterSettings alpFilterSettings {
2947                 .packetType = packetType,
2948                 .lengthType = lengthType,
2949             };
2950             DemuxAlpFilterType alpType = static_cast<DemuxAlpFilterType>(subtype);
2951             switch (alpType) {
2952                 case DemuxAlpFilterType::SECTION:
2953                     alpFilterSettings.filterSettings.section(
2954                             getFilterSectionSettings(env, settingsObj));
2955                     break;
2956                 default:
2957                     break;
2958             }
2959             filterSettings.alp(alpFilterSettings);
2960             break;
2961         }
2962         default: {
2963             break;
2964         }
2965     }
2966     return filterSettings;
2967 }
2968 
copyData(JNIEnv * env,std::unique_ptr<MQ> & mq,EventFlag * flag,jbyteArray buffer,jlong offset,jlong size)2969 static jint copyData(JNIEnv *env, std::unique_ptr<MQ>& mq, EventFlag* flag, jbyteArray buffer,
2970         jlong offset, jlong size) {
2971     ALOGD("copyData, size=%ld, offset=%ld", (long) size, (long) offset);
2972 
2973     jlong available = mq->availableToRead();
2974     ALOGD("copyData, available=%ld", (long) available);
2975     size = std::min(size, available);
2976 
2977     jboolean isCopy;
2978     jbyte *dst = env->GetByteArrayElements(buffer, &isCopy);
2979     ALOGD("copyData, isCopy=%d", isCopy);
2980     if (dst == nullptr) {
2981         jniThrowRuntimeException(env, "Failed to GetByteArrayElements");
2982         return 0;
2983     }
2984 
2985     if (mq->read(reinterpret_cast<unsigned char*>(dst) + offset, size)) {
2986         env->ReleaseByteArrayElements(buffer, dst, 0);
2987         flag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
2988     } else {
2989         jniThrowRuntimeException(env, "Failed to read FMQ");
2990         env->ReleaseByteArrayElements(buffer, dst, 0);
2991         return 0;
2992     }
2993     return size;
2994 }
2995 
android_media_tv_Tuner_configure_filter(JNIEnv * env,jobject filter,int type,int subtype,jobject settings)2996 static jint android_media_tv_Tuner_configure_filter(
2997         JNIEnv *env, jobject filter, int type, int subtype, jobject settings) {
2998     ALOGD("configure filter type=%d, subtype=%d", type, subtype);
2999     sp<Filter> filterSp = getFilter(env, filter);
3000     sp<IFilter> iFilterSp = filterSp->getIFilter();
3001     if (iFilterSp == NULL) {
3002         ALOGD("Failed to configure filter: filter not found");
3003         return (jint) Result::NOT_INITIALIZED;
3004     }
3005     DemuxFilterSettings filterSettings = getFilterConfiguration(env, type, subtype, settings);
3006     Result res = iFilterSp->configure(filterSettings);
3007 
3008     if (res != Result::SUCCESS) {
3009         return (jint) res;
3010     }
3011 
3012     MQDescriptorSync<uint8_t> filterMQDesc;
3013     Result getQueueDescResult = Result::UNKNOWN_ERROR;
3014     if (filterSp->mFilterMQ == NULL) {
3015         iFilterSp->getQueueDesc(
3016                 [&](Result r, const MQDescriptorSync<uint8_t>& desc) {
3017                     filterMQDesc = desc;
3018                     getQueueDescResult = r;
3019                     ALOGD("getFilterQueueDesc");
3020                 });
3021         if (getQueueDescResult == Result::SUCCESS) {
3022             filterSp->mFilterMQ = std::make_unique<MQ>(filterMQDesc, true);
3023             EventFlag::createEventFlag(
3024                     filterSp->mFilterMQ->getEventFlagWord(), &(filterSp->mFilterMQEventFlag));
3025         }
3026     }
3027     return (jint) getQueueDescResult;
3028 }
3029 
android_media_tv_Tuner_get_filter_id(JNIEnv * env,jobject filter)3030 static jint android_media_tv_Tuner_get_filter_id(JNIEnv* env, jobject filter) {
3031     sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
3032     if (iFilterSp == NULL) {
3033         ALOGD("Failed to get filter ID: filter not found");
3034         return (int) Result::NOT_INITIALIZED;
3035     }
3036     Result res;
3037     uint32_t id;
3038     iFilterSp->getId(
3039             [&](Result r, uint32_t filterId) {
3040                 res = r;
3041                 id = filterId;
3042             });
3043     if (res != Result::SUCCESS) {
3044         return (jint) Constant::INVALID_FILTER_ID;
3045     }
3046     return (jint) id;
3047 }
3048 
android_media_tv_Tuner_set_filter_data_source(JNIEnv * env,jobject filter,jobject srcFilter)3049 static jint android_media_tv_Tuner_set_filter_data_source(
3050         JNIEnv* env, jobject filter, jobject srcFilter) {
3051     sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
3052     if (iFilterSp == NULL) {
3053         ALOGD("Failed to set filter data source: filter not found");
3054         return (jint) Result::NOT_INITIALIZED;
3055     }
3056     Result r;
3057     if (srcFilter == NULL) {
3058         r = iFilterSp->setDataSource(NULL);
3059     } else {
3060         sp<IFilter> srcSp = getFilter(env, srcFilter)->getIFilter();
3061         if (iFilterSp == NULL) {
3062             ALOGD("Failed to set filter data source: src filter not found");
3063             return (jint) Result::INVALID_ARGUMENT;
3064         }
3065         r = iFilterSp->setDataSource(srcSp);
3066     }
3067     return (jint) r;
3068 }
3069 
android_media_tv_Tuner_start_filter(JNIEnv * env,jobject filter)3070 static jint android_media_tv_Tuner_start_filter(JNIEnv *env, jobject filter) {
3071     sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
3072     if (iFilterSp == NULL) {
3073         ALOGD("Failed to start filter: filter not found");
3074         return (jint) Result::NOT_INITIALIZED;
3075     }
3076     Result r = iFilterSp->start();
3077     return (jint) r;
3078 }
3079 
android_media_tv_Tuner_stop_filter(JNIEnv * env,jobject filter)3080 static jint android_media_tv_Tuner_stop_filter(JNIEnv *env, jobject filter) {
3081     sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
3082     if (iFilterSp == NULL) {
3083         ALOGD("Failed to stop filter: filter not found");
3084         return (jint) Result::NOT_INITIALIZED;
3085     }
3086     Result r = iFilterSp->stop();
3087     return (jint) r;
3088 }
3089 
android_media_tv_Tuner_flush_filter(JNIEnv * env,jobject filter)3090 static jint android_media_tv_Tuner_flush_filter(JNIEnv *env, jobject filter) {
3091     sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
3092     if (iFilterSp == NULL) {
3093         ALOGD("Failed to flush filter: filter not found");
3094         return (jint) Result::NOT_INITIALIZED;
3095     }
3096     Result r = iFilterSp->flush();
3097     return (jint) r;
3098 }
3099 
android_media_tv_Tuner_read_filter_fmq(JNIEnv * env,jobject filter,jbyteArray buffer,jlong offset,jlong size)3100 static jint android_media_tv_Tuner_read_filter_fmq(
3101         JNIEnv *env, jobject filter, jbyteArray buffer, jlong offset, jlong size) {
3102     sp<Filter> filterSp = getFilter(env, filter);
3103     if (filterSp == NULL) {
3104         jniThrowException(env, "java/lang/IllegalStateException",
3105                 "Failed to read filter FMQ: filter not found");
3106         return 0;
3107     }
3108     return copyData(env, filterSp->mFilterMQ, filterSp->mFilterMQEventFlag, buffer, offset, size);
3109 }
3110 
android_media_tv_Tuner_close_filter(JNIEnv * env,jobject filter)3111 static jint android_media_tv_Tuner_close_filter(JNIEnv *env, jobject filter) {
3112     sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
3113     if (iFilterSp == NULL) {
3114         ALOGD("Failed to close filter: filter not found");
3115         return (jint) Result::NOT_INITIALIZED;
3116     }
3117     Result r = iFilterSp->close();
3118     return (jint) r;
3119 }
3120 
getTimeFilter(JNIEnv * env,jobject filter)3121 static sp<TimeFilter> getTimeFilter(JNIEnv *env, jobject filter) {
3122     return (TimeFilter *)env->GetLongField(filter, gFields.timeFilterContext);
3123 }
3124 
android_media_tv_Tuner_time_filter_set_timestamp(JNIEnv * env,jobject filter,jlong timestamp)3125 static int android_media_tv_Tuner_time_filter_set_timestamp(
3126         JNIEnv *env, jobject filter, jlong timestamp) {
3127     sp<TimeFilter> filterSp = getTimeFilter(env, filter);
3128     if (filterSp == NULL) {
3129         ALOGD("Failed set timestamp: time filter not found");
3130         return (int) Result::INVALID_STATE;
3131     }
3132     sp<ITimeFilter> iFilterSp = filterSp->getITimeFilter();
3133     Result r = iFilterSp->setTimeStamp(static_cast<uint64_t>(timestamp));
3134     return (int) r;
3135 }
3136 
android_media_tv_Tuner_time_filter_clear_timestamp(JNIEnv * env,jobject filter)3137 static int android_media_tv_Tuner_time_filter_clear_timestamp(JNIEnv *env, jobject filter) {
3138     sp<TimeFilter> filterSp = getTimeFilter(env, filter);
3139     if (filterSp == NULL) {
3140         ALOGD("Failed clear timestamp: time filter not found");
3141         return (int) Result::INVALID_STATE;
3142     }
3143     sp<ITimeFilter> iFilterSp = filterSp->getITimeFilter();
3144     Result r = iFilterSp->clearTimeStamp();
3145     return (int) r;
3146 }
3147 
android_media_tv_Tuner_time_filter_get_timestamp(JNIEnv * env,jobject filter)3148 static jobject android_media_tv_Tuner_time_filter_get_timestamp(JNIEnv *env, jobject filter) {
3149     sp<TimeFilter> filterSp = getTimeFilter(env, filter);
3150     if (filterSp == NULL) {
3151         ALOGD("Failed get timestamp: time filter not found");
3152         return NULL;
3153     }
3154 
3155     sp<ITimeFilter> iFilterSp = filterSp->getITimeFilter();
3156     Result res;
3157     uint64_t timestamp;
3158     iFilterSp->getTimeStamp(
3159             [&](Result r, uint64_t t) {
3160                 res = r;
3161                 timestamp = t;
3162             });
3163     if (res != Result::SUCCESS) {
3164         return NULL;
3165     }
3166 
3167     jclass longClazz = env->FindClass("java/lang/Long");
3168     jmethodID longInit = env->GetMethodID(longClazz, "<init>", "(J)V");
3169 
3170     jobject longObj = env->NewObject(longClazz, longInit, static_cast<jlong>(timestamp));
3171     return longObj;
3172 }
3173 
android_media_tv_Tuner_time_filter_get_source_time(JNIEnv * env,jobject filter)3174 static jobject android_media_tv_Tuner_time_filter_get_source_time(JNIEnv *env, jobject filter) {
3175     sp<TimeFilter> filterSp = getTimeFilter(env, filter);
3176     if (filterSp == NULL) {
3177         ALOGD("Failed get source time: time filter not found");
3178         return NULL;
3179     }
3180 
3181     sp<ITimeFilter> iFilterSp = filterSp->getITimeFilter();
3182     Result res;
3183     uint64_t timestamp;
3184     iFilterSp->getSourceTime(
3185             [&](Result r, uint64_t t) {
3186                 res = r;
3187                 timestamp = t;
3188             });
3189     if (res != Result::SUCCESS) {
3190         return NULL;
3191     }
3192 
3193     jclass longClazz = env->FindClass("java/lang/Long");
3194     jmethodID longInit = env->GetMethodID(longClazz, "<init>", "(J)V");
3195 
3196     jobject longObj = env->NewObject(longClazz, longInit, static_cast<jlong>(timestamp));
3197     return longObj;
3198 }
3199 
android_media_tv_Tuner_time_filter_close(JNIEnv * env,jobject filter)3200 static int android_media_tv_Tuner_time_filter_close(JNIEnv *env, jobject filter) {
3201     sp<TimeFilter> filterSp = getTimeFilter(env, filter);
3202     if (filterSp == NULL) {
3203         ALOGD("Failed close time filter: time filter not found");
3204         return (int) Result::INVALID_STATE;
3205     }
3206 
3207     Result r = filterSp->getITimeFilter()->close();
3208     if (r == Result::SUCCESS) {
3209         filterSp->decStrong(filter);
3210         env->SetLongField(filter, gFields.timeFilterContext, 0);
3211     }
3212     return (int) r;
3213 }
3214 
android_media_tv_Tuner_open_descrambler(JNIEnv * env,jobject thiz,jint)3215 static jobject android_media_tv_Tuner_open_descrambler(JNIEnv *env, jobject thiz, jint) {
3216     sp<JTuner> tuner = getTuner(env, thiz);
3217     return tuner->openDescrambler();
3218 }
3219 
android_media_tv_Tuner_descrambler_add_pid(JNIEnv * env,jobject descrambler,jint pidType,jint pid,jobject filter)3220 static jint android_media_tv_Tuner_descrambler_add_pid(
3221         JNIEnv *env, jobject descrambler, jint pidType, jint pid, jobject filter) {
3222     sp<IDescrambler> descramblerSp = getDescrambler(env, descrambler);
3223     if (descramblerSp == NULL) {
3224         return (jint) Result::NOT_INITIALIZED;
3225     }
3226     sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
3227     Result result = descramblerSp->addPid(getDemuxPid((int)pidType, (int)pid), iFilterSp);
3228     return (jint) result;
3229 }
3230 
android_media_tv_Tuner_descrambler_remove_pid(JNIEnv * env,jobject descrambler,jint pidType,jint pid,jobject filter)3231 static jint android_media_tv_Tuner_descrambler_remove_pid(
3232         JNIEnv *env, jobject descrambler, jint pidType, jint pid, jobject filter) {
3233     sp<IDescrambler> descramblerSp = getDescrambler(env, descrambler);
3234     if (descramblerSp == NULL) {
3235         return (jint) Result::NOT_INITIALIZED;
3236     }
3237     sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
3238     Result result = descramblerSp->removePid(getDemuxPid((int)pidType, (int)pid), iFilterSp);
3239     return (jint) result;
3240 }
3241 
android_media_tv_Tuner_descrambler_set_key_token(JNIEnv * env,jobject descrambler,jbyteArray keyToken)3242 static jint android_media_tv_Tuner_descrambler_set_key_token(
3243         JNIEnv* env, jobject descrambler, jbyteArray keyToken) {
3244     sp<IDescrambler> descramblerSp = getDescrambler(env, descrambler);
3245     if (descramblerSp == NULL) {
3246         return (jint) Result::NOT_INITIALIZED;
3247     }
3248     int size = env->GetArrayLength(keyToken);
3249     std::vector<uint8_t> v(size);
3250     env->GetByteArrayRegion(keyToken, 0, size, reinterpret_cast<jbyte*>(&v[0]));
3251     Result result = descramblerSp->setKeyToken(v);
3252     return (jint) result;
3253 }
3254 
android_media_tv_Tuner_close_descrambler(JNIEnv * env,jobject descrambler)3255 static jint android_media_tv_Tuner_close_descrambler(JNIEnv* env, jobject descrambler) {
3256     sp<IDescrambler> descramblerSp = getDescrambler(env, descrambler);
3257     if (descramblerSp == NULL) {
3258         return (jint) Result::NOT_INITIALIZED;
3259     }
3260     Result r = descramblerSp->close();
3261     if (r == Result::SUCCESS) {
3262         descramblerSp->decStrong(descrambler);
3263     }
3264     return (jint) r;
3265 }
3266 
android_media_tv_Tuner_open_dvr_recorder(JNIEnv * env,jobject thiz,jlong bufferSize)3267 static jobject android_media_tv_Tuner_open_dvr_recorder(
3268         JNIEnv* env, jobject thiz, jlong bufferSize) {
3269     sp<JTuner> tuner = getTuner(env, thiz);
3270     return tuner->openDvr(DvrType::RECORD, bufferSize);
3271 }
3272 
android_media_tv_Tuner_open_dvr_playback(JNIEnv * env,jobject thiz,jlong bufferSize)3273 static jobject android_media_tv_Tuner_open_dvr_playback(
3274         JNIEnv* env, jobject thiz, jlong bufferSize) {
3275     sp<JTuner> tuner = getTuner(env, thiz);
3276     return tuner->openDvr(DvrType::PLAYBACK, bufferSize);
3277 }
3278 
android_media_tv_Tuner_get_demux_caps(JNIEnv * env,jobject thiz)3279 static jobject android_media_tv_Tuner_get_demux_caps(JNIEnv* env, jobject thiz) {
3280     sp<JTuner> tuner = getTuner(env, thiz);
3281     return tuner->getDemuxCaps();
3282 }
3283 
android_media_tv_Tuner_open_demux(JNIEnv * env,jobject thiz,jint)3284 static jint android_media_tv_Tuner_open_demux(JNIEnv* env, jobject thiz, jint /* handle */) {
3285     sp<JTuner> tuner = getTuner(env, thiz);
3286     return (jint) tuner->openDemux();
3287 }
3288 
android_media_tv_Tuner_close_tuner(JNIEnv * env,jobject thiz)3289 static jint android_media_tv_Tuner_close_tuner(JNIEnv* env, jobject thiz) {
3290     sp<JTuner> tuner = getTuner(env, thiz);
3291     return (jint) tuner->close();
3292 }
3293 
android_media_tv_Tuner_close_demux(JNIEnv * env,jobject thiz,jint)3294 static jint android_media_tv_Tuner_close_demux(JNIEnv* env, jobject thiz, jint /* handle */) {
3295     sp<JTuner> tuner = getTuner(env, thiz);
3296     return tuner->closeDemux();
3297 }
3298 
android_media_tv_Tuner_close_frontend(JNIEnv * env,jobject thiz,jint)3299 static jint android_media_tv_Tuner_close_frontend(JNIEnv* env, jobject thiz, jint /* handle */) {
3300     sp<JTuner> tuner = getTuner(env, thiz);
3301     return tuner->closeFrontend();
3302 }
3303 
android_media_tv_Tuner_attach_filter(JNIEnv * env,jobject dvr,jobject filter)3304 static jint android_media_tv_Tuner_attach_filter(JNIEnv *env, jobject dvr, jobject filter) {
3305     sp<Dvr> dvrSp = getDvr(env, dvr);
3306     if (dvrSp == NULL) {
3307         return (jint) Result::NOT_INITIALIZED;
3308     }
3309     sp<Filter> filterSp = getFilter(env, filter);
3310     if (filterSp == NULL) {
3311         return (jint) Result::INVALID_ARGUMENT;
3312     }
3313     sp<IDvr> iDvrSp = dvrSp->getIDvr();
3314     sp<IFilter> iFilterSp = filterSp->getIFilter();
3315     Result result = iDvrSp->attachFilter(iFilterSp);
3316     return (jint) result;
3317 }
3318 
android_media_tv_Tuner_detach_filter(JNIEnv * env,jobject dvr,jobject filter)3319 static jint android_media_tv_Tuner_detach_filter(JNIEnv *env, jobject dvr, jobject filter) {
3320     sp<Dvr> dvrSp = getDvr(env, dvr);
3321     if (dvrSp == NULL) {
3322         return (jint) Result::NOT_INITIALIZED;
3323     }
3324     sp<Filter> filterSp = getFilter(env, filter);
3325     if (filterSp == NULL) {
3326         return (jint) Result::INVALID_ARGUMENT;
3327     }
3328     sp<IDvr> iDvrSp = dvrSp->getIDvr();
3329     sp<IFilter> iFilterSp = filterSp->getIFilter();
3330     Result result = iDvrSp->detachFilter(iFilterSp);
3331     return (jint) result;
3332 }
3333 
android_media_tv_Tuner_configure_dvr(JNIEnv * env,jobject dvr,jobject settings)3334 static jint android_media_tv_Tuner_configure_dvr(JNIEnv *env, jobject dvr, jobject settings) {
3335     sp<Dvr> dvrSp = getDvr(env, dvr);
3336     if (dvrSp == NULL) {
3337         ALOGD("Failed to configure dvr: dvr not found");
3338         return (int)Result::NOT_INITIALIZED;
3339     }
3340     sp<IDvr> iDvrSp = dvrSp->getIDvr();
3341     bool isRecorder =
3342             env->IsInstanceOf(dvr, env->FindClass("android/media/tv/tuner/dvr/DvrRecorder"));
3343     Result result = iDvrSp->configure(getDvrSettings(env, settings, isRecorder));
3344     if (result != Result::SUCCESS) {
3345         return (jint) result;
3346     }
3347     MQDescriptorSync<uint8_t> dvrMQDesc;
3348     Result getQueueDescResult = Result::UNKNOWN_ERROR;
3349     iDvrSp->getQueueDesc(
3350             [&](Result r, const MQDescriptorSync<uint8_t>& desc) {
3351                 dvrMQDesc = desc;
3352                 getQueueDescResult = r;
3353                 ALOGD("getDvrQueueDesc");
3354             });
3355     if (getQueueDescResult == Result::SUCCESS) {
3356         dvrSp->mDvrMQ = std::make_unique<MQ>(dvrMQDesc, true);
3357         EventFlag::createEventFlag(
3358                 dvrSp->mDvrMQ->getEventFlagWord(), &(dvrSp->mDvrMQEventFlag));
3359     }
3360     return (jint) getQueueDescResult;
3361 }
3362 
android_media_tv_Tuner_start_dvr(JNIEnv * env,jobject dvr)3363 static jint android_media_tv_Tuner_start_dvr(JNIEnv *env, jobject dvr) {
3364     sp<Dvr> dvrSp = getDvr(env, dvr);
3365     if (dvrSp == NULL) {
3366         ALOGD("Failed to start dvr: dvr not found");
3367         return (jint) Result::NOT_INITIALIZED;
3368     }
3369     sp<IDvr> iDvrSp = dvrSp->getIDvr();
3370     Result result = iDvrSp->start();
3371     return (jint) result;
3372 }
3373 
android_media_tv_Tuner_stop_dvr(JNIEnv * env,jobject dvr)3374 static jint android_media_tv_Tuner_stop_dvr(JNIEnv *env, jobject dvr) {
3375     sp<Dvr> dvrSp = getDvr(env, dvr);
3376     if (dvrSp == NULL) {
3377         ALOGD("Failed to stop dvr: dvr not found");
3378         return (jint) Result::NOT_INITIALIZED;
3379     }
3380     sp<IDvr> iDvrSp = dvrSp->getIDvr();
3381     Result result = iDvrSp->stop();
3382     return (jint) result;
3383 }
3384 
android_media_tv_Tuner_flush_dvr(JNIEnv * env,jobject dvr)3385 static jint android_media_tv_Tuner_flush_dvr(JNIEnv *env, jobject dvr) {
3386     sp<Dvr> dvrSp = getDvr(env, dvr);
3387     if (dvrSp == NULL) {
3388         ALOGD("Failed to flush dvr: dvr not found");
3389         return (jint) Result::NOT_INITIALIZED;
3390     }
3391     sp<IDvr> iDvrSp = dvrSp->getIDvr();
3392     Result result = iDvrSp->flush();
3393     return (jint) result;
3394 }
3395 
android_media_tv_Tuner_close_dvr(JNIEnv * env,jobject dvr)3396 static jint android_media_tv_Tuner_close_dvr(JNIEnv* env, jobject dvr) {
3397     sp<Dvr> dvrSp = getDvr(env, dvr);
3398     if (dvrSp == NULL) {
3399         ALOGD("Failed to close dvr: dvr not found");
3400         return (jint) Result::NOT_INITIALIZED;
3401     }
3402     return dvrSp->close();
3403 }
3404 
getLnb(JNIEnv * env,jobject lnb)3405 static sp<Lnb> getLnb(JNIEnv *env, jobject lnb) {
3406     return (Lnb *)env->GetLongField(lnb, gFields.lnbContext);
3407 }
3408 
android_media_tv_Tuner_lnb_set_voltage(JNIEnv * env,jobject lnb,jint voltage)3409 static jint android_media_tv_Tuner_lnb_set_voltage(JNIEnv* env, jobject lnb, jint voltage) {
3410     sp<ILnb> iLnbSp = getLnb(env, lnb)->getILnb();
3411     Result r = iLnbSp->setVoltage(static_cast<LnbVoltage>(voltage));
3412     return (jint) r;
3413 }
3414 
android_media_tv_Tuner_lnb_set_tone(JNIEnv * env,jobject lnb,jint tone)3415 static int android_media_tv_Tuner_lnb_set_tone(JNIEnv* env, jobject lnb, jint tone) {
3416     sp<ILnb> iLnbSp = getLnb(env, lnb)->getILnb();
3417     Result r = iLnbSp->setTone(static_cast<LnbTone>(tone));
3418     return (jint) r;
3419 }
3420 
android_media_tv_Tuner_lnb_set_position(JNIEnv * env,jobject lnb,jint position)3421 static int android_media_tv_Tuner_lnb_set_position(JNIEnv* env, jobject lnb, jint position) {
3422     sp<ILnb> iLnbSp = getLnb(env, lnb)->getILnb();
3423     Result r = iLnbSp->setSatellitePosition(static_cast<LnbPosition>(position));
3424     return (jint) r;
3425 }
3426 
android_media_tv_Tuner_lnb_send_diseqc_msg(JNIEnv * env,jobject lnb,jbyteArray msg)3427 static int android_media_tv_Tuner_lnb_send_diseqc_msg(JNIEnv* env, jobject lnb, jbyteArray msg) {
3428     sp<ILnb> iLnbSp = getLnb(env, lnb)->getILnb();
3429     int size = env->GetArrayLength(msg);
3430     std::vector<uint8_t> v(size);
3431     env->GetByteArrayRegion(msg, 0, size, reinterpret_cast<jbyte*>(&v[0]));
3432     Result r = iLnbSp->sendDiseqcMessage(v);
3433     return (jint) r;
3434 }
3435 
android_media_tv_Tuner_close_lnb(JNIEnv * env,jobject lnb)3436 static int android_media_tv_Tuner_close_lnb(JNIEnv* env, jobject lnb) {
3437     sp<Lnb> lnbSp = getLnb(env, lnb);
3438     Result r = lnbSp->getILnb()->close();
3439     if (r == Result::SUCCESS) {
3440         lnbSp->decStrong(lnb);
3441         env->SetLongField(lnb, gFields.lnbContext, 0);
3442     }
3443     return (jint) r;
3444 }
3445 
android_media_tv_Tuner_dvr_set_fd(JNIEnv * env,jobject dvr,jint fd)3446 static void android_media_tv_Tuner_dvr_set_fd(JNIEnv *env, jobject dvr, jint fd) {
3447     sp<Dvr> dvrSp = getDvr(env, dvr);
3448     if (dvrSp == NULL) {
3449         ALOGD("Failed to set FD for dvr: dvr not found");
3450     }
3451     dvrSp->mFd = (int) fd;
3452     ALOGD("set fd = %d", dvrSp->mFd);
3453 }
3454 
android_media_tv_Tuner_read_dvr(JNIEnv * env,jobject dvr,jlong size)3455 static jlong android_media_tv_Tuner_read_dvr(JNIEnv *env, jobject dvr, jlong size) {
3456     sp<Dvr> dvrSp = getDvr(env, dvr);
3457     if (dvrSp == NULL) {
3458         jniThrowException(env, "java/lang/IllegalStateException",
3459                 "Failed to read dvr: dvr not found");
3460         return 0;
3461     }
3462 
3463     long available = dvrSp->mDvrMQ->availableToWrite();
3464     long write = std::min((long) size, available);
3465 
3466     MQ::MemTransaction tx;
3467     long ret = 0;
3468     if (dvrSp->mDvrMQ->beginWrite(write, &tx)) {
3469         auto first = tx.getFirstRegion();
3470         auto data = first.getAddress();
3471         long length = first.getLength();
3472         long firstToWrite = std::min(length, write);
3473         ret = read(dvrSp->mFd, data, firstToWrite);
3474 
3475         if (ret < 0) {
3476             ALOGE("[DVR] Failed to read from FD: %s", strerror(errno));
3477             jniThrowRuntimeException(env, strerror(errno));
3478             return 0;
3479         }
3480         if (ret < firstToWrite) {
3481             ALOGW("[DVR] file to MQ, first region: %ld bytes to write, but %ld bytes written",
3482                     firstToWrite, ret);
3483         } else if (firstToWrite < write) {
3484             ALOGD("[DVR] write second region: %ld bytes written, %ld bytes in total", ret, write);
3485             auto second = tx.getSecondRegion();
3486             data = second.getAddress();
3487             length = second.getLength();
3488             int secondToWrite = std::min(length, write - firstToWrite);
3489             ret += read(dvrSp->mFd, data, secondToWrite);
3490         }
3491         ALOGD("[DVR] file to MQ: %ld bytes need to be written, %ld bytes written", write, ret);
3492         if (!dvrSp->mDvrMQ->commitWrite(ret)) {
3493             ALOGE("[DVR] Error: failed to commit write!");
3494             return 0;
3495         }
3496 
3497     } else {
3498         ALOGE("dvrMq.beginWrite failed");
3499     }
3500     return (jlong) ret;
3501 }
3502 
android_media_tv_Tuner_read_dvr_from_array(JNIEnv * env,jobject dvr,jbyteArray buffer,jlong offset,jlong size)3503 static jlong android_media_tv_Tuner_read_dvr_from_array(
3504         JNIEnv* env, jobject dvr, jbyteArray buffer, jlong offset, jlong size) {
3505     sp<Dvr> dvrSp = getDvr(env, dvr);
3506     if (dvrSp == NULL) {
3507         ALOGW("Failed to read dvr: dvr not found");
3508         return 0;
3509     }
3510     if (dvrSp->mDvrMQ == NULL) {
3511         ALOGW("Failed to read dvr: dvr not configured");
3512         return 0;
3513     }
3514 
3515     jlong available = dvrSp->mDvrMQ->availableToWrite();
3516     size = std::min(size, available);
3517 
3518     jboolean isCopy;
3519     jbyte *src = env->GetByteArrayElements(buffer, &isCopy);
3520     if (src == nullptr) {
3521         ALOGD("Failed to GetByteArrayElements");
3522         return 0;
3523     }
3524 
3525     if (dvrSp->mDvrMQ->write(reinterpret_cast<unsigned char*>(src) + offset, size)) {
3526         env->ReleaseByteArrayElements(buffer, src, 0);
3527         dvrSp->mDvrMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
3528     } else {
3529         ALOGD("Failed to write FMQ");
3530         env->ReleaseByteArrayElements(buffer, src, 0);
3531         return 0;
3532     }
3533     return size;
3534 }
3535 
android_media_tv_Tuner_write_dvr(JNIEnv * env,jobject dvr,jlong size)3536 static jlong android_media_tv_Tuner_write_dvr(JNIEnv *env, jobject dvr, jlong size) {
3537     sp<Dvr> dvrSp = getDvr(env, dvr);
3538     if (dvrSp == NULL) {
3539         jniThrowException(env, "java/lang/IllegalStateException",
3540                 "Failed to write dvr: dvr not found");
3541         return 0;
3542     }
3543 
3544     if (dvrSp->mDvrMQ == NULL) {
3545         jniThrowException(env, "java/lang/IllegalStateException",
3546                 "Failed to write dvr: dvr not configured");
3547         return 0;
3548     }
3549 
3550     MQ& dvrMq = dvrSp->getDvrMQ();
3551 
3552     long available = dvrMq.availableToRead();
3553     long toRead = std::min((long) size, available);
3554 
3555     long ret = 0;
3556     MQ::MemTransaction tx;
3557     if (dvrMq.beginRead(toRead, &tx)) {
3558         auto first = tx.getFirstRegion();
3559         auto data = first.getAddress();
3560         long length = first.getLength();
3561         long firstToRead = std::min(length, toRead);
3562         ret = write(dvrSp->mFd, data, firstToRead);
3563 
3564         if (ret < 0) {
3565             ALOGE("[DVR] Failed to write to FD: %s", strerror(errno));
3566             jniThrowRuntimeException(env, strerror(errno));
3567             return 0;
3568         }
3569         if (ret < firstToRead) {
3570             ALOGW("[DVR] MQ to file: %ld bytes read, but %ld bytes written", firstToRead, ret);
3571         } else if (firstToRead < toRead) {
3572             ALOGD("[DVR] read second region: %ld bytes read, %ld bytes in total", ret, toRead);
3573             auto second = tx.getSecondRegion();
3574             data = second.getAddress();
3575             length = second.getLength();
3576             int secondToRead = toRead - firstToRead;
3577             ret += write(dvrSp->mFd, data, secondToRead);
3578         }
3579         ALOGD("[DVR] MQ to file: %ld bytes to be read, %ld bytes written", toRead, ret);
3580         if (!dvrMq.commitRead(ret)) {
3581             ALOGE("[DVR] Error: failed to commit read!");
3582             return 0;
3583         }
3584 
3585     } else {
3586         ALOGE("dvrMq.beginRead failed");
3587     }
3588 
3589     return (jlong) ret;
3590 }
3591 
android_media_tv_Tuner_write_dvr_to_array(JNIEnv * env,jobject dvr,jbyteArray buffer,jlong offset,jlong size)3592 static jlong android_media_tv_Tuner_write_dvr_to_array(
3593         JNIEnv *env, jobject dvr, jbyteArray buffer, jlong offset, jlong size) {
3594     sp<Dvr> dvrSp = getDvr(env, dvr);
3595     if (dvrSp == NULL) {
3596         ALOGW("Failed to write dvr: dvr not found");
3597         return 0;
3598     }
3599     if (dvrSp->mDvrMQ == NULL) {
3600         ALOGW("Failed to write dvr: dvr not configured");
3601         return 0;
3602     }
3603     return copyData(env, dvrSp->mDvrMQ, dvrSp->mDvrMQEventFlag, buffer, offset, size);
3604 }
3605 
getMediaEventSp(JNIEnv * env,jobject mediaEventObj)3606 static sp<MediaEvent> getMediaEventSp(JNIEnv *env, jobject mediaEventObj) {
3607     return (MediaEvent *)env->GetLongField(mediaEventObj, gFields.mediaEventContext);
3608 }
3609 
android_media_tv_Tuner_media_event_get_linear_block(JNIEnv * env,jobject mediaEventObj)3610 static jobject android_media_tv_Tuner_media_event_get_linear_block(
3611         JNIEnv* env, jobject mediaEventObj) {
3612     sp<MediaEvent> mediaEventSp = getMediaEventSp(env, mediaEventObj);
3613     if (mediaEventSp == NULL) {
3614         ALOGD("Failed get MediaEvent");
3615         return NULL;
3616     }
3617 
3618     return mediaEventSp->getLinearBlock();
3619 }
3620 
android_media_tv_Tuner_media_event_get_audio_handle(JNIEnv * env,jobject mediaEventObj)3621 static jobject android_media_tv_Tuner_media_event_get_audio_handle(
3622         JNIEnv* env, jobject mediaEventObj) {
3623     sp<MediaEvent> mediaEventSp = getMediaEventSp(env, mediaEventObj);
3624     if (mediaEventSp == NULL) {
3625         ALOGD("Failed get MediaEvent");
3626         return NULL;
3627     }
3628 
3629     android::Mutex::Autolock autoLock(mediaEventSp->mLock);
3630     uint64_t audioHandle = mediaEventSp->getAudioHandle();
3631     jclass longClazz = env->FindClass("java/lang/Long");
3632     jmethodID longInit = env->GetMethodID(longClazz, "<init>", "(J)V");
3633 
3634     jobject longObj = env->NewObject(longClazz, longInit, static_cast<jlong>(audioHandle));
3635     return longObj;
3636 }
3637 
android_media_tv_Tuner_media_event_finalize(JNIEnv * env,jobject mediaEventObj)3638 static void android_media_tv_Tuner_media_event_finalize(JNIEnv* env, jobject mediaEventObj) {
3639     sp<MediaEvent> mediaEventSp = getMediaEventSp(env, mediaEventObj);
3640     if (mediaEventSp == NULL) {
3641         ALOGD("Failed get MediaEvent");
3642         return;
3643     }
3644 
3645     android::Mutex::Autolock autoLock(mediaEventSp->mLock);
3646     mediaEventSp->mAvHandleRefCnt--;
3647     mediaEventSp->finalize();
3648 
3649     mediaEventSp->decStrong(mediaEventObj);
3650 }
3651 
3652 static const JNINativeMethod gTunerMethods[] = {
3653     { "nativeInit", "()V", (void *)android_media_tv_Tuner_native_init },
3654     { "nativeSetup", "()V", (void *)android_media_tv_Tuner_native_setup },
3655     { "nativeGetFrontendIds", "()Ljava/util/List;",
3656             (void *)android_media_tv_Tuner_get_frontend_ids },
3657     { "nativeOpenFrontendByHandle", "(I)Landroid/media/tv/tuner/Tuner$Frontend;",
3658             (void *)android_media_tv_Tuner_open_frontend_by_handle },
3659     { "nativeCloseFrontendByHandle", "(I)I",
3660             (void *)android_media_tv_Tuner_close_frontend_by_handle },
3661     { "nativeTune", "(ILandroid/media/tv/tuner/frontend/FrontendSettings;)I",
3662             (void *)android_media_tv_Tuner_tune },
3663     { "nativeStopTune", "()I", (void *)android_media_tv_Tuner_stop_tune },
3664     { "nativeScan", "(ILandroid/media/tv/tuner/frontend/FrontendSettings;I)I",
3665             (void *)android_media_tv_Tuner_scan },
3666     { "nativeStopScan", "()I", (void *)android_media_tv_Tuner_stop_scan },
3667     { "nativeSetLnb", "(I)I", (void *)android_media_tv_Tuner_set_lnb },
3668     { "nativeSetLna", "(Z)I", (void *)android_media_tv_Tuner_set_lna },
3669     { "nativeGetFrontendStatus", "([I)Landroid/media/tv/tuner/frontend/FrontendStatus;",
3670             (void *)android_media_tv_Tuner_get_frontend_status },
3671     { "nativeGetAvSyncHwId", "(Landroid/media/tv/tuner/filter/Filter;)Ljava/lang/Integer;",
3672             (void *)android_media_tv_Tuner_get_av_sync_hw_id },
3673     { "nativeGetAvSyncTime", "(I)Ljava/lang/Long;",
3674             (void *)android_media_tv_Tuner_get_av_sync_time },
3675     { "nativeConnectCiCam", "(I)I", (void *)android_media_tv_Tuner_connect_cicam },
3676     { "nativeDisconnectCiCam", "()I", (void *)android_media_tv_Tuner_disconnect_cicam },
3677     { "nativeGetFrontendInfo", "(I)Landroid/media/tv/tuner/frontend/FrontendInfo;",
3678             (void *)android_media_tv_Tuner_get_frontend_info },
3679     { "nativeOpenFilter", "(IIJ)Landroid/media/tv/tuner/filter/Filter;",
3680             (void *)android_media_tv_Tuner_open_filter },
3681     { "nativeOpenTimeFilter", "()Landroid/media/tv/tuner/filter/TimeFilter;",
3682             (void *)android_media_tv_Tuner_open_time_filter },
3683     { "nativeGetLnbIds", "()[I", (void *)android_media_tv_Tuner_get_lnb_ids },
3684     { "nativeOpenLnbByHandle", "(I)Landroid/media/tv/tuner/Lnb;",
3685             (void *)android_media_tv_Tuner_open_lnb_by_handle },
3686     { "nativeOpenLnbByName", "(Ljava/lang/String;)Landroid/media/tv/tuner/Lnb;",
3687             (void *)android_media_tv_Tuner_open_lnb_by_name },
3688     { "nativeOpenDescramblerByHandle", "(I)Landroid/media/tv/tuner/Descrambler;",
3689             (void *)android_media_tv_Tuner_open_descrambler },
3690     { "nativeOpenDvrRecorder", "(J)Landroid/media/tv/tuner/dvr/DvrRecorder;",
3691             (void *)android_media_tv_Tuner_open_dvr_recorder },
3692     { "nativeOpenDvrPlayback", "(J)Landroid/media/tv/tuner/dvr/DvrPlayback;",
3693             (void *)android_media_tv_Tuner_open_dvr_playback },
3694     { "nativeGetDemuxCapabilities", "()Landroid/media/tv/tuner/DemuxCapabilities;",
3695             (void *)android_media_tv_Tuner_get_demux_caps },
3696     { "nativeOpenDemuxByhandle", "(I)I", (void *)android_media_tv_Tuner_open_demux },
3697     { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_tuner },
3698     { "nativeCloseFrontend", "(I)I", (void *)android_media_tv_Tuner_close_frontend },
3699     { "nativeCloseDemux", "(I)I", (void *)android_media_tv_Tuner_close_demux },
3700 };
3701 
3702 static const JNINativeMethod gFilterMethods[] = {
3703     { "nativeConfigureFilter", "(IILandroid/media/tv/tuner/filter/FilterConfiguration;)I",
3704             (void *)android_media_tv_Tuner_configure_filter },
3705     { "nativeGetId", "()I", (void *)android_media_tv_Tuner_get_filter_id },
3706     { "nativeSetDataSource", "(Landroid/media/tv/tuner/filter/Filter;)I",
3707             (void *)android_media_tv_Tuner_set_filter_data_source },
3708     { "nativeStartFilter", "()I", (void *)android_media_tv_Tuner_start_filter },
3709     { "nativeStopFilter", "()I", (void *)android_media_tv_Tuner_stop_filter },
3710     { "nativeFlushFilter", "()I", (void *)android_media_tv_Tuner_flush_filter },
3711     { "nativeRead", "([BJJ)I", (void *)android_media_tv_Tuner_read_filter_fmq },
3712     { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_filter },
3713 };
3714 
3715 static const JNINativeMethod gTimeFilterMethods[] = {
3716     { "nativeSetTimestamp", "(J)I", (void *)android_media_tv_Tuner_time_filter_set_timestamp },
3717     { "nativeClearTimestamp", "()I", (void *)android_media_tv_Tuner_time_filter_clear_timestamp },
3718     { "nativeGetTimestamp", "()Ljava/lang/Long;",
3719             (void *)android_media_tv_Tuner_time_filter_get_timestamp },
3720     { "nativeGetSourceTime", "()Ljava/lang/Long;",
3721             (void *)android_media_tv_Tuner_time_filter_get_source_time },
3722     { "nativeClose", "()I", (void *)android_media_tv_Tuner_time_filter_close },
3723 };
3724 
3725 static const JNINativeMethod gDescramblerMethods[] = {
3726     { "nativeAddPid", "(IILandroid/media/tv/tuner/filter/Filter;)I",
3727             (void *)android_media_tv_Tuner_descrambler_add_pid },
3728     { "nativeRemovePid", "(IILandroid/media/tv/tuner/filter/Filter;)I",
3729             (void *)android_media_tv_Tuner_descrambler_remove_pid },
3730     { "nativeSetKeyToken", "([B)I", (void *)android_media_tv_Tuner_descrambler_set_key_token },
3731     { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_descrambler },
3732 };
3733 
3734 static const JNINativeMethod gDvrRecorderMethods[] = {
3735     { "nativeAttachFilter", "(Landroid/media/tv/tuner/filter/Filter;)I",
3736             (void *)android_media_tv_Tuner_attach_filter },
3737     { "nativeDetachFilter", "(Landroid/media/tv/tuner/filter/Filter;)I",
3738             (void *)android_media_tv_Tuner_detach_filter },
3739     { "nativeConfigureDvr", "(Landroid/media/tv/tuner/dvr/DvrSettings;)I",
3740             (void *)android_media_tv_Tuner_configure_dvr },
3741     { "nativeStartDvr", "()I", (void *)android_media_tv_Tuner_start_dvr },
3742     { "nativeStopDvr", "()I", (void *)android_media_tv_Tuner_stop_dvr },
3743     { "nativeFlushDvr", "()I", (void *)android_media_tv_Tuner_flush_dvr },
3744     { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_dvr },
3745     { "nativeSetFileDescriptor", "(I)V", (void *)android_media_tv_Tuner_dvr_set_fd },
3746     { "nativeWrite", "(J)J", (void *)android_media_tv_Tuner_write_dvr },
3747     { "nativeWrite", "([BJJ)J", (void *)android_media_tv_Tuner_write_dvr_to_array },
3748 };
3749 
3750 static const JNINativeMethod gDvrPlaybackMethods[] = {
3751     { "nativeAttachFilter", "(Landroid/media/tv/tuner/filter/Filter;)I",
3752             (void *)android_media_tv_Tuner_attach_filter },
3753     { "nativeDetachFilter", "(Landroid/media/tv/tuner/filter/Filter;)I",
3754             (void *)android_media_tv_Tuner_detach_filter },
3755     { "nativeConfigureDvr", "(Landroid/media/tv/tuner/dvr/DvrSettings;)I",
3756             (void *)android_media_tv_Tuner_configure_dvr },
3757     { "nativeStartDvr", "()I", (void *)android_media_tv_Tuner_start_dvr },
3758     { "nativeStopDvr", "()I", (void *)android_media_tv_Tuner_stop_dvr },
3759     { "nativeFlushDvr", "()I", (void *)android_media_tv_Tuner_flush_dvr },
3760     { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_dvr },
3761     { "nativeSetFileDescriptor", "(I)V", (void *)android_media_tv_Tuner_dvr_set_fd },
3762     { "nativeRead", "(J)J", (void *)android_media_tv_Tuner_read_dvr },
3763     { "nativeRead", "([BJJ)J", (void *)android_media_tv_Tuner_read_dvr_from_array },
3764 };
3765 
3766 static const JNINativeMethod gLnbMethods[] = {
3767     { "nativeSetVoltage", "(I)I", (void *)android_media_tv_Tuner_lnb_set_voltage },
3768     { "nativeSetTone", "(I)I", (void *)android_media_tv_Tuner_lnb_set_tone },
3769     { "nativeSetSatellitePosition", "(I)I", (void *)android_media_tv_Tuner_lnb_set_position },
3770     { "nativeSendDiseqcMessage", "([B)I", (void *)android_media_tv_Tuner_lnb_send_diseqc_msg },
3771     { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_lnb },
3772 };
3773 
3774 static const JNINativeMethod gMediaEventMethods[] = {
3775     { "nativeGetLinearBlock", "()Landroid/media/MediaCodec$LinearBlock;",
3776             (void *)android_media_tv_Tuner_media_event_get_linear_block },
3777     { "nativeGetAudioHandle", "()Ljava/lang/Long;",
3778             (void *)android_media_tv_Tuner_media_event_get_audio_handle },
3779     { "nativeFinalize", "()V",
3780             (void *)android_media_tv_Tuner_media_event_finalize },
3781 };
3782 
register_android_media_tv_Tuner(JNIEnv * env)3783 static bool register_android_media_tv_Tuner(JNIEnv *env) {
3784     if (AndroidRuntime::registerNativeMethods(
3785             env, "android/media/tv/tuner/Tuner", gTunerMethods, NELEM(gTunerMethods)) != JNI_OK) {
3786         ALOGE("Failed to register tuner native methods");
3787         return false;
3788     }
3789     if (AndroidRuntime::registerNativeMethods(
3790             env, "android/media/tv/tuner/filter/Filter",
3791             gFilterMethods,
3792             NELEM(gFilterMethods)) != JNI_OK) {
3793         ALOGE("Failed to register filter native methods");
3794         return false;
3795     }
3796     if (AndroidRuntime::registerNativeMethods(
3797             env, "android/media/tv/tuner/filter/TimeFilter",
3798             gTimeFilterMethods,
3799             NELEM(gTimeFilterMethods)) != JNI_OK) {
3800         ALOGE("Failed to register time filter native methods");
3801         return false;
3802     }
3803     if (AndroidRuntime::registerNativeMethods(
3804             env, "android/media/tv/tuner/Descrambler",
3805             gDescramblerMethods,
3806             NELEM(gDescramblerMethods)) != JNI_OK) {
3807         ALOGE("Failed to register descrambler native methods");
3808         return false;
3809     }
3810     if (AndroidRuntime::registerNativeMethods(
3811             env, "android/media/tv/tuner/dvr/DvrRecorder",
3812             gDvrRecorderMethods,
3813             NELEM(gDvrRecorderMethods)) != JNI_OK) {
3814         ALOGE("Failed to register dvr recorder native methods");
3815         return false;
3816     }
3817     if (AndroidRuntime::registerNativeMethods(
3818             env, "android/media/tv/tuner/dvr/DvrPlayback",
3819             gDvrPlaybackMethods,
3820             NELEM(gDvrPlaybackMethods)) != JNI_OK) {
3821         ALOGE("Failed to register dvr playback native methods");
3822         return false;
3823     }
3824     if (AndroidRuntime::registerNativeMethods(
3825             env, "android/media/tv/tuner/Lnb",
3826             gLnbMethods,
3827             NELEM(gLnbMethods)) != JNI_OK) {
3828         ALOGE("Failed to register lnb native methods");
3829         return false;
3830     }
3831     if (AndroidRuntime::registerNativeMethods(
3832             env, "android/media/tv/tuner/filter/MediaEvent",
3833             gMediaEventMethods,
3834             NELEM(gMediaEventMethods)) != JNI_OK) {
3835         ALOGE("Failed to register MediaEvent native methods");
3836         return false;
3837     }
3838     return true;
3839 }
3840 
JNI_OnLoad(JavaVM * vm,void *)3841 jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
3842 {
3843     JNIEnv* env = NULL;
3844     jint result = -1;
3845 
3846     if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
3847         ALOGE("ERROR: GetEnv failed\n");
3848         return result;
3849     }
3850     assert(env != NULL);
3851 
3852     if (!register_android_media_tv_Tuner(env)) {
3853         ALOGE("ERROR: Tuner native registration failed\n");
3854         return result;
3855     }
3856     return JNI_VERSION_1_4;
3857 }
3858