blob: 007d367a533a81fa4eaf7701ecfad8925bd4171e [file] [log] [blame]
shubang8ab43b12019-10-18 15:55:55 -07001/*
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_tv_Tuner.h"
21#include "android_runtime/AndroidRuntime.h"
22
23#include <android/hardware/tv/tuner/1.0/ITuner.h>
24#include <media/stagefright/foundation/ADebug.h>
shubangba21a7f2019-12-05 16:58:55 -080025#include <nativehelper/JNIHelp.h>
shubang8ab43b12019-10-18 15:55:55 -070026
27#pragma GCC diagnostic ignored "-Wunused-function"
28
shubang6f473d62019-11-01 15:42:21 -070029using ::android::hardware::Void;
shubang7e849b02019-10-18 19:36:25 -070030using ::android::hardware::hidl_vec;
shubang030afb52019-11-27 16:09:02 -080031using ::android::hardware::tv::tuner::V1_0::DataFormat;
shubang6f473d62019-11-01 15:42:21 -070032using ::android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
shubang75c87082019-11-15 11:26:56 -080033using ::android::hardware::tv::tuner::V1_0::DemuxFilterPesDataSettings;
34using ::android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
shubang13f15e02019-11-04 17:51:02 -080035using ::android::hardware::tv::tuner::V1_0::DemuxMmtpPid;
shubang964e6132019-11-26 15:05:22 -080036using ::android::hardware::tv::tuner::V1_0::DemuxQueueNotifyBits;
shubang13f15e02019-11-04 17:51:02 -080037using ::android::hardware::tv::tuner::V1_0::DemuxTpid;
shubang75c87082019-11-15 11:26:56 -080038using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterSettings;
shubang6f473d62019-11-01 15:42:21 -070039using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
shubang030afb52019-11-27 16:09:02 -080040using ::android::hardware::tv::tuner::V1_0::DvrSettings;
shubang74bfd482019-10-29 19:10:22 -070041using ::android::hardware::tv::tuner::V1_0::FrontendAnalogSettings;
42using ::android::hardware::tv::tuner::V1_0::FrontendAnalogSifStandard;
43using ::android::hardware::tv::tuner::V1_0::FrontendAnalogType;
shubang8ab43b12019-10-18 15:55:55 -070044using ::android::hardware::tv::tuner::V1_0::ITuner;
shubang030afb52019-11-27 16:09:02 -080045using ::android::hardware::tv::tuner::V1_0::PlaybackSettings;
46using ::android::hardware::tv::tuner::V1_0::RecordSettings;
shubang7e849b02019-10-18 19:36:25 -070047using ::android::hardware::tv::tuner::V1_0::Result;
shubang8ab43b12019-10-18 15:55:55 -070048
49struct fields_t {
shubang13f15e02019-11-04 17:51:02 -080050 jfieldID tunerContext;
shubangcdf30de2019-11-06 17:28:38 -080051 jfieldID filterContext;
shubang13f15e02019-11-04 17:51:02 -080052 jfieldID descramblerContext;
shubang4a0eddf2019-11-08 17:10:18 -080053 jfieldID dvrContext;
shubang7e849b02019-10-18 19:36:25 -070054 jmethodID frontendInitID;
shubang6f473d62019-11-01 15:42:21 -070055 jmethodID filterInitID;
shubang4a0eddf2019-11-08 17:10:18 -080056 jmethodID dvrInitID;
shubang4b8c5402019-10-24 17:49:53 -070057 jmethodID onFrontendEventID;
shubangcdf30de2019-11-06 17:28:38 -080058 jmethodID onFilterStatusID;
shubang760f0312019-11-12 17:11:28 -080059 jmethodID lnbInitID;
60 jmethodID onLnbEventID;
shubang13f15e02019-11-04 17:51:02 -080061 jmethodID descramblerInitID;
shubang8ab43b12019-10-18 15:55:55 -070062};
63
64static fields_t gFields;
65
66namespace android {
shubang760f0312019-11-12 17:11:28 -080067/////////////// LnbCallback ///////////////////////
68LnbCallback::LnbCallback(jweak tunerObj, LnbId id) : mObject(tunerObj), mId(id) {}
69
70Return<void> LnbCallback::onEvent(LnbEventType lnbEventType) {
71 ALOGD("LnbCallback::onEvent, type=%d", lnbEventType);
72 JNIEnv *env = AndroidRuntime::getJNIEnv();
73 env->CallVoidMethod(
74 mObject,
75 gFields.onLnbEventID,
76 (jint)lnbEventType);
77 return Void();
78}
79Return<void> LnbCallback::onDiseqcMessage(const hidl_vec<uint8_t>& /*diseqcMessage*/) {
80 ALOGD("LnbCallback::onDiseqcMessage");
81 return Void();
82}
83
shubang4a0eddf2019-11-08 17:10:18 -080084/////////////// DvrCallback ///////////////////////
85Return<void> DvrCallback::onRecordStatus(RecordStatus /*status*/) {
86 ALOGD("DvrCallback::onRecordStatus");
87 return Void();
88}
89
90Return<void> DvrCallback::onPlaybackStatus(PlaybackStatus /*status*/) {
91 ALOGD("DvrCallback::onPlaybackStatus");
92 return Void();
93}
94
95void DvrCallback::setDvr(const jobject dvr) {
shubangba21a7f2019-12-05 16:58:55 -080096 ALOGD("DvrCallback::setDvr");
shubang4a0eddf2019-11-08 17:10:18 -080097 JNIEnv *env = AndroidRuntime::getJNIEnv();
98 mDvr = env->NewWeakGlobalRef(dvr);
99}
100
shubang9e700ff2019-12-04 16:26:51 -0800101/////////////// Dvr ///////////////////////
102
Greg Kaiser4aaee382020-01-07 09:42:10 -0800103Dvr::Dvr(sp<IDvr> sp, jweak obj) : mDvrSp(sp), mDvrObj(obj), mDvrMQEventFlag(nullptr) {}
shubang9e700ff2019-12-04 16:26:51 -0800104
shubangba21a7f2019-12-05 16:58:55 -0800105Dvr::~Dvr() {
106 EventFlag::deleteEventFlag(&mDvrMQEventFlag);
107}
108
109int Dvr::close() {
110 Result r = mDvrSp->close();
111 if (r == Result::SUCCESS) {
112 EventFlag::deleteEventFlag(&mDvrMQEventFlag);
113 }
114 return (int)r;
115}
116
shubang9e700ff2019-12-04 16:26:51 -0800117sp<IDvr> Dvr::getIDvr() {
118 return mDvrSp;
119}
120
shubang5f4ea352019-12-09 15:12:10 -0800121DvrMQ& Dvr::getDvrMQ() {
122 return *mDvrMQ;
123}
124
shubang6f473d62019-11-01 15:42:21 -0700125/////////////// FilterCallback ///////////////////////
126//TODO: implement filter callback
shubangcdf30de2019-11-06 17:28:38 -0800127Return<void> FilterCallback::onFilterEvent(const DemuxFilterEvent& /*filterEvent*/) {
shubang6f473d62019-11-01 15:42:21 -0700128 ALOGD("FilterCallback::onFilterEvent");
129 return Void();
130}
shubangcdf30de2019-11-06 17:28:38 -0800131
132Return<void> FilterCallback::onFilterStatus(const DemuxFilterStatus status) {
133 ALOGD("FilterCallback::onFilterStatus");
134 JNIEnv *env = AndroidRuntime::getJNIEnv();
135 env->CallVoidMethod(
136 mFilter,
137 gFields.onFilterStatusID,
138 (jint)status);
shubang6f473d62019-11-01 15:42:21 -0700139 return Void();
140}
shubang8ab43b12019-10-18 15:55:55 -0700141
shubangcdf30de2019-11-06 17:28:38 -0800142void FilterCallback::setFilter(const jobject filter) {
143 ALOGD("FilterCallback::setFilter");
144 JNIEnv *env = AndroidRuntime::getJNIEnv();
145 mFilter = env->NewWeakGlobalRef(filter);
146}
147
shubang7648a3c2019-11-25 18:16:45 -0800148/////////////// Filter ///////////////////////
149
150Filter::Filter(sp<IFilter> sp, jweak obj) : mFilterSp(sp), mFilterObj(obj) {}
151
shubang964e6132019-11-26 15:05:22 -0800152Filter::~Filter() {
153 EventFlag::deleteEventFlag(&mFilterMQEventFlag);
154}
155
156int Filter::close() {
157 Result r = mFilterSp->close();
158 if (r == Result::SUCCESS) {
159 EventFlag::deleteEventFlag(&mFilterMQEventFlag);
160 }
161 return (int)r;
162}
163
shubang7648a3c2019-11-25 18:16:45 -0800164sp<IFilter> Filter::getIFilter() {
165 return mFilterSp;
166}
167
shubang4b8c5402019-10-24 17:49:53 -0700168/////////////// FrontendCallback ///////////////////////
169
170FrontendCallback::FrontendCallback(jweak tunerObj, FrontendId id) : mObject(tunerObj), mId(id) {}
171
172Return<void> FrontendCallback::onEvent(FrontendEventType frontendEventType) {
173 ALOGD("FrontendCallback::onEvent, type=%d", frontendEventType);
174 JNIEnv *env = AndroidRuntime::getJNIEnv();
175 env->CallVoidMethod(
176 mObject,
177 gFields.onFrontendEventID,
178 (jint)frontendEventType);
179 return Void();
180}
181Return<void> FrontendCallback::onDiseqcMessage(const hidl_vec<uint8_t>& /*diseqcMessage*/) {
182 ALOGD("FrontendCallback::onDiseqcMessage");
183 return Void();
184}
185
186Return<void> FrontendCallback::onScanMessage(
187 FrontendScanMessageType type, const FrontendScanMessage& /*message*/) {
188 ALOGD("FrontendCallback::onScanMessage, type=%d", type);
189 return Void();
190}
191
shubang6f473d62019-11-01 15:42:21 -0700192/////////////// Tuner ///////////////////////
shubang4b8c5402019-10-24 17:49:53 -0700193
shubang8ab43b12019-10-18 15:55:55 -0700194sp<ITuner> JTuner::mTuner;
195
196JTuner::JTuner(JNIEnv *env, jobject thiz)
197 : mClass(NULL) {
198 jclass clazz = env->GetObjectClass(thiz);
199 CHECK(clazz != NULL);
200
201 mClass = (jclass)env->NewGlobalRef(clazz);
202 mObject = env->NewWeakGlobalRef(thiz);
203 if (mTuner == NULL) {
204 mTuner = getTunerService();
205 }
206}
207
208JTuner::~JTuner() {
209 JNIEnv *env = AndroidRuntime::getJNIEnv();
210
211 env->DeleteGlobalRef(mClass);
212 mTuner = NULL;
213 mClass = NULL;
214 mObject = NULL;
215}
216
217sp<ITuner> JTuner::getTunerService() {
218 if (mTuner == nullptr) {
219 mTuner = ITuner::getService();
220
221 if (mTuner == nullptr) {
222 ALOGW("Failed to get tuner service.");
223 }
224 }
225 return mTuner;
226}
227
shubang7e849b02019-10-18 19:36:25 -0700228jobject JTuner::getFrontendIds() {
229 ALOGD("JTuner::getFrontendIds()");
shubang7e849b02019-10-18 19:36:25 -0700230 mTuner->getFrontendIds([&](Result, const hidl_vec<FrontendId>& frontendIds) {
shubang4b8c5402019-10-24 17:49:53 -0700231 mFeIds = frontendIds;
shubang7e849b02019-10-18 19:36:25 -0700232 });
shubang4b8c5402019-10-24 17:49:53 -0700233 if (mFeIds.size() == 0) {
shubang7e849b02019-10-18 19:36:25 -0700234 ALOGW("Frontend isn't available");
235 return NULL;
236 }
237
238 JNIEnv *env = AndroidRuntime::getJNIEnv();
239 jclass arrayListClazz = env->FindClass("java/util/ArrayList");
240 jmethodID arrayListAdd = env->GetMethodID(arrayListClazz, "add", "(Ljava/lang/Object;)Z");
241 jobject obj = env->NewObject(arrayListClazz, env->GetMethodID(arrayListClazz, "<init>", "()V"));
242
243 jclass integerClazz = env->FindClass("java/lang/Integer");
244 jmethodID intInit = env->GetMethodID(integerClazz, "<init>", "(I)V");
245
shubang4b8c5402019-10-24 17:49:53 -0700246 for (int i=0; i < mFeIds.size(); i++) {
247 jobject idObj = env->NewObject(integerClazz, intInit, mFeIds[i]);
shubang7e849b02019-10-18 19:36:25 -0700248 env->CallBooleanMethod(obj, arrayListAdd, idObj);
249 }
250 return obj;
251}
252
253jobject JTuner::openFrontendById(int id) {
shubang4b8c5402019-10-24 17:49:53 -0700254 sp<IFrontend> fe;
shubang7e849b02019-10-18 19:36:25 -0700255 mTuner->openFrontendById(id, [&](Result, const sp<IFrontend>& frontend) {
shubang4b8c5402019-10-24 17:49:53 -0700256 fe = frontend;
shubang7e849b02019-10-18 19:36:25 -0700257 });
shubang4b8c5402019-10-24 17:49:53 -0700258 if (fe == nullptr) {
shubang7e849b02019-10-18 19:36:25 -0700259 ALOGE("Failed to open frontend");
260 return NULL;
261 }
shubang4b8c5402019-10-24 17:49:53 -0700262 mFe = fe;
263 sp<FrontendCallback> feCb = new FrontendCallback(mObject, id);
264 fe->setCallback(feCb);
shubang7e849b02019-10-18 19:36:25 -0700265
266 jint jId = (jint) id;
shubang964e6132019-11-26 15:05:22 -0800267
shubang7e849b02019-10-18 19:36:25 -0700268 JNIEnv *env = AndroidRuntime::getJNIEnv();
269 // TODO: add more fields to frontend
270 return env->NewObject(
271 env->FindClass("android/media/tv/tuner/Tuner$Frontend"),
272 gFields.frontendInitID,
shubang4b8c5402019-10-24 17:49:53 -0700273 mObject,
shubang7e849b02019-10-18 19:36:25 -0700274 (jint) jId);
275}
276
shubang760f0312019-11-12 17:11:28 -0800277jobject JTuner::getLnbIds() {
278 ALOGD("JTuner::getLnbIds()");
279 mTuner->getLnbIds([&](Result, const hidl_vec<FrontendId>& lnbIds) {
280 mLnbIds = lnbIds;
281 });
282 if (mLnbIds.size() == 0) {
283 ALOGW("Lnb isn't available");
284 return NULL;
285 }
286
287 JNIEnv *env = AndroidRuntime::getJNIEnv();
288 jclass arrayListClazz = env->FindClass("java/util/ArrayList");
289 jmethodID arrayListAdd = env->GetMethodID(arrayListClazz, "add", "(Ljava/lang/Object;)Z");
290 jobject obj = env->NewObject(arrayListClazz, env->GetMethodID(arrayListClazz, "<init>", "()V"));
291
292 jclass integerClazz = env->FindClass("java/lang/Integer");
293 jmethodID intInit = env->GetMethodID(integerClazz, "<init>", "(I)V");
294
295 for (int i=0; i < mLnbIds.size(); i++) {
296 jobject idObj = env->NewObject(integerClazz, intInit, mLnbIds[i]);
297 env->CallBooleanMethod(obj, arrayListAdd, idObj);
298 }
299 return obj;
300}
301
302jobject JTuner::openLnbById(int id) {
303 sp<ILnb> lnbSp;
304 mTuner->openLnbById(id, [&](Result, const sp<ILnb>& lnb) {
305 lnbSp = lnb;
306 });
307 if (lnbSp == nullptr) {
308 ALOGE("Failed to open lnb");
309 return NULL;
310 }
311 mLnb = lnbSp;
312 sp<LnbCallback> lnbCb = new LnbCallback(mObject, id);
313 mLnb->setCallback(lnbCb);
314
315 JNIEnv *env = AndroidRuntime::getJNIEnv();
316 return env->NewObject(
shubangd351b822020-01-22 17:29:18 -0800317 env->FindClass("android/media/tv/tuner/Lnb"),
shubang760f0312019-11-12 17:11:28 -0800318 gFields.lnbInitID,
319 mObject,
320 id);
321}
322
shubang74bfd482019-10-29 19:10:22 -0700323int JTuner::tune(const FrontendSettings& settings) {
324 if (mFe == NULL) {
325 ALOGE("frontend is not initialized");
326 return (int)Result::INVALID_STATE;
327 }
328 Result result = mFe->tune(settings);
329 return (int)result;
330}
331
shubangd5b845f2019-12-11 15:29:09 -0800332int JTuner::scan(const FrontendSettings& settings, FrontendScanType scanType) {
333 if (mFe == NULL) {
334 ALOGE("frontend is not initialized");
335 return (int)Result::INVALID_STATE;
336 }
337 Result result = mFe->scan(settings, scanType);
338 return (int)result;
339}
340
shubang6f473d62019-11-01 15:42:21 -0700341bool JTuner::openDemux() {
342 if (mTuner == nullptr) {
343 return false;
344 }
345 if (mDemux != nullptr) {
346 return true;
347 }
348 mTuner->openDemux([&](Result, uint32_t demuxId, const sp<IDemux>& demux) {
349 mDemux = demux;
350 mDemuxId = demuxId;
351 ALOGD("open demux, id = %d", demuxId);
352 });
353 if (mDemux == nullptr) {
354 return false;
355 }
356 return true;
357}
358
shubang13f15e02019-11-04 17:51:02 -0800359jobject JTuner::openDescrambler() {
360 ALOGD("JTuner::openDescrambler");
361 if (mTuner == nullptr) {
362 return NULL;
363 }
364 sp<IDescrambler> descramblerSp;
365 mTuner->openDescrambler([&](Result, const sp<IDescrambler>& descrambler) {
366 descramblerSp = descrambler;
367 });
368
369 if (descramblerSp == NULL) {
370 return NULL;
371 }
372
373 JNIEnv *env = AndroidRuntime::getJNIEnv();
374 jobject descramblerObj =
375 env->NewObject(
shubangd351b822020-01-22 17:29:18 -0800376 env->FindClass("android/media/tv/tuner/Descrambler"),
shubang13f15e02019-11-04 17:51:02 -0800377 gFields.descramblerInitID,
378 mObject);
379
380 descramblerSp->incStrong(descramblerObj);
381 env->SetLongField(descramblerObj, gFields.descramblerContext, (jlong)descramblerSp.get());
382
383 return descramblerObj;
384}
385
shubang6f473d62019-11-01 15:42:21 -0700386jobject JTuner::openFilter(DemuxFilterType type, int bufferSize) {
387 if (mDemux == NULL) {
388 if (!openDemux()) {
389 return NULL;
390 }
391 }
392
shubang7648a3c2019-11-25 18:16:45 -0800393 sp<IFilter> iFilterSp;
shubangcdf30de2019-11-06 17:28:38 -0800394 sp<FilterCallback> callback = new FilterCallback();
395 mDemux->openFilter(type, bufferSize, callback,
shubang6f473d62019-11-01 15:42:21 -0700396 [&](Result, const sp<IFilter>& filter) {
shubang7648a3c2019-11-25 18:16:45 -0800397 iFilterSp = filter;
shubang6f473d62019-11-01 15:42:21 -0700398 });
shubang7648a3c2019-11-25 18:16:45 -0800399 if (iFilterSp == NULL) {
shubang6f473d62019-11-01 15:42:21 -0700400 ALOGD("Failed to open filter, type = %d", type.mainType);
401 return NULL;
402 }
403 int fId;
shubang7648a3c2019-11-25 18:16:45 -0800404 iFilterSp->getId([&](Result, uint32_t filterId) {
shubang6f473d62019-11-01 15:42:21 -0700405 fId = filterId;
406 });
shubang6f473d62019-11-01 15:42:21 -0700407
408 JNIEnv *env = AndroidRuntime::getJNIEnv();
shubangcdf30de2019-11-06 17:28:38 -0800409 jobject filterObj =
410 env->NewObject(
shubangd351b822020-01-22 17:29:18 -0800411 env->FindClass("android/media/tv/tuner/filter/Filter"),
shubangcdf30de2019-11-06 17:28:38 -0800412 gFields.filterInitID,
413 mObject,
414 (jint) fId);
415
shubang7648a3c2019-11-25 18:16:45 -0800416 sp<Filter> filterSp = new Filter(iFilterSp, filterObj);
shubangcdf30de2019-11-06 17:28:38 -0800417 filterSp->incStrong(filterObj);
418 env->SetLongField(filterObj, gFields.filterContext, (jlong)filterSp.get());
419
420 callback->setFilter(filterObj);
421
422 return filterObj;
shubang6f473d62019-11-01 15:42:21 -0700423}
424
shubang4a0eddf2019-11-08 17:10:18 -0800425jobject JTuner::openDvr(DvrType type, int bufferSize) {
426 ALOGD("JTuner::openDvr");
427 if (mDemux == NULL) {
428 if (!openDemux()) {
429 return NULL;
430 }
431 }
shubang9e700ff2019-12-04 16:26:51 -0800432 sp<IDvr> iDvrSp;
shubang4a0eddf2019-11-08 17:10:18 -0800433 sp<DvrCallback> callback = new DvrCallback();
434 mDemux->openDvr(type, bufferSize, callback,
435 [&](Result, const sp<IDvr>& dvr) {
shubang9e700ff2019-12-04 16:26:51 -0800436 iDvrSp = dvr;
shubang4a0eddf2019-11-08 17:10:18 -0800437 });
438
shubang9e700ff2019-12-04 16:26:51 -0800439 if (iDvrSp == NULL) {
shubang4a0eddf2019-11-08 17:10:18 -0800440 return NULL;
441 }
442
443 JNIEnv *env = AndroidRuntime::getJNIEnv();
444 jobject dvrObj =
445 env->NewObject(
shubangd351b822020-01-22 17:29:18 -0800446 env->FindClass("android/media/tv/tuner/dvr/Dvr"),
shubang4a0eddf2019-11-08 17:10:18 -0800447 gFields.dvrInitID,
448 mObject);
shubang9e700ff2019-12-04 16:26:51 -0800449 sp<Dvr> dvrSp = new Dvr(iDvrSp, dvrObj);
shubang4a0eddf2019-11-08 17:10:18 -0800450 dvrSp->incStrong(dvrObj);
451 env->SetLongField(dvrObj, gFields.dvrContext, (jlong)dvrSp.get());
452
453 callback->setDvr(dvrObj);
454
455 return dvrObj;
456}
457
shubang8ab43b12019-10-18 15:55:55 -0700458} // namespace android
459
460////////////////////////////////////////////////////////////////////////////////
461
462using namespace android;
463
464static sp<JTuner> setTuner(JNIEnv *env, jobject thiz, const sp<JTuner> &tuner) {
shubang13f15e02019-11-04 17:51:02 -0800465 sp<JTuner> old = (JTuner *)env->GetLongField(thiz, gFields.tunerContext);
shubang8ab43b12019-10-18 15:55:55 -0700466
467 if (tuner != NULL) {
468 tuner->incStrong(thiz);
469 }
470 if (old != NULL) {
471 old->decStrong(thiz);
472 }
shubang13f15e02019-11-04 17:51:02 -0800473 env->SetLongField(thiz, gFields.tunerContext, (jlong)tuner.get());
shubang8ab43b12019-10-18 15:55:55 -0700474
475 return old;
476}
477
478static sp<JTuner> getTuner(JNIEnv *env, jobject thiz) {
shubang13f15e02019-11-04 17:51:02 -0800479 return (JTuner *)env->GetLongField(thiz, gFields.tunerContext);
480}
481
482static sp<IDescrambler> getDescrambler(JNIEnv *env, jobject descrambler) {
483 return (IDescrambler *)env->GetLongField(descrambler, gFields.descramblerContext);
484}
485
486static DemuxPid getDemuxPid(int pidType, int pid) {
487 DemuxPid demuxPid;
488 if ((int)pidType == 1) {
489 demuxPid.tPid(static_cast<DemuxTpid>(pid));
490 } else if ((int)pidType == 2) {
491 demuxPid.mmtpPid(static_cast<DemuxMmtpPid>(pid));
492 }
493 return demuxPid;
shubang8ab43b12019-10-18 15:55:55 -0700494}
495
shubang74bfd482019-10-29 19:10:22 -0700496static FrontendSettings getFrontendSettings(JNIEnv *env, int type, jobject settings) {
497 FrontendSettings frontendSettings;
shubangd351b822020-01-22 17:29:18 -0800498 jclass clazz = env->FindClass("android/media/tv/tuner/frontend/FrontendSettings");
shubang964e6132019-11-26 15:05:22 -0800499 jfieldID freqField = env->GetFieldID(clazz, "mFrequency", "I");
shubang74bfd482019-10-29 19:10:22 -0700500 uint32_t freq = static_cast<uint32_t>(env->GetIntField(clazz, freqField));
501
502 // TODO: handle the other 8 types of settings
503 if (type == 1) {
504 // analog
shubangd351b822020-01-22 17:29:18 -0800505 clazz = env->FindClass("android/media/tv/tuner/frontend/AnalogFrontendSettings");
shubang74bfd482019-10-29 19:10:22 -0700506 FrontendAnalogType analogType =
507 static_cast<FrontendAnalogType>(
508 env->GetIntField(settings, env->GetFieldID(clazz, "mAnalogType", "I")));
509 FrontendAnalogSifStandard sifStandard =
510 static_cast<FrontendAnalogSifStandard>(
511 env->GetIntField(settings, env->GetFieldID(clazz, "mSifStandard", "I")));
512 FrontendAnalogSettings frontendAnalogSettings {
513 .frequency = freq,
514 .type = analogType,
515 .sifStandard = sifStandard,
516 };
517 frontendSettings.analog(frontendAnalogSettings);
518 }
519 return frontendSettings;
520}
521
shubang7648a3c2019-11-25 18:16:45 -0800522static sp<Filter> getFilter(JNIEnv *env, jobject filter) {
523 return (Filter *)env->GetLongField(filter, gFields.filterContext);
shubangcdf30de2019-11-06 17:28:38 -0800524}
525
shubang030afb52019-11-27 16:09:02 -0800526static DvrSettings getDvrSettings(JNIEnv *env, jobject settings) {
527 DvrSettings dvrSettings;
shubangd351b822020-01-22 17:29:18 -0800528 jclass clazz = env->FindClass("android/media/tv/tuner/dvr/DvrSettings");
shubang030afb52019-11-27 16:09:02 -0800529 uint32_t statusMask =
530 static_cast<uint32_t>(env->GetIntField(
531 settings, env->GetFieldID(clazz, "mStatusMask", "I")));
532 uint32_t lowThreshold =
533 static_cast<uint32_t>(env->GetIntField(
534 settings, env->GetFieldID(clazz, "mLowThreshold", "I")));
535 uint32_t highThreshold =
536 static_cast<uint32_t>(env->GetIntField(
537 settings, env->GetFieldID(clazz, "mHighThreshold", "I")));
538 uint8_t packetSize =
539 static_cast<uint8_t>(env->GetIntField(
540 settings, env->GetFieldID(clazz, "mPacketSize", "I")));
541 DataFormat dataFormat =
542 static_cast<DataFormat>(env->GetIntField(
543 settings, env->GetFieldID(clazz, "mDataFormat", "I")));
544 DvrType type =
545 static_cast<DvrType>(env->GetIntField(
546 settings, env->GetFieldID(clazz, "mType", "I")));
547 if (type == DvrType::RECORD) {
548 RecordSettings recordSettings {
549 .statusMask = static_cast<unsigned char>(statusMask),
550 .lowThreshold = lowThreshold,
551 .highThreshold = highThreshold,
552 .dataFormat = dataFormat,
553 .packetSize = packetSize,
554 };
555 dvrSettings.record(recordSettings);
556 } else if (type == DvrType::PLAYBACK) {
557 PlaybackSettings PlaybackSettings {
558 .statusMask = statusMask,
559 .lowThreshold = lowThreshold,
560 .highThreshold = highThreshold,
561 .dataFormat = dataFormat,
562 .packetSize = packetSize,
563 };
564 dvrSettings.playback(PlaybackSettings);
565 }
566 return dvrSettings;
567}
568
shubang9e700ff2019-12-04 16:26:51 -0800569static sp<Dvr> getDvr(JNIEnv *env, jobject dvr) {
570 return (Dvr *)env->GetLongField(dvr, gFields.dvrContext);
shubang4a0eddf2019-11-08 17:10:18 -0800571}
572
shubang8ab43b12019-10-18 15:55:55 -0700573static void android_media_tv_Tuner_native_init(JNIEnv *env) {
574 jclass clazz = env->FindClass("android/media/tv/tuner/Tuner");
575 CHECK(clazz != NULL);
576
shubang13f15e02019-11-04 17:51:02 -0800577 gFields.tunerContext = env->GetFieldID(clazz, "mNativeContext", "J");
578 CHECK(gFields.tunerContext != NULL);
shubang7e849b02019-10-18 19:36:25 -0700579
shubang4b8c5402019-10-24 17:49:53 -0700580 gFields.onFrontendEventID = env->GetMethodID(clazz, "onFrontendEvent", "(I)V");
581
shubang760f0312019-11-12 17:11:28 -0800582 gFields.onLnbEventID = env->GetMethodID(clazz, "onLnbEvent", "(I)V");
583
shubang7e849b02019-10-18 19:36:25 -0700584 jclass frontendClazz = env->FindClass("android/media/tv/tuner/Tuner$Frontend");
shubang4b8c5402019-10-24 17:49:53 -0700585 gFields.frontendInitID =
586 env->GetMethodID(frontendClazz, "<init>", "(Landroid/media/tv/tuner/Tuner;I)V");
shubang6f473d62019-11-01 15:42:21 -0700587
shubangd351b822020-01-22 17:29:18 -0800588 jclass lnbClazz = env->FindClass("android/media/tv/tuner/Lnb");
shubang760f0312019-11-12 17:11:28 -0800589 gFields.lnbInitID =
590 env->GetMethodID(lnbClazz, "<init>", "(Landroid/media/tv/tuner/Tuner;I)V");
591
shubangd351b822020-01-22 17:29:18 -0800592 jclass filterClazz = env->FindClass("android/media/tv/tuner/filter/Filter");
shubangcdf30de2019-11-06 17:28:38 -0800593 gFields.filterContext = env->GetFieldID(filterClazz, "mNativeContext", "J");
shubang6f473d62019-11-01 15:42:21 -0700594 gFields.filterInitID =
595 env->GetMethodID(filterClazz, "<init>", "(Landroid/media/tv/tuner/Tuner;I)V");
shubangcdf30de2019-11-06 17:28:38 -0800596 gFields.onFilterStatusID =
597 env->GetMethodID(filterClazz, "onFilterStatus", "(I)V");
shubang13f15e02019-11-04 17:51:02 -0800598
shubangd351b822020-01-22 17:29:18 -0800599 jclass descramblerClazz = env->FindClass("android/media/tv/tuner/Descrambler");
shubang13f15e02019-11-04 17:51:02 -0800600 gFields.descramblerContext = env->GetFieldID(descramblerClazz, "mNativeContext", "J");
601 gFields.descramblerInitID =
602 env->GetMethodID(descramblerClazz, "<init>", "(Landroid/media/tv/tuner/Tuner;)V");
shubang4a0eddf2019-11-08 17:10:18 -0800603
shubangd351b822020-01-22 17:29:18 -0800604 jclass dvrClazz = env->FindClass("android/media/tv/tuner/dvr/Dvr");
shubang4a0eddf2019-11-08 17:10:18 -0800605 gFields.dvrContext = env->GetFieldID(dvrClazz, "mNativeContext", "J");
606 gFields.dvrInitID = env->GetMethodID(dvrClazz, "<init>", "(Landroid/media/tv/tuner/Tuner;)V");
shubang8ab43b12019-10-18 15:55:55 -0700607}
608
609static void android_media_tv_Tuner_native_setup(JNIEnv *env, jobject thiz) {
610 sp<JTuner> tuner = new JTuner(env, thiz);
611 setTuner(env,thiz, tuner);
612}
613
shubang7e849b02019-10-18 19:36:25 -0700614static jobject android_media_tv_Tuner_get_frontend_ids(JNIEnv *env, jobject thiz) {
615 sp<JTuner> tuner = getTuner(env, thiz);
616 return tuner->getFrontendIds();
617}
618
619static jobject android_media_tv_Tuner_open_frontend_by_id(JNIEnv *env, jobject thiz, jint id) {
620 sp<JTuner> tuner = getTuner(env, thiz);
621 return tuner->openFrontendById(id);
622}
623
shubang74bfd482019-10-29 19:10:22 -0700624static int android_media_tv_Tuner_tune(JNIEnv *env, jobject thiz, jint type, jobject settings) {
625 sp<JTuner> tuner = getTuner(env, thiz);
626 return tuner->tune(getFrontendSettings(env, type, settings));
627}
628
shubang793e5702019-12-26 15:15:46 -0800629static int android_media_tv_Tuner_stop_tune(JNIEnv*, jobject) {
shubange65b6862019-12-17 15:43:35 -0800630 return 0;
631}
632
shubangd5b845f2019-12-11 15:29:09 -0800633static int android_media_tv_Tuner_scan(
634 JNIEnv *env, jobject thiz, jint settingsType, jobject settings, jint scanType) {
635 sp<JTuner> tuner = getTuner(env, thiz);
636 return tuner->scan(getFrontendSettings(
637 env, settingsType, settings), static_cast<FrontendScanType>(scanType));
638}
639
shubang793e5702019-12-26 15:15:46 -0800640static int android_media_tv_Tuner_stop_scan(JNIEnv*, jobject) {
shubange65b6862019-12-17 15:43:35 -0800641 return 0;
642}
643
shubang793e5702019-12-26 15:15:46 -0800644static int android_media_tv_Tuner_set_lnb(JNIEnv*, jobject, jint) {
645 return 0;
646}
647
648static int android_media_tv_Tuner_set_lna(JNIEnv*, jobject, jint, jboolean) {
shubange65b6862019-12-17 15:43:35 -0800649 return 0;
650}
651
shubangd351b822020-01-22 17:29:18 -0800652static jobject android_media_tv_Tuner_get_frontend_status(JNIEnv, jobject, jintArray) {
shubang1512ec12019-12-23 18:22:42 -0800653 return NULL;
654}
655
shubang7343fee2019-12-27 12:02:08 -0800656static int android_media_tv_Tuner_gat_av_sync_hw_id(JNIEnv*, jobject, jobject) {
657 return 0;
658}
659
660static jlong android_media_tv_Tuner_gat_av_sync_time(JNIEnv*, jobject, jint) {
661 return 0;
662}
663
664static int android_media_tv_Tuner_connect_cicam(JNIEnv*, jobject, jint) {
665 return 0;
666}
667
668static int android_media_tv_Tuner_disconnect_cicam(JNIEnv*, jobject) {
669 return 0;
670}
671
shubang95c1f752019-12-27 16:29:48 -0800672static jobject android_media_tv_Tuner_get_frontend_info(JNIEnv*, jobject, jint) {
673 return NULL;
674}
675
shubang760f0312019-11-12 17:11:28 -0800676static jobject android_media_tv_Tuner_get_lnb_ids(JNIEnv *env, jobject thiz) {
677 sp<JTuner> tuner = getTuner(env, thiz);
678 return tuner->getLnbIds();
679}
680
681static jobject android_media_tv_Tuner_open_lnb_by_id(JNIEnv *env, jobject thiz, jint id) {
682 sp<JTuner> tuner = getTuner(env, thiz);
683 return tuner->openLnbById(id);
684}
685
shubang6f473d62019-11-01 15:42:21 -0700686static jobject android_media_tv_Tuner_open_filter(
shubangd351b822020-01-22 17:29:18 -0800687 JNIEnv *env, jobject thiz, jint type, jint subType, jlong bufferSize) {
shubang6f473d62019-11-01 15:42:21 -0700688 sp<JTuner> tuner = getTuner(env, thiz);
689 DemuxFilterType filterType {
690 .mainType = static_cast<DemuxFilterMainType>(type),
691 };
692
693 // TODO: other sub types
694 filterType.subType.tsFilterType(static_cast<DemuxTsFilterType>(subType));
695
696 return tuner->openFilter(filterType, bufferSize);
697}
698
shubang4347e2e2019-12-13 17:20:40 -0800699static jobject android_media_tv_Tuner_open_time_filter(JNIEnv, jobject) {
700 return NULL;
701}
702
shubang75c87082019-11-15 11:26:56 -0800703static DemuxFilterSettings getFilterSettings(
704 JNIEnv *env, int type, int subtype, jobject filterSettingsObj) {
705 DemuxFilterSettings filterSettings;
706 // TODO: more setting types
707 jobject settingsObj =
708 env->GetObjectField(
709 filterSettingsObj,
710 env->GetFieldID(
shubangd351b822020-01-22 17:29:18 -0800711 env->FindClass("android/media/tv/tuner/filter/FilterConfiguration"),
shubang75c87082019-11-15 11:26:56 -0800712 "mSettings",
shubangd351b822020-01-22 17:29:18 -0800713 "Landroid/media/tv/tuner/filter/Settings;"));
shubang75c87082019-11-15 11:26:56 -0800714 if (type == (int)DemuxFilterMainType::TS) {
715 // DemuxTsFilterSettings
shubangd351b822020-01-22 17:29:18 -0800716 jclass clazz = env->FindClass("android/media/tv/tuner/filter/TsFilterConfiguration");
shubang75c87082019-11-15 11:26:56 -0800717 int tpid = env->GetIntField(filterSettingsObj, env->GetFieldID(clazz, "mTpid", "I"));
718 if (subtype == (int)DemuxTsFilterType::PES) {
719 // DemuxFilterPesDataSettings
720 jclass settingClazz =
shubangd351b822020-01-22 17:29:18 -0800721 env->FindClass("android/media/tv/tuner/filter/PesSettings");
shubang75c87082019-11-15 11:26:56 -0800722 int streamId = env->GetIntField(
723 settingsObj, env->GetFieldID(settingClazz, "mStreamId", "I"));
724 bool isRaw = (bool)env->GetBooleanField(
725 settingsObj, env->GetFieldID(settingClazz, "mIsRaw", "Z"));
726 DemuxFilterPesDataSettings filterPesDataSettings {
727 .streamId = static_cast<uint16_t>(streamId),
728 .isRaw = isRaw,
729 };
730 DemuxTsFilterSettings tsFilterSettings {
731 .tpid = static_cast<uint16_t>(tpid),
732 };
733 tsFilterSettings.filterSettings.pesData(filterPesDataSettings);
734 filterSettings.ts(tsFilterSettings);
735 }
736 }
737 return filterSettings;
738}
739
shubang964e6132019-11-26 15:05:22 -0800740static int copyData(JNIEnv *env, sp<Filter> filter, jbyteArray buffer, jint offset, int size) {
741 ALOGD("copyData, size=%d, offset=%d", size, offset);
742
743 int available = filter->mFilterMQ->availableToRead();
744 ALOGD("copyData, available=%d", available);
745 size = std::min(size, available);
746
747 jboolean isCopy;
748 jbyte *dst = env->GetByteArrayElements(buffer, &isCopy);
749 ALOGD("copyData, isCopy=%d", isCopy);
750 if (dst == nullptr) {
751 ALOGD("Failed to GetByteArrayElements");
752 return 0;
753 }
754
755 if (filter->mFilterMQ->read(reinterpret_cast<unsigned char*>(dst) + offset, size)) {
756 env->ReleaseByteArrayElements(buffer, dst, 0);
757 filter->mFilterMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
758 } else {
759 ALOGD("Failed to read FMQ");
760 env->ReleaseByteArrayElements(buffer, dst, 0);
761 return 0;
762 }
763 return size;
764}
765
shubang75c87082019-11-15 11:26:56 -0800766static int android_media_tv_Tuner_configure_filter(
767 JNIEnv *env, jobject filter, int type, int subtype, jobject settings) {
768 ALOGD("configure filter type=%d, subtype=%d", type, subtype);
shubang964e6132019-11-26 15:05:22 -0800769 sp<Filter> filterSp = getFilter(env, filter);
770 sp<IFilter> iFilterSp = filterSp->getIFilter();
771 if (iFilterSp == NULL) {
shubang75c87082019-11-15 11:26:56 -0800772 ALOGD("Failed to configure filter: filter not found");
773 return (int)Result::INVALID_STATE;
774 }
775 DemuxFilterSettings filterSettings = getFilterSettings(env, type, subtype, settings);
shubang964e6132019-11-26 15:05:22 -0800776 Result res = iFilterSp->configure(filterSettings);
777 MQDescriptorSync<uint8_t> filterMQDesc;
778 if (res == Result::SUCCESS && filterSp->mFilterMQ == NULL) {
779 Result getQueueDescResult = Result::UNKNOWN_ERROR;
780 iFilterSp->getQueueDesc(
781 [&](Result r, const MQDescriptorSync<uint8_t>& desc) {
782 filterMQDesc = desc;
783 getQueueDescResult = r;
784 ALOGD("getFilterQueueDesc");
785 });
786 if (getQueueDescResult == Result::SUCCESS) {
787 filterSp->mFilterMQ = std::make_unique<FilterMQ>(filterMQDesc, true);
788 EventFlag::createEventFlag(
789 filterSp->mFilterMQ->getEventFlagWord(), &(filterSp->mFilterMQEventFlag));
790 }
791 }
shubang75c87082019-11-15 11:26:56 -0800792 return (int)res;
793}
794
shubang793e5702019-12-26 15:15:46 -0800795static int android_media_tv_Tuner_get_filter_id(JNIEnv*, jobject) {
796 return 0;
797}
798
799static int android_media_tv_Tuner_set_filter_data_source(JNIEnv*, jobject, jobject) {
800 return 0;
801}
802
803static int android_media_tv_Tuner_start_filter(JNIEnv *env, jobject filter) {
shubang7648a3c2019-11-25 18:16:45 -0800804 sp<IFilter> filterSp = getFilter(env, filter)->getIFilter();
shubangd0977902019-11-07 18:58:43 -0800805 if (filterSp == NULL) {
806 ALOGD("Failed to start filter: filter not found");
807 return false;
808 }
shubang793e5702019-12-26 15:15:46 -0800809 Result r = filterSp->start();
810 return (int) r;
shubangd0977902019-11-07 18:58:43 -0800811}
812
shubang793e5702019-12-26 15:15:46 -0800813static int android_media_tv_Tuner_stop_filter(JNIEnv *env, jobject filter) {
shubang7648a3c2019-11-25 18:16:45 -0800814 sp<IFilter> filterSp = getFilter(env, filter)->getIFilter();
shubangd0977902019-11-07 18:58:43 -0800815 if (filterSp == NULL) {
816 ALOGD("Failed to stop filter: filter not found");
817 return false;
818 }
shubang793e5702019-12-26 15:15:46 -0800819 Result r = filterSp->stop();
820 return (int) r;
shubangd0977902019-11-07 18:58:43 -0800821}
822
shubang793e5702019-12-26 15:15:46 -0800823static int android_media_tv_Tuner_flush_filter(JNIEnv *env, jobject filter) {
shubang7648a3c2019-11-25 18:16:45 -0800824 sp<IFilter> filterSp = getFilter(env, filter)->getIFilter();
shubangd0977902019-11-07 18:58:43 -0800825 if (filterSp == NULL) {
826 ALOGD("Failed to flush filter: filter not found");
827 return false;
828 }
shubang793e5702019-12-26 15:15:46 -0800829 Result r = filterSp->flush();
830 return (int) r;
shubangd0977902019-11-07 18:58:43 -0800831}
832
shubang964e6132019-11-26 15:05:22 -0800833static int android_media_tv_Tuner_read_filter_fmq(
shubangd351b822020-01-22 17:29:18 -0800834 JNIEnv *env, jobject filter, jbyteArray buffer, jlong offset, jlong size) {
shubang964e6132019-11-26 15:05:22 -0800835 sp<Filter> filterSp = getFilter(env, filter);
836 if (filterSp == NULL) {
837 ALOGD("Failed to read filter FMQ: filter not found");
838 return 0;
839 }
840 return copyData(env, filterSp, buffer, offset, size);
841}
842
shubang793e5702019-12-26 15:15:46 -0800843static int android_media_tv_Tuner_close_filter(JNIEnv*, jobject) {
844 return 0;
845}
846
shubang4347e2e2019-12-13 17:20:40 -0800847// TODO: implement TimeFilter functions
848static int android_media_tv_Tuner_time_filter_set_timestamp(
849 JNIEnv, jobject, jlong) {
850 return 0;
851}
852
853static int android_media_tv_Tuner_time_filter_clear_timestamp(JNIEnv, jobject) {
854 return 0;
855}
856
857static jobject android_media_tv_Tuner_time_filter_get_timestamp(JNIEnv, jobject) {
858 return NULL;
859}
860
861static jobject android_media_tv_Tuner_time_filter_get_source_time(JNIEnv, jobject) {
862 return NULL;
863}
864
865static int android_media_tv_Tuner_time_filter_close(JNIEnv, jobject) {
866 return 0;
867}
868
shubang13f15e02019-11-04 17:51:02 -0800869static jobject android_media_tv_Tuner_open_descrambler(JNIEnv *env, jobject thiz) {
870 sp<JTuner> tuner = getTuner(env, thiz);
871 return tuner->openDescrambler();
872}
873
shubang99c89922019-12-17 17:33:15 -0800874static int android_media_tv_Tuner_add_pid(
shubang13f15e02019-11-04 17:51:02 -0800875 JNIEnv *env, jobject descrambler, jint pidType, jint pid, jobject filter) {
876 sp<IDescrambler> descramblerSp = getDescrambler(env, descrambler);
877 if (descramblerSp == NULL) {
878 return false;
879 }
shubang7648a3c2019-11-25 18:16:45 -0800880 sp<IFilter> filterSp = getFilter(env, filter)->getIFilter();
shubang13f15e02019-11-04 17:51:02 -0800881 Result result = descramblerSp->addPid(getDemuxPid((int)pidType, (int)pid), filterSp);
shubang99c89922019-12-17 17:33:15 -0800882 return (int)result;
shubang13f15e02019-11-04 17:51:02 -0800883}
884
shubang99c89922019-12-17 17:33:15 -0800885static int android_media_tv_Tuner_remove_pid(
shubang13f15e02019-11-04 17:51:02 -0800886 JNIEnv *env, jobject descrambler, jint pidType, jint pid, jobject filter) {
887 sp<IDescrambler> descramblerSp = getDescrambler(env, descrambler);
888 if (descramblerSp == NULL) {
889 return false;
890 }
shubang7648a3c2019-11-25 18:16:45 -0800891 sp<IFilter> filterSp = getFilter(env, filter)->getIFilter();
shubang13f15e02019-11-04 17:51:02 -0800892 Result result = descramblerSp->removePid(getDemuxPid((int)pidType, (int)pid), filterSp);
shubang99c89922019-12-17 17:33:15 -0800893 return (int)result;
894}
895
896static int android_media_tv_Tuner_set_key_token(JNIEnv, jobject, jbyteArray) {
897 return 0;
898}
899
900static int android_media_tv_Tuner_close_descrambler(JNIEnv, jobject) {
901 return 0;
shubang13f15e02019-11-04 17:51:02 -0800902}
903
shubangd351b822020-01-22 17:29:18 -0800904static jobject android_media_tv_Tuner_open_dvr_recorder(
905 JNIEnv* /* env */, jobject /* thiz */, jlong /* bufferSize */) {
906 return NULL;
907}
908
909static jobject android_media_tv_Tuner_open_dvr_playback(
910 JNIEnv* /* env */, jobject /* thiz */, jlong /* bufferSize */) {
911 return NULL;
shubang4a0eddf2019-11-08 17:10:18 -0800912}
913
shubang34258932019-12-27 13:59:23 -0800914static jobject android_media_tv_Tuner_get_demux_caps(JNIEnv*, jobject) {
915 return NULL;
916}
917
shubang793e5702019-12-26 15:15:46 -0800918static int android_media_tv_Tuner_attach_filter(JNIEnv *env, jobject dvr, jobject filter) {
shubang9e700ff2019-12-04 16:26:51 -0800919 sp<IDvr> dvrSp = getDvr(env, dvr)->getIDvr();
shubang7648a3c2019-11-25 18:16:45 -0800920 sp<IFilter> filterSp = getFilter(env, filter)->getIFilter();
shubang4a0eddf2019-11-08 17:10:18 -0800921 if (dvrSp == NULL || filterSp == NULL) {
922 return false;
923 }
924 Result result = dvrSp->attachFilter(filterSp);
shubang793e5702019-12-26 15:15:46 -0800925 return (int) result;
shubang4a0eddf2019-11-08 17:10:18 -0800926}
927
shubang793e5702019-12-26 15:15:46 -0800928static int android_media_tv_Tuner_detach_filter(JNIEnv *env, jobject dvr, jobject filter) {
shubang9e700ff2019-12-04 16:26:51 -0800929 sp<IDvr> dvrSp = getDvr(env, dvr)->getIDvr();
shubang7648a3c2019-11-25 18:16:45 -0800930 sp<IFilter> filterSp = getFilter(env, filter)->getIFilter();
shubang4a0eddf2019-11-08 17:10:18 -0800931 if (dvrSp == NULL || filterSp == NULL) {
932 return false;
933 }
934 Result result = dvrSp->detachFilter(filterSp);
shubang793e5702019-12-26 15:15:46 -0800935 return (int) result;
shubang4a0eddf2019-11-08 17:10:18 -0800936}
937
shubang030afb52019-11-27 16:09:02 -0800938static int android_media_tv_Tuner_configure_dvr(JNIEnv *env, jobject dvr, jobject settings) {
shubangba21a7f2019-12-05 16:58:55 -0800939 sp<Dvr> dvrSp = getDvr(env, dvr);
940 sp<IDvr> iDvrSp = dvrSp->getIDvr();
shubang030afb52019-11-27 16:09:02 -0800941 if (dvrSp == NULL) {
942 ALOGD("Failed to configure dvr: dvr not found");
943 return (int)Result::INVALID_STATE;
944 }
shubangba21a7f2019-12-05 16:58:55 -0800945 Result result = iDvrSp->configure(getDvrSettings(env, settings));
946 MQDescriptorSync<uint8_t> dvrMQDesc;
947 if (result == Result::SUCCESS) {
948 Result getQueueDescResult = Result::UNKNOWN_ERROR;
949 iDvrSp->getQueueDesc(
950 [&](Result r, const MQDescriptorSync<uint8_t>& desc) {
951 dvrMQDesc = desc;
952 getQueueDescResult = r;
953 ALOGD("getDvrQueueDesc");
954 });
955 if (getQueueDescResult == Result::SUCCESS) {
956 dvrSp->mDvrMQ = std::make_unique<DvrMQ>(dvrMQDesc, true);
957 EventFlag::createEventFlag(
958 dvrSp->mDvrMQ->getEventFlagWord(), &(dvrSp->mDvrMQEventFlag));
959 }
960 }
shubang030afb52019-11-27 16:09:02 -0800961 return (int)result;
962}
963
shubang793e5702019-12-26 15:15:46 -0800964static int android_media_tv_Tuner_start_dvr(JNIEnv *env, jobject dvr) {
shubang9e700ff2019-12-04 16:26:51 -0800965 sp<IDvr> dvrSp = getDvr(env, dvr)->getIDvr();
shubang4a0eddf2019-11-08 17:10:18 -0800966 if (dvrSp == NULL) {
967 ALOGD("Failed to start dvr: dvr not found");
968 return false;
969 }
shubang793e5702019-12-26 15:15:46 -0800970 Result result = dvrSp->start();
971 return (int) result;
shubang4a0eddf2019-11-08 17:10:18 -0800972}
973
shubang793e5702019-12-26 15:15:46 -0800974static int android_media_tv_Tuner_stop_dvr(JNIEnv *env, jobject dvr) {
shubang9e700ff2019-12-04 16:26:51 -0800975 sp<IDvr> dvrSp = getDvr(env, dvr)->getIDvr();
shubang4a0eddf2019-11-08 17:10:18 -0800976 if (dvrSp == NULL) {
977 ALOGD("Failed to stop dvr: dvr not found");
978 return false;
979 }
shubang793e5702019-12-26 15:15:46 -0800980 Result result = dvrSp->stop();
981 return (int) result;
shubang4a0eddf2019-11-08 17:10:18 -0800982}
983
shubang793e5702019-12-26 15:15:46 -0800984static int android_media_tv_Tuner_flush_dvr(JNIEnv *env, jobject dvr) {
shubang9e700ff2019-12-04 16:26:51 -0800985 sp<IDvr> dvrSp = getDvr(env, dvr)->getIDvr();
shubang4a0eddf2019-11-08 17:10:18 -0800986 if (dvrSp == NULL) {
987 ALOGD("Failed to flush dvr: dvr not found");
988 return false;
989 }
shubang793e5702019-12-26 15:15:46 -0800990 Result result = dvrSp->flush();
991 return (int) result;
992}
993
994static int android_media_tv_Tuner_close_dvr(JNIEnv*, jobject) {
995 return 0;
shubang4a0eddf2019-11-08 17:10:18 -0800996}
997
shubang847fc0a2019-12-26 16:54:10 -0800998static int android_media_tv_Tuner_lnb_set_voltage(JNIEnv*, jobject, jint) {
999 return 0;
1000}
1001
1002static int android_media_tv_Tuner_lnb_set_tone(JNIEnv*, jobject, jint) {
1003 return 0;
1004}
1005
1006static int android_media_tv_Tuner_lnb_set_position(JNIEnv*, jobject, jint) {
1007 return 0;
1008}
1009
1010static int android_media_tv_Tuner_lnb_send_diseqc_msg(JNIEnv*, jobject, jbyteArray) {
1011 return 0;
1012}
1013
1014static int android_media_tv_Tuner_close_lnb(JNIEnv*, jobject) {
1015 return 0;
1016}
1017
shubangba21a7f2019-12-05 16:58:55 -08001018static void android_media_tv_Tuner_dvr_set_fd(JNIEnv *env, jobject dvr, jobject jfd) {
1019 sp<Dvr> dvrSp = getDvr(env, dvr);
1020 if (dvrSp == NULL) {
1021 ALOGD("Failed to set FD for dvr: dvr not found");
1022 }
1023 dvrSp->mFd = jniGetFDFromFileDescriptor(env, jfd);
1024 ALOGD("set fd = %d", dvrSp->mFd);
1025}
1026
shubangd351b822020-01-22 17:29:18 -08001027static jlong android_media_tv_Tuner_read_dvr(JNIEnv *env, jobject dvr, jlong size) {
shubangba21a7f2019-12-05 16:58:55 -08001028 sp<Dvr> dvrSp = getDvr(env, dvr);
1029 if (dvrSp == NULL) {
1030 ALOGD("Failed to read dvr: dvr not found");
1031 }
1032
shubangd351b822020-01-22 17:29:18 -08001033 long available = dvrSp->mDvrMQ->availableToWrite();
1034 long write = std::min((long) size, available);
shubangba21a7f2019-12-05 16:58:55 -08001035
1036 DvrMQ::MemTransaction tx;
shubangd351b822020-01-22 17:29:18 -08001037 long ret = 0;
shubangba21a7f2019-12-05 16:58:55 -08001038 if (dvrSp->mDvrMQ->beginWrite(write, &tx)) {
1039 auto first = tx.getFirstRegion();
1040 auto data = first.getAddress();
shubangd351b822020-01-22 17:29:18 -08001041 long length = first.getLength();
1042 long firstToWrite = std::min(length, write);
shubangba21a7f2019-12-05 16:58:55 -08001043 ret = read(dvrSp->mFd, data, firstToWrite);
1044 if (ret < firstToWrite) {
shubangd351b822020-01-22 17:29:18 -08001045 ALOGW("[DVR] file to MQ, first region: %ld bytes to write, but %ld bytes written",
shubangba21a7f2019-12-05 16:58:55 -08001046 firstToWrite, ret);
1047 } else if (firstToWrite < write) {
shubangd351b822020-01-22 17:29:18 -08001048 ALOGD("[DVR] write second region: %ld bytes written, %ld bytes in total", ret, write);
shubangba21a7f2019-12-05 16:58:55 -08001049 auto second = tx.getSecondRegion();
1050 data = second.getAddress();
1051 length = second.getLength();
1052 int secondToWrite = std::min(length, write - firstToWrite);
1053 ret += read(dvrSp->mFd, data, secondToWrite);
1054 }
shubangd351b822020-01-22 17:29:18 -08001055 ALOGD("[DVR] file to MQ: %ld bytes need to be written, %ld bytes written", write, ret);
shubangba21a7f2019-12-05 16:58:55 -08001056 if (!dvrSp->mDvrMQ->commitWrite(ret)) {
1057 ALOGE("[DVR] Error: failed to commit write!");
1058 }
1059
1060 } else {
1061 ALOGE("dvrMq.beginWrite failed");
1062 }
shubangd351b822020-01-22 17:29:18 -08001063 return (jlong) ret;
shubangba21a7f2019-12-05 16:58:55 -08001064}
1065
shubangd351b822020-01-22 17:29:18 -08001066static jlong android_media_tv_Tuner_read_dvr_from_array(
1067 JNIEnv /* *env */, jobject /* dvr */, jbyteArray /* bytes */, jlong /* offset */,
1068 jlong /* size */) {
shubangba21a7f2019-12-05 16:58:55 -08001069 //TODO: impl
1070 return 0;
1071}
1072
shubangd351b822020-01-22 17:29:18 -08001073static jlong android_media_tv_Tuner_write_dvr(JNIEnv *env, jobject dvr, jlong size) {
shubang5f4ea352019-12-09 15:12:10 -08001074 sp<Dvr> dvrSp = getDvr(env, dvr);
1075 if (dvrSp == NULL) {
1076 ALOGW("Failed to write dvr: dvr not found");
1077 return 0;
1078 }
1079
1080 if (dvrSp->mDvrMQ == NULL) {
1081 ALOGW("Failed to write dvr: dvr not configured");
1082 return 0;
1083 }
1084
1085 DvrMQ& dvrMq = dvrSp->getDvrMQ();
1086
shubangd351b822020-01-22 17:29:18 -08001087 long available = dvrMq.availableToRead();
1088 long toRead = std::min((long) size, available);
shubang5f4ea352019-12-09 15:12:10 -08001089
shubangd351b822020-01-22 17:29:18 -08001090 long ret = 0;
shubang5f4ea352019-12-09 15:12:10 -08001091 DvrMQ::MemTransaction tx;
1092 if (dvrMq.beginRead(toRead, &tx)) {
1093 auto first = tx.getFirstRegion();
1094 auto data = first.getAddress();
shubangd351b822020-01-22 17:29:18 -08001095 long length = first.getLength();
1096 long firstToRead = std::min(length, toRead);
shubang5f4ea352019-12-09 15:12:10 -08001097 ret = write(dvrSp->mFd, data, firstToRead);
1098 if (ret < firstToRead) {
shubangd351b822020-01-22 17:29:18 -08001099 ALOGW("[DVR] MQ to file: %ld bytes read, but %ld bytes written", firstToRead, ret);
shubang5f4ea352019-12-09 15:12:10 -08001100 } else if (firstToRead < toRead) {
shubangd351b822020-01-22 17:29:18 -08001101 ALOGD("[DVR] read second region: %ld bytes read, %ld bytes in total", ret, toRead);
shubang5f4ea352019-12-09 15:12:10 -08001102 auto second = tx.getSecondRegion();
1103 data = second.getAddress();
1104 length = second.getLength();
1105 int secondToRead = toRead - firstToRead;
1106 ret += write(dvrSp->mFd, data, secondToRead);
1107 }
shubangd351b822020-01-22 17:29:18 -08001108 ALOGD("[DVR] MQ to file: %ld bytes to be read, %ld bytes written", toRead, ret);
shubang5f4ea352019-12-09 15:12:10 -08001109 if (!dvrMq.commitRead(ret)) {
1110 ALOGE("[DVR] Error: failed to commit read!");
1111 }
1112
1113 } else {
1114 ALOGE("dvrMq.beginRead failed");
1115 }
1116
shubangd351b822020-01-22 17:29:18 -08001117 return (jlong) ret;
shubang5f4ea352019-12-09 15:12:10 -08001118}
1119
shubangd351b822020-01-22 17:29:18 -08001120static jlong android_media_tv_Tuner_write_dvr_to_array(
1121 JNIEnv /* *env */, jobject /* dvr */, jbyteArray /* bytes */, jlong /* offset */,
1122 jlong /* size */) {
shubang5f4ea352019-12-09 15:12:10 -08001123 //TODO: impl
1124 return 0;
1125}
shubangba21a7f2019-12-05 16:58:55 -08001126
shubangd0977902019-11-07 18:58:43 -08001127static const JNINativeMethod gTunerMethods[] = {
shubang8ab43b12019-10-18 15:55:55 -07001128 { "nativeInit", "()V", (void *)android_media_tv_Tuner_native_init },
1129 { "nativeSetup", "()V", (void *)android_media_tv_Tuner_native_setup },
shubang7e849b02019-10-18 19:36:25 -07001130 { "nativeGetFrontendIds", "()Ljava/util/List;",
1131 (void *)android_media_tv_Tuner_get_frontend_ids },
1132 { "nativeOpenFrontendById", "(I)Landroid/media/tv/tuner/Tuner$Frontend;",
1133 (void *)android_media_tv_Tuner_open_frontend_by_id },
shubangd351b822020-01-22 17:29:18 -08001134 { "nativeTune", "(ILandroid/media/tv/tuner/frontend/FrontendSettings;)I",
shubang74bfd482019-10-29 19:10:22 -07001135 (void *)android_media_tv_Tuner_tune },
shubange65b6862019-12-17 15:43:35 -08001136 { "nativeStopTune", "()I", (void *)android_media_tv_Tuner_stop_tune },
shubangd351b822020-01-22 17:29:18 -08001137 { "nativeScan", "(ILandroid/media/tv/tuner/frontend/FrontendSettings;I)I",
shubangd5b845f2019-12-11 15:29:09 -08001138 (void *)android_media_tv_Tuner_scan },
shubang793e5702019-12-26 15:15:46 -08001139 { "nativeStopScan", "()I", (void *)android_media_tv_Tuner_stop_scan },
shubange65b6862019-12-17 15:43:35 -08001140 { "nativeSetLnb", "(I)I", (void *)android_media_tv_Tuner_set_lnb },
1141 { "nativeSetLna", "(Z)I", (void *)android_media_tv_Tuner_set_lna },
shubangd351b822020-01-22 17:29:18 -08001142 { "nativeGetFrontendStatus", "([I)Landroid/media/tv/tuner/frontend/FrontendStatus;",
shubang1512ec12019-12-23 18:22:42 -08001143 (void *)android_media_tv_Tuner_get_frontend_status },
shubangd351b822020-01-22 17:29:18 -08001144 { "nativeGetAvSyncHwId", "(Landroid/media/tv/tuner/Tuner/filter/Filter;)I",
shubang7343fee2019-12-27 12:02:08 -08001145 (void *)android_media_tv_Tuner_gat_av_sync_hw_id },
1146 { "nativeGetAvSyncTime", "(I)J", (void *)android_media_tv_Tuner_gat_av_sync_time },
1147 { "nativeConnectCiCam", "(I)I", (void *)android_media_tv_Tuner_connect_cicam },
1148 { "nativeDisconnectCiCam", "()I", (void *)android_media_tv_Tuner_disconnect_cicam },
shubangd351b822020-01-22 17:29:18 -08001149 { "nativeGetFrontendInfo", "(I)Landroid/media/tv/tuner/FrontendInfo;",
shubang95c1f752019-12-27 16:29:48 -08001150 (void *)android_media_tv_Tuner_get_frontend_info },
shubangd351b822020-01-22 17:29:18 -08001151 { "nativeOpenFilter", "(IIJ)Landroid/media/tv/tuner/Tuner/filter/Filter;",
shubang6f473d62019-11-01 15:42:21 -07001152 (void *)android_media_tv_Tuner_open_filter },
shubangd351b822020-01-22 17:29:18 -08001153 { "nativeOpenTimeFilter", "()Landroid/media/tv/tuner/Tuner/filter/TimeFilter;",
shubang4347e2e2019-12-13 17:20:40 -08001154 (void *)android_media_tv_Tuner_open_time_filter },
shubang760f0312019-11-12 17:11:28 -08001155 { "nativeGetLnbIds", "()Ljava/util/List;",
1156 (void *)android_media_tv_Tuner_get_lnb_ids },
shubangd351b822020-01-22 17:29:18 -08001157 { "nativeOpenLnbById", "(I)Landroid/media/tv/tuner/Lnb;",
shubang760f0312019-11-12 17:11:28 -08001158 (void *)android_media_tv_Tuner_open_lnb_by_id },
shubangd351b822020-01-22 17:29:18 -08001159 { "nativeOpenDescrambler", "()Landroid/media/tv/tuner/Descrambler;",
shubang13f15e02019-11-04 17:51:02 -08001160 (void *)android_media_tv_Tuner_open_descrambler },
shubangd351b822020-01-22 17:29:18 -08001161 { "nativeOpenDvrRecorder", "(J)Landroid/media/tv/tuner/dvr/DvrRecorder;",
1162 (void *)android_media_tv_Tuner_open_dvr_recorder },
1163 { "nativeOpenDvrPlayback", "(J)Landroid/media/tv/tuner/dvr/DvrPlayback;",
1164 (void *)android_media_tv_Tuner_open_dvr_playback },
shubang34258932019-12-27 13:59:23 -08001165 { "nativeGetDemuxCapabilities", "()Landroid/media/tv/tuner/DemuxCapabilities;",
1166 (void *)android_media_tv_Tuner_get_demux_caps },
shubang8ab43b12019-10-18 15:55:55 -07001167};
1168
shubangd0977902019-11-07 18:58:43 -08001169static const JNINativeMethod gFilterMethods[] = {
shubangd351b822020-01-22 17:29:18 -08001170 { "nativeConfigureFilter", "(IILandroid/media/tv/tuner/filter/FilterConfiguration;)I",
shubang75c87082019-11-15 11:26:56 -08001171 (void *)android_media_tv_Tuner_configure_filter },
shubang793e5702019-12-26 15:15:46 -08001172 { "nativeGetId", "()I", (void *)android_media_tv_Tuner_get_filter_id },
shubangd351b822020-01-22 17:29:18 -08001173 { "nativeSetDataSource", "(Landroid/media/tv/tuner/filter/Filter;)I",
shubang793e5702019-12-26 15:15:46 -08001174 (void *)android_media_tv_Tuner_set_filter_data_source },
1175 { "nativeStartFilter", "()I", (void *)android_media_tv_Tuner_start_filter },
1176 { "nativeStopFilter", "()I", (void *)android_media_tv_Tuner_stop_filter },
1177 { "nativeFlushFilter", "()I", (void *)android_media_tv_Tuner_flush_filter },
shubangd351b822020-01-22 17:29:18 -08001178 { "nativeRead", "([BJJ)I", (void *)android_media_tv_Tuner_read_filter_fmq },
Amy1b301f42020-01-02 11:07:56 -08001179 { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_filter },
shubangd0977902019-11-07 18:58:43 -08001180};
1181
shubang4347e2e2019-12-13 17:20:40 -08001182static const JNINativeMethod gTimeFilterMethods[] = {
1183 { "nativeSetTimeStamp", "(J)I", (void *)android_media_tv_Tuner_time_filter_set_timestamp },
1184 { "nativeClearTimeStamp", "()I", (void *)android_media_tv_Tuner_time_filter_clear_timestamp },
1185 { "nativeGetTimeStamp", "()Ljava/lang/Long;",
1186 (void *)android_media_tv_Tuner_time_filter_get_timestamp },
1187 { "nativeGetSourceTime", "()Ljava/lang/Long;",
1188 (void *)android_media_tv_Tuner_time_filter_get_source_time },
1189 { "nativeClose", "()I", (void *)android_media_tv_Tuner_time_filter_close },
1190};
1191
shubang13f15e02019-11-04 17:51:02 -08001192static const JNINativeMethod gDescramblerMethods[] = {
shubangd351b822020-01-22 17:29:18 -08001193 { "nativeAddPid", "(IILandroid/media/tv/tuner/filter/Filter;)I",
shubang13f15e02019-11-04 17:51:02 -08001194 (void *)android_media_tv_Tuner_add_pid },
shubangd351b822020-01-22 17:29:18 -08001195 { "nativeRemovePid", "(IILandroid/media/tv/tuner/filter/Filter;)I",
shubang13f15e02019-11-04 17:51:02 -08001196 (void *)android_media_tv_Tuner_remove_pid },
shubang99c89922019-12-17 17:33:15 -08001197 { "nativeSetKeyToken", "([B)I", (void *)android_media_tv_Tuner_set_key_token },
Amy1b301f42020-01-02 11:07:56 -08001198 { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_descrambler },
shubang13f15e02019-11-04 17:51:02 -08001199};
1200
shubang4a0eddf2019-11-08 17:10:18 -08001201static const JNINativeMethod gDvrMethods[] = {
shubangd351b822020-01-22 17:29:18 -08001202 { "nativeAttachFilter", "(Landroid/media/tv/tuner/filter/Filter;)I",
shubang4a0eddf2019-11-08 17:10:18 -08001203 (void *)android_media_tv_Tuner_attach_filter },
shubangd351b822020-01-22 17:29:18 -08001204 { "nativeDetachFilter", "(Landroid/media/tv/tuner/filter/Filter;)I",
shubang4a0eddf2019-11-08 17:10:18 -08001205 (void *)android_media_tv_Tuner_detach_filter },
shubangd351b822020-01-22 17:29:18 -08001206 { "nativeConfigureDvr", "(Landroid/media/tv/tuner/dvr/DvrSettings;)I",
shubang030afb52019-11-27 16:09:02 -08001207 (void *)android_media_tv_Tuner_configure_dvr },
shubang793e5702019-12-26 15:15:46 -08001208 { "nativeStartDvr", "()I", (void *)android_media_tv_Tuner_start_dvr },
1209 { "nativeStopDvr", "()I", (void *)android_media_tv_Tuner_stop_dvr },
1210 { "nativeFlushDvr", "()I", (void *)android_media_tv_Tuner_flush_dvr },
1211 { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_dvr },
shubangd351b822020-01-22 17:29:18 -08001212 { "nativeSetFileDescriptor", "(I)V", (void *)android_media_tv_Tuner_dvr_set_fd },
1213};
1214
1215static const JNINativeMethod gDvrRecorderMethods[] = {
1216 { "nativeWrite", "(J)J", (void *)android_media_tv_Tuner_write_dvr },
1217 { "nativeWrite", "([BJJ)J", (void *)android_media_tv_Tuner_write_dvr_to_array },
1218};
1219
1220static const JNINativeMethod gDvrPlaybackMethods[] = {
1221 { "nativeRead", "(J)J", (void *)android_media_tv_Tuner_read_dvr },
1222 { "nativeRead", "([BJJ)J", (void *)android_media_tv_Tuner_read_dvr_from_array },
shubang4a0eddf2019-11-08 17:10:18 -08001223};
1224
shubang847fc0a2019-12-26 16:54:10 -08001225static const JNINativeMethod gLnbMethods[] = {
1226 { "nativeSetVoltage", "(I)I", (void *)android_media_tv_Tuner_lnb_set_voltage },
1227 { "nativeSetTone", "(I)I", (void *)android_media_tv_Tuner_lnb_set_tone },
1228 { "nativeSetSatellitePosition", "(I)I", (void *)android_media_tv_Tuner_lnb_set_position },
1229 { "nativeSendDiseqcMessage", "([B)I", (void *)android_media_tv_Tuner_lnb_send_diseqc_msg },
1230 { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_lnb },
1231};
1232
shubangd0977902019-11-07 18:58:43 -08001233static bool register_android_media_tv_Tuner(JNIEnv *env) {
1234 if (AndroidRuntime::registerNativeMethods(
1235 env, "android/media/tv/tuner/Tuner", gTunerMethods, NELEM(gTunerMethods)) != JNI_OK) {
1236 ALOGE("Failed to register tuner native methods");
1237 return false;
1238 }
1239 if (AndroidRuntime::registerNativeMethods(
shubangd351b822020-01-22 17:29:18 -08001240 env, "android/media/tv/tuner/filter/Filter",
shubangd0977902019-11-07 18:58:43 -08001241 gFilterMethods,
1242 NELEM(gFilterMethods)) != JNI_OK) {
1243 ALOGE("Failed to register filter native methods");
1244 return false;
1245 }
shubang13f15e02019-11-04 17:51:02 -08001246 if (AndroidRuntime::registerNativeMethods(
shubangd351b822020-01-22 17:29:18 -08001247 env, "android/media/tv/tuner/filter/TimeFilter",
shubang4347e2e2019-12-13 17:20:40 -08001248 gTimeFilterMethods,
1249 NELEM(gTimeFilterMethods)) != JNI_OK) {
1250 ALOGE("Failed to register time filter native methods");
1251 return false;
1252 }
1253 if (AndroidRuntime::registerNativeMethods(
shubangd351b822020-01-22 17:29:18 -08001254 env, "android/media/tv/tuner/Descrambler",
shubang13f15e02019-11-04 17:51:02 -08001255 gDescramblerMethods,
1256 NELEM(gDescramblerMethods)) != JNI_OK) {
1257 ALOGE("Failed to register descrambler native methods");
1258 return false;
1259 }
shubang4a0eddf2019-11-08 17:10:18 -08001260 if (AndroidRuntime::registerNativeMethods(
shubangd351b822020-01-22 17:29:18 -08001261 env, "android/media/tv/tuner/dvr/Dvr",
shubang4a0eddf2019-11-08 17:10:18 -08001262 gDvrMethods,
1263 NELEM(gDvrMethods)) != JNI_OK) {
1264 ALOGE("Failed to register dvr native methods");
1265 return false;
1266 }
shubang847fc0a2019-12-26 16:54:10 -08001267 if (AndroidRuntime::registerNativeMethods(
shubangd351b822020-01-22 17:29:18 -08001268 env, "android/media/tv/tuner/dvr/DvrRecorder",
1269 gDvrRecorderMethods,
1270 NELEM(gDvrRecorderMethods)) != JNI_OK) {
1271 ALOGE("Failed to register dvr recorder native methods");
1272 return false;
1273 }
1274 if (AndroidRuntime::registerNativeMethods(
1275 env, "android/media/tv/tuner/dvr/DvrPlayback",
1276 gDvrPlaybackMethods,
1277 NELEM(gDvrPlaybackMethods)) != JNI_OK) {
1278 ALOGE("Failed to register dvr playback native methods");
1279 return false;
1280 }
1281 if (AndroidRuntime::registerNativeMethods(
1282 env, "android/media/tv/tuner/Lnb",
shubang847fc0a2019-12-26 16:54:10 -08001283 gLnbMethods,
1284 NELEM(gLnbMethods)) != JNI_OK) {
1285 ALOGE("Failed to register lnb native methods");
1286 return false;
1287 }
shubangd0977902019-11-07 18:58:43 -08001288 return true;
shubang8ab43b12019-10-18 15:55:55 -07001289}
1290
1291jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
1292{
1293 JNIEnv* env = NULL;
1294 jint result = -1;
1295
1296 if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
1297 ALOGE("ERROR: GetEnv failed\n");
1298 return result;
1299 }
1300 assert(env != NULL);
1301
shubangd0977902019-11-07 18:58:43 -08001302 if (!register_android_media_tv_Tuner(env)) {
shubang8ab43b12019-10-18 15:55:55 -07001303 ALOGE("ERROR: Tuner native registration failed\n");
1304 return result;
1305 }
1306 return JNI_VERSION_1_4;
1307}