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