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