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