blob: ab311c0e245ac4143ec987a7cdc4c1eda0a90b76 [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
shubangd49681e2020-02-17 21:32:30 -080020#include "android_media_MediaCodecLinearBlock.h"
shubang8ab43b12019-10-18 15:55:55 -070021#include "android_media_tv_Tuner.h"
22#include "android_runtime/AndroidRuntime.h"
23
shubangd49681e2020-02-17 21:32:30 -080024#include <C2BlockInternal.h>
25#include <C2HandleIonInternal.h>
shubang8ab43b12019-10-18 15:55:55 -070026#include <android/hardware/tv/tuner/1.0/ITuner.h>
27#include <media/stagefright/foundation/ADebug.h>
shubangba21a7f2019-12-05 16:58:55 -080028#include <nativehelper/JNIHelp.h>
shubangd49681e2020-02-17 21:32:30 -080029#include <nativehelper/ScopedLocalRef.h>
30#include <utils/NativeHandle.h>
shubang8ab43b12019-10-18 15:55:55 -070031
32#pragma GCC diagnostic ignored "-Wunused-function"
33
shubang6f473d62019-11-01 15:42:21 -070034using ::android::hardware::Void;
shubang44fa1422020-01-30 11:42:59 -080035using ::android::hardware::hidl_bitfield;
shubang7e849b02019-10-18 19:36:25 -070036using ::android::hardware::hidl_vec;
shubang3e0c37b2020-02-19 19:09:10 -080037using ::android::hardware::tv::tuner::V1_0::AudioExtraMetaData;
38using ::android::hardware::tv::tuner::V1_0::Constant;
shubang030afb52019-11-27 16:09:02 -080039using ::android::hardware::tv::tuner::V1_0::DataFormat;
shubang44fa1422020-01-30 11:42:59 -080040using ::android::hardware::tv::tuner::V1_0::DemuxAlpFilterSettings;
41using ::android::hardware::tv::tuner::V1_0::DemuxAlpFilterType;
shubang87788c32020-02-04 13:55:23 -080042using ::android::hardware::tv::tuner::V1_0::DemuxAlpLengthType;
shubangc4b45702020-03-23 18:48:12 -070043using ::android::hardware::tv::tuner::V1_0::DemuxCapabilities;
shubang44fa1422020-01-30 11:42:59 -080044using ::android::hardware::tv::tuner::V1_0::DemuxFilterAvSettings;
shubang3e0c37b2020-02-19 19:09:10 -080045using ::android::hardware::tv::tuner::V1_0::DemuxFilterDownloadEvent;
shubang44fa1422020-01-30 11:42:59 -080046using ::android::hardware::tv::tuner::V1_0::DemuxFilterDownloadSettings;
shubang3e0c37b2020-02-19 19:09:10 -080047using ::android::hardware::tv::tuner::V1_0::DemuxFilterIpPayloadEvent;
shubang6f473d62019-11-01 15:42:21 -070048using ::android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
shubangd49681e2020-02-17 21:32:30 -080049using ::android::hardware::tv::tuner::V1_0::DemuxFilterMediaEvent;
shubang3e0c37b2020-02-19 19:09:10 -080050using ::android::hardware::tv::tuner::V1_0::DemuxFilterMmtpRecordEvent;
shubang75c87082019-11-15 11:26:56 -080051using ::android::hardware::tv::tuner::V1_0::DemuxFilterPesDataSettings;
shubang3e0c37b2020-02-19 19:09:10 -080052using ::android::hardware::tv::tuner::V1_0::DemuxFilterPesEvent;
shubang44fa1422020-01-30 11:42:59 -080053using ::android::hardware::tv::tuner::V1_0::DemuxFilterRecordSettings;
54using ::android::hardware::tv::tuner::V1_0::DemuxFilterSectionBits;
shubang3e0c37b2020-02-19 19:09:10 -080055using ::android::hardware::tv::tuner::V1_0::DemuxFilterSectionEvent;
shubang44fa1422020-01-30 11:42:59 -080056using ::android::hardware::tv::tuner::V1_0::DemuxFilterSectionSettings;
shubang75c87082019-11-15 11:26:56 -080057using ::android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
shubang3e0c37b2020-02-19 19:09:10 -080058using ::android::hardware::tv::tuner::V1_0::DemuxFilterTemiEvent;
59using ::android::hardware::tv::tuner::V1_0::DemuxFilterTsRecordEvent;
shubang87788c32020-02-04 13:55:23 -080060using ::android::hardware::tv::tuner::V1_0::DemuxIpAddress;
shubang44fa1422020-01-30 11:42:59 -080061using ::android::hardware::tv::tuner::V1_0::DemuxIpFilterSettings;
62using ::android::hardware::tv::tuner::V1_0::DemuxIpFilterType;
63using ::android::hardware::tv::tuner::V1_0::DemuxMmtpFilterSettings;
64using ::android::hardware::tv::tuner::V1_0::DemuxMmtpFilterType;
shubang13f15e02019-11-04 17:51:02 -080065using ::android::hardware::tv::tuner::V1_0::DemuxMmtpPid;
shubang964e6132019-11-26 15:05:22 -080066using ::android::hardware::tv::tuner::V1_0::DemuxQueueNotifyBits;
shubang44fa1422020-01-30 11:42:59 -080067using ::android::hardware::tv::tuner::V1_0::DemuxRecordScIndexType;
68using ::android::hardware::tv::tuner::V1_0::DemuxScHevcIndex;
69using ::android::hardware::tv::tuner::V1_0::DemuxScIndex;
70using ::android::hardware::tv::tuner::V1_0::DemuxTlvFilterSettings;
71using ::android::hardware::tv::tuner::V1_0::DemuxTlvFilterType;
shubang13f15e02019-11-04 17:51:02 -080072using ::android::hardware::tv::tuner::V1_0::DemuxTpid;
shubang75c87082019-11-15 11:26:56 -080073using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterSettings;
shubang6f473d62019-11-01 15:42:21 -070074using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
shubang44fa1422020-01-30 11:42:59 -080075using ::android::hardware::tv::tuner::V1_0::DemuxTsIndex;
shubang030afb52019-11-27 16:09:02 -080076using ::android::hardware::tv::tuner::V1_0::DvrSettings;
shubang74bfd482019-10-29 19:10:22 -070077using ::android::hardware::tv::tuner::V1_0::FrontendAnalogSettings;
78using ::android::hardware::tv::tuner::V1_0::FrontendAnalogSifStandard;
79using ::android::hardware::tv::tuner::V1_0::FrontendAnalogType;
shubangdeb067c2020-01-27 13:21:55 -080080using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3Bandwidth;
81using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3CodeRate;
82using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3DemodOutputFormat;
83using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3Fec;
84using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3Modulation;
85using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3PlpSettings;
86using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3Settings;
87using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3TimeInterleaveMode;
88using ::android::hardware::tv::tuner::V1_0::FrontendAtscSettings;
89using ::android::hardware::tv::tuner::V1_0::FrontendAtscModulation;
90using ::android::hardware::tv::tuner::V1_0::FrontendDvbcAnnex;
91using ::android::hardware::tv::tuner::V1_0::FrontendDvbcModulation;
92using ::android::hardware::tv::tuner::V1_0::FrontendDvbcOuterFec;
93using ::android::hardware::tv::tuner::V1_0::FrontendDvbcSettings;
94using ::android::hardware::tv::tuner::V1_0::FrontendDvbcSpectralInversion;
95using ::android::hardware::tv::tuner::V1_0::FrontendDvbsCodeRate;
96using ::android::hardware::tv::tuner::V1_0::FrontendDvbsModulation;
97using ::android::hardware::tv::tuner::V1_0::FrontendDvbsPilot;
98using ::android::hardware::tv::tuner::V1_0::FrontendDvbsRolloff;
99using ::android::hardware::tv::tuner::V1_0::FrontendDvbsSettings;
100using ::android::hardware::tv::tuner::V1_0::FrontendDvbsStandard;
101using ::android::hardware::tv::tuner::V1_0::FrontendDvbsVcmMode;
102using ::android::hardware::tv::tuner::V1_0::FrontendDvbtBandwidth;
103using ::android::hardware::tv::tuner::V1_0::FrontendDvbtCoderate;
104using ::android::hardware::tv::tuner::V1_0::FrontendDvbtConstellation;
105using ::android::hardware::tv::tuner::V1_0::FrontendDvbtGuardInterval;
106using ::android::hardware::tv::tuner::V1_0::FrontendDvbtHierarchy;
107using ::android::hardware::tv::tuner::V1_0::FrontendDvbtPlpMode;
108using ::android::hardware::tv::tuner::V1_0::FrontendDvbtSettings;
109using ::android::hardware::tv::tuner::V1_0::FrontendDvbtStandard;
110using ::android::hardware::tv::tuner::V1_0::FrontendDvbtTransmissionMode;
111using ::android::hardware::tv::tuner::V1_0::FrontendInnerFec;
112using ::android::hardware::tv::tuner::V1_0::FrontendIsdbs3Coderate;
113using ::android::hardware::tv::tuner::V1_0::FrontendIsdbs3Modulation;
114using ::android::hardware::tv::tuner::V1_0::FrontendIsdbs3Rolloff;
115using ::android::hardware::tv::tuner::V1_0::FrontendIsdbs3Settings;
116using ::android::hardware::tv::tuner::V1_0::FrontendIsdbsCoderate;
117using ::android::hardware::tv::tuner::V1_0::FrontendIsdbsModulation;
118using ::android::hardware::tv::tuner::V1_0::FrontendIsdbsRolloff;
119using ::android::hardware::tv::tuner::V1_0::FrontendIsdbsSettings;
120using ::android::hardware::tv::tuner::V1_0::FrontendIsdbsStreamIdType;
121using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtBandwidth;
122using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtCoderate;
123using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtGuardInterval;
124using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtMode;
125using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtModulation;
126using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtSettings;
shubangb83f8232020-03-24 18:04:35 -0700127using ::android::hardware::tv::tuner::V1_0::FrontendModulationStatus;
shubangc8736b72020-02-11 18:27:53 -0800128using ::android::hardware::tv::tuner::V1_0::FrontendScanAtsc3PlpInfo;
shubangb83f8232020-03-24 18:04:35 -0700129using ::android::hardware::tv::tuner::V1_0::FrontendStatus;
130using ::android::hardware::tv::tuner::V1_0::FrontendStatusAtsc3PlpInfo;
131using ::android::hardware::tv::tuner::V1_0::FrontendStatusType;
shubangdeb067c2020-01-27 13:21:55 -0800132using ::android::hardware::tv::tuner::V1_0::FrontendType;
shubang8ab43b12019-10-18 15:55:55 -0700133using ::android::hardware::tv::tuner::V1_0::ITuner;
shubang1c1144e2020-03-03 18:00:17 -0800134using ::android::hardware::tv::tuner::V1_0::LnbPosition;
135using ::android::hardware::tv::tuner::V1_0::LnbTone;
136using ::android::hardware::tv::tuner::V1_0::LnbVoltage;
shubang030afb52019-11-27 16:09:02 -0800137using ::android::hardware::tv::tuner::V1_0::PlaybackSettings;
138using ::android::hardware::tv::tuner::V1_0::RecordSettings;
shubang8ab43b12019-10-18 15:55:55 -0700139
140struct fields_t {
shubang13f15e02019-11-04 17:51:02 -0800141 jfieldID tunerContext;
shubang1c1144e2020-03-03 18:00:17 -0800142 jfieldID lnbContext;
shubangcdf30de2019-11-06 17:28:38 -0800143 jfieldID filterContext;
shubangf657da22020-02-05 16:27:06 -0800144 jfieldID timeFilterContext;
shubang13f15e02019-11-04 17:51:02 -0800145 jfieldID descramblerContext;
shubang5637a662020-02-27 18:06:21 -0800146 jfieldID dvrRecorderContext;
147 jfieldID dvrPlaybackContext;
shubang7e849b02019-10-18 19:36:25 -0700148 jmethodID frontendInitID;
shubang6f473d62019-11-01 15:42:21 -0700149 jmethodID filterInitID;
shubangf657da22020-02-05 16:27:06 -0800150 jmethodID timeFilterInitID;
shubang5637a662020-02-27 18:06:21 -0800151 jmethodID dvrRecorderInitID;
152 jmethodID dvrPlaybackInitID;
shubang4b8c5402019-10-24 17:49:53 -0700153 jmethodID onFrontendEventID;
shubangcdf30de2019-11-06 17:28:38 -0800154 jmethodID onFilterStatusID;
shubang3e0c37b2020-02-19 19:09:10 -0800155 jmethodID onFilterEventID;
shubang760f0312019-11-12 17:11:28 -0800156 jmethodID lnbInitID;
157 jmethodID onLnbEventID;
shubangd295be02020-03-27 17:08:11 -0700158 jmethodID onLnbDiseqcMessageID;
shubang431e5612020-03-30 21:24:56 -0700159 jmethodID onDvrRecordStatusID;
160 jmethodID onDvrPlaybackStatusID;
shubang13f15e02019-11-04 17:51:02 -0800161 jmethodID descramblerInitID;
shubangd49681e2020-02-17 21:32:30 -0800162 jmethodID linearBlockInitID;
163 jmethodID linearBlockSetInternalStateID;
shubang8ab43b12019-10-18 15:55:55 -0700164};
165
166static fields_t gFields;
167
shubangd49681e2020-02-17 21:32:30 -0800168
shubang87788c32020-02-04 13:55:23 -0800169static int IP_V4_LENGTH = 4;
170static int IP_V6_LENGTH = 16;
171
shubang8ab43b12019-10-18 15:55:55 -0700172namespace android {
shubang760f0312019-11-12 17:11:28 -0800173/////////////// LnbCallback ///////////////////////
shubangd295be02020-03-27 17:08:11 -0700174LnbCallback::LnbCallback(jobject lnbObj, LnbId id) : mId(id) {
175 JNIEnv *env = AndroidRuntime::getJNIEnv();
176 mLnb = env->NewWeakGlobalRef(lnbObj);
177}
shubang760f0312019-11-12 17:11:28 -0800178
179Return<void> LnbCallback::onEvent(LnbEventType lnbEventType) {
180 ALOGD("LnbCallback::onEvent, type=%d", lnbEventType);
181 JNIEnv *env = AndroidRuntime::getJNIEnv();
182 env->CallVoidMethod(
shubangd295be02020-03-27 17:08:11 -0700183 mLnb,
shubang760f0312019-11-12 17:11:28 -0800184 gFields.onLnbEventID,
185 (jint)lnbEventType);
186 return Void();
187}
shubangd295be02020-03-27 17:08:11 -0700188Return<void> LnbCallback::onDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage) {
shubang760f0312019-11-12 17:11:28 -0800189 ALOGD("LnbCallback::onDiseqcMessage");
shubangd295be02020-03-27 17:08:11 -0700190 JNIEnv *env = AndroidRuntime::getJNIEnv();
191 jbyteArray array = env->NewByteArray(diseqcMessage.size());
192 env->SetByteArrayRegion(
193 array, 0, diseqcMessage.size(), reinterpret_cast<jbyte*>(diseqcMessage[0]));
194
195 env->CallVoidMethod(
196 mLnb,
197 gFields.onLnbDiseqcMessageID,
198 array);
shubang760f0312019-11-12 17:11:28 -0800199 return Void();
200}
201
shubang1c1144e2020-03-03 18:00:17 -0800202/////////////// Lnb ///////////////////////
203
204Lnb::Lnb(sp<ILnb> sp, jobject obj) : mLnbSp(sp) {
205 JNIEnv *env = AndroidRuntime::getJNIEnv();
206 mLnbObj = env->NewWeakGlobalRef(obj);
207}
208
209Lnb::~Lnb() {
210 JNIEnv *env = AndroidRuntime::getJNIEnv();
211 env->DeleteWeakGlobalRef(mLnbObj);
212 mLnbObj = NULL;
213}
214
215sp<ILnb> Lnb::getILnb() {
216 return mLnbSp;
217}
218
shubang4a0eddf2019-11-08 17:10:18 -0800219/////////////// DvrCallback ///////////////////////
shubang431e5612020-03-30 21:24:56 -0700220Return<void> DvrCallback::onRecordStatus(RecordStatus status) {
shubang4a0eddf2019-11-08 17:10:18 -0800221 ALOGD("DvrCallback::onRecordStatus");
shubang431e5612020-03-30 21:24:56 -0700222 JNIEnv *env = AndroidRuntime::getJNIEnv();
223 env->CallVoidMethod(
224 mDvr,
225 gFields.onDvrRecordStatusID,
226 (jint) status);
shubang4a0eddf2019-11-08 17:10:18 -0800227 return Void();
228}
229
shubang431e5612020-03-30 21:24:56 -0700230Return<void> DvrCallback::onPlaybackStatus(PlaybackStatus status) {
shubang4a0eddf2019-11-08 17:10:18 -0800231 ALOGD("DvrCallback::onPlaybackStatus");
shubang431e5612020-03-30 21:24:56 -0700232 JNIEnv *env = AndroidRuntime::getJNIEnv();
233 env->CallVoidMethod(
234 mDvr,
235 gFields.onDvrPlaybackStatusID,
236 (jint) status);
shubang4a0eddf2019-11-08 17:10:18 -0800237 return Void();
238}
239
240void DvrCallback::setDvr(const jobject dvr) {
shubangba21a7f2019-12-05 16:58:55 -0800241 ALOGD("DvrCallback::setDvr");
shubang4a0eddf2019-11-08 17:10:18 -0800242 JNIEnv *env = AndroidRuntime::getJNIEnv();
243 mDvr = env->NewWeakGlobalRef(dvr);
244}
245
shubang431e5612020-03-30 21:24:56 -0700246DvrCallback::~DvrCallback() {
247 JNIEnv *env = AndroidRuntime::getJNIEnv();
248 if (mDvr != NULL) {
249 env->DeleteWeakGlobalRef(mDvr);
250 mDvr = NULL;
251 }
shubangba21a7f2019-12-05 16:58:55 -0800252}
253
shubang431e5612020-03-30 21:24:56 -0700254/////////////// Dvr ///////////////////////
255
256Dvr::Dvr(sp<IDvr> sp, jobject obj) : mDvrSp(sp), mDvrMQEventFlag(nullptr) {
257 JNIEnv *env = AndroidRuntime::getJNIEnv();
258 mDvrObj = env->NewWeakGlobalRef(obj);
259}
260
261Dvr::~Dvr() {
262 JNIEnv *env = AndroidRuntime::getJNIEnv();
263 env->DeleteWeakGlobalRef(mDvrObj);
264 mDvrObj = NULL;
265}
266
267jint Dvr::close() {
shubangba21a7f2019-12-05 16:58:55 -0800268 Result r = mDvrSp->close();
269 if (r == Result::SUCCESS) {
270 EventFlag::deleteEventFlag(&mDvrMQEventFlag);
271 }
shubang431e5612020-03-30 21:24:56 -0700272 return (jint) r;
shubangba21a7f2019-12-05 16:58:55 -0800273}
274
shubang9e700ff2019-12-04 16:26:51 -0800275sp<IDvr> Dvr::getIDvr() {
276 return mDvrSp;
277}
278
shubang431e5612020-03-30 21:24:56 -0700279MQ& Dvr::getDvrMQ() {
shubang5f4ea352019-12-09 15:12:10 -0800280 return *mDvrMQ;
281}
282
shubang6f473d62019-11-01 15:42:21 -0700283/////////////// FilterCallback ///////////////////////
284//TODO: implement filter callback
shubangd49681e2020-02-17 21:32:30 -0800285jobject FilterCallback::handleToLinearBlock(const native_handle_t* handle, uint32_t size) {
286 ALOGD("FilterCallback::handleToLinearBlock");
287 C2HandleIon* ion = new C2HandleIon(handle->data[0], size);
288 std::shared_ptr<C2LinearBlock> block = _C2BlockFactory::CreateLinearBlock(ion);
289
290 JNIEnv *env = AndroidRuntime::getJNIEnv();
291 std::unique_ptr<JMediaCodecLinearBlock> context{new JMediaCodecLinearBlock};
292 context->mBlock = block;
293
294 jobject linearBlock =
295 env->NewObject(
296 env->FindClass("android/media/MediaCodec$LinearBlock"),
297 gFields.linearBlockInitID);
298 env->CallVoidMethod(
299 linearBlock,
300 gFields.linearBlockSetInternalStateID,
301 (jlong)context.release(),
302 true);
303 return linearBlock;
304}
305
shubang3e0c37b2020-02-19 19:09:10 -0800306jobjectArray FilterCallback::getSectionEvent(
307 jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) {
shubangd49681e2020-02-17 21:32:30 -0800308 JNIEnv *env = AndroidRuntime::getJNIEnv();
shubang3e0c37b2020-02-19 19:09:10 -0800309 jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/SectionEvent");
310 jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(IIII)V");
311
312 for (int i = 0; i < events.size(); i++) {
313 auto event = events[i];
314 DemuxFilterSectionEvent sectionEvent = event.section();
315
316 jint tableId = static_cast<jint>(sectionEvent.tableId);
317 jint version = static_cast<jint>(sectionEvent.version);
318 jint sectionNum = static_cast<jint>(sectionEvent.sectionNum);
319 jint dataLength = static_cast<jint>(sectionEvent.dataLength);
320
321 jobject obj =
322 env->NewObject(eventClazz, eventInit, tableId, version, sectionNum, dataLength);
323 env->SetObjectArrayElement(arr, i, obj);
324 }
325 return arr;
326}
327
328jobjectArray FilterCallback::getMediaEvent(
329 jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) {
330 JNIEnv *env = AndroidRuntime::getJNIEnv();
331 jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/MediaEvent");
332 jmethodID eventInit = env->GetMethodID(eventClazz,
shubangd49681e2020-02-17 21:32:30 -0800333 "<init>",
334 "(IZJJJLandroid/media/MediaCodec$LinearBlock;"
335 "ZJIZLandroid/media/tv/tuner/filter/AudioDescriptor;)V");
336
shubang3e0c37b2020-02-19 19:09:10 -0800337 for (int i = 0; i < events.size(); i++) {
338 auto event = events[i];
339 DemuxFilterMediaEvent mediaEvent = event.media();
shubangd49681e2020-02-17 21:32:30 -0800340
shubang3e0c37b2020-02-19 19:09:10 -0800341 jobject audioDescriptor = NULL;
342 if (mediaEvent.extraMetaData.getDiscriminator()
343 == DemuxFilterMediaEvent::ExtraMetaData::hidl_discriminator::audio) {
344 jclass adClazz = env->FindClass("android/media/tv/tuner/filter/AudioDescriptor");
345 jmethodID adInit = env->GetMethodID(adClazz, "<init>", "(BBCBBB)V");
346
347 AudioExtraMetaData ad = mediaEvent.extraMetaData.audio();
348 jbyte adFade = static_cast<jbyte>(ad.adFade);
349 jbyte adPan = static_cast<jbyte>(ad.adPan);
350 jchar versionTextTag = static_cast<jchar>(ad.versionTextTag);
351 jbyte adGainCenter = static_cast<jbyte>(ad.adGainCenter);
352 jbyte adGainFront = static_cast<jbyte>(ad.adGainFront);
353 jbyte adGainSurround = static_cast<jbyte>(ad.adGainSurround);
354
355 audioDescriptor =
356 env->NewObject(adClazz, adInit, adFade, adPan, versionTextTag, adGainCenter,
357 adGainFront, adGainSurround);
358 }
359
360 jlong dataLength = static_cast<jlong>(mediaEvent.dataLength);
361 const native_handle_t* h = NULL;
362 jobject block = NULL;
363 if (mediaEvent.avMemory != NULL) {
364 h = mediaEvent.avMemory.getNativeHandle();
365 block = handleToLinearBlock(h, dataLength);
366 }
367
368 jint streamId = static_cast<jint>(mediaEvent.streamId);
369 jboolean isPtsPresent = static_cast<jboolean>(mediaEvent.isPtsPresent);
370 jlong pts = static_cast<jlong>(mediaEvent.pts);
371 jlong offset = static_cast<jlong>(mediaEvent.offset);
372 jboolean isSecureMemory = static_cast<jboolean>(mediaEvent.isSecureMemory);
373 jlong avDataId = static_cast<jlong>(mediaEvent.avDataId);
374 jint mpuSequenceNumber = static_cast<jint>(mediaEvent.mpuSequenceNumber);
375 jboolean isPesPrivateData = static_cast<jboolean>(mediaEvent.isPesPrivateData);
376
377 jobject obj =
378 env->NewObject(eventClazz, eventInit, streamId, isPtsPresent, pts, dataLength,
379 offset, block, isSecureMemory, avDataId, mpuSequenceNumber, isPesPrivateData,
380 audioDescriptor);
381 env->SetObjectArrayElement(arr, i, obj);
382 }
383 return arr;
384}
385
386jobjectArray FilterCallback::getPesEvent(
387 jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) {
388 JNIEnv *env = AndroidRuntime::getJNIEnv();
389 jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/PesEvent");
390 jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(III)V");
391
392 for (int i = 0; i < events.size(); i++) {
393 auto event = events[i];
394 DemuxFilterPesEvent pesEvent = event.pes();
395
396 jint streamId = static_cast<jint>(pesEvent.streamId);
397 jint dataLength = static_cast<jint>(pesEvent.dataLength);
398 jint mpuSequenceNumber = static_cast<jint>(pesEvent.mpuSequenceNumber);
399
400 jobject obj =
401 env->NewObject(eventClazz, eventInit, streamId, dataLength, mpuSequenceNumber);
402 env->SetObjectArrayElement(arr, i, obj);
403 }
404 return arr;
405}
406
407jobjectArray FilterCallback::getTsRecordEvent(
408 jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) {
409 JNIEnv *env = AndroidRuntime::getJNIEnv();
410 jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/TsRecordEvent");
411 jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(IIIJ)V");
412
413 for (int i = 0; i < events.size(); i++) {
414 auto event = events[i];
415 DemuxFilterTsRecordEvent tsRecordEvent = event.tsRecord();
416 DemuxPid pid = tsRecordEvent.pid;
417
418 jint jpid = static_cast<jint>(Constant::INVALID_TS_PID);
419
420 if (pid.getDiscriminator() == DemuxPid::hidl_discriminator::tPid) {
421 jpid = static_cast<jint>(pid.tPid());
422 } else if (pid.getDiscriminator() == DemuxPid::hidl_discriminator::mmtpPid) {
423 jpid = static_cast<jint>(pid.mmtpPid());
424 }
425
426 jint sc = 0;
427
428 if (tsRecordEvent.scIndexMask.getDiscriminator()
429 == DemuxFilterTsRecordEvent::ScIndexMask::hidl_discriminator::sc) {
430 sc = static_cast<jint>(tsRecordEvent.scIndexMask.sc());
431 } else if (tsRecordEvent.scIndexMask.getDiscriminator()
432 == DemuxFilterTsRecordEvent::ScIndexMask::hidl_discriminator::scHevc) {
433 sc = static_cast<jint>(tsRecordEvent.scIndexMask.scHevc());
434 }
435
436 jint ts = static_cast<jint>(tsRecordEvent.tsIndexMask);
437
438 jlong byteNumber = static_cast<jlong>(tsRecordEvent.byteNumber);
439
440 jobject obj =
441 env->NewObject(eventClazz, eventInit, jpid, ts, sc, byteNumber);
442 env->SetObjectArrayElement(arr, i, obj);
443 }
444 return arr;
445}
446
447jobjectArray FilterCallback::getMmtpRecordEvent(
448 jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) {
449 JNIEnv *env = AndroidRuntime::getJNIEnv();
450 jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/MmtpRecordEvent");
451 jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(IJ)V");
452
453 for (int i = 0; i < events.size(); i++) {
454 auto event = events[i];
455 DemuxFilterMmtpRecordEvent mmtpRecordEvent = event.mmtpRecord();
456
457 jint scHevcIndexMask = static_cast<jint>(mmtpRecordEvent.scHevcIndexMask);
458 jlong byteNumber = static_cast<jlong>(mmtpRecordEvent.byteNumber);
459
460 jobject obj =
461 env->NewObject(eventClazz, eventInit, scHevcIndexMask, byteNumber);
462 env->SetObjectArrayElement(arr, i, obj);
463 }
464 return arr;
465}
466
467jobjectArray FilterCallback::getDownloadEvent(
468 jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) {
469 JNIEnv *env = AndroidRuntime::getJNIEnv();
470 jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/DownloadEvent");
471 jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(IIIII)V");
472
473 for (int i = 0; i < events.size(); i++) {
474 auto event = events[i];
475 DemuxFilterDownloadEvent downloadEvent = event.download();
476
477 jint itemId = static_cast<jint>(downloadEvent.itemId);
478 jint mpuSequenceNumber = static_cast<jint>(downloadEvent.mpuSequenceNumber);
479 jint itemFragmentIndex = static_cast<jint>(downloadEvent.itemFragmentIndex);
480 jint lastItemFragmentIndex = static_cast<jint>(downloadEvent.lastItemFragmentIndex);
481 jint dataLength = static_cast<jint>(downloadEvent.dataLength);
482
483 jobject obj =
484 env->NewObject(eventClazz, eventInit, itemId, mpuSequenceNumber, itemFragmentIndex,
485 lastItemFragmentIndex, dataLength);
486 env->SetObjectArrayElement(arr, i, obj);
487 }
488 return arr;
489}
490
491jobjectArray FilterCallback::getIpPayloadEvent(
492 jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) {
493 JNIEnv *env = AndroidRuntime::getJNIEnv();
494 jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/IpPayloadEvent");
495 jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(I)V");
496
497 for (int i = 0; i < events.size(); i++) {
498 auto event = events[i];
499 DemuxFilterIpPayloadEvent ipPayloadEvent = event.ipPayload();
500 jint dataLength = static_cast<jint>(ipPayloadEvent.dataLength);
501 jobject obj = env->NewObject(eventClazz, eventInit, dataLength);
502 env->SetObjectArrayElement(arr, i, obj);
503 }
504 return arr;
505}
506
507jobjectArray FilterCallback::getTemiEvent(
508 jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) {
509 JNIEnv *env = AndroidRuntime::getJNIEnv();
510 jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/TemiEvent");
511 jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(JB[B)V");
512
513 for (int i = 0; i < events.size(); i++) {
514 auto event = events[i];
515 DemuxFilterTemiEvent temiEvent = event.temi();
516 jlong pts = static_cast<jlong>(temiEvent.pts);
517 jbyte descrTag = static_cast<jbyte>(temiEvent.descrTag);
518 std::vector<uint8_t> descrData = temiEvent.descrData;
519
520 jbyteArray array = env->NewByteArray(descrData.size());
521 env->SetByteArrayRegion(
522 array, 0, descrData.size(), reinterpret_cast<jbyte*>(&descrData[0]));
523
524 jobject obj = env->NewObject(eventClazz, eventInit, pts, descrTag, array);
525 env->SetObjectArrayElement(arr, i, obj);
526 }
527 return arr;
shubangd49681e2020-02-17 21:32:30 -0800528}
529
530Return<void> FilterCallback::onFilterEvent(const DemuxFilterEvent& filterEvent) {
shubang6f473d62019-11-01 15:42:21 -0700531 ALOGD("FilterCallback::onFilterEvent");
shubangd49681e2020-02-17 21:32:30 -0800532
533 JNIEnv *env = AndroidRuntime::getJNIEnv();
shubangd49681e2020-02-17 21:32:30 -0800534
535 std::vector<DemuxFilterEvent::Event> events = filterEvent.events;
536 jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/FilterEvent");
537 jobjectArray array = env->NewObjectArray(events.size(), eventClazz, NULL);
538
shubang3e0c37b2020-02-19 19:09:10 -0800539 if (!events.empty()) {
540 auto event = events[0];
541 switch (event.getDiscriminator()) {
542 case DemuxFilterEvent::Event::hidl_discriminator::media: {
543 array = getMediaEvent(array, events);
544 break;
545 }
546 case DemuxFilterEvent::Event::hidl_discriminator::section: {
547 array = getSectionEvent(array, events);
548 break;
549 }
550 case DemuxFilterEvent::Event::hidl_discriminator::pes: {
551 array = getPesEvent(array, events);
552 break;
553 }
554 case DemuxFilterEvent::Event::hidl_discriminator::tsRecord: {
555 array = getTsRecordEvent(array, events);
556 break;
557 }
558 case DemuxFilterEvent::Event::hidl_discriminator::mmtpRecord: {
559 array = getMmtpRecordEvent(array, events);
560 break;
561 }
562 case DemuxFilterEvent::Event::hidl_discriminator::download: {
563 array = getDownloadEvent(array, events);
564 break;
565 }
566 case DemuxFilterEvent::Event::hidl_discriminator::ipPayload: {
567 array = getIpPayloadEvent(array, events);
568 break;
569 }
570 case DemuxFilterEvent::Event::hidl_discriminator::temi: {
571 array = getTemiEvent(array, events);
572 break;
573 }
574 default: {
575 break;
576 }
shubangd49681e2020-02-17 21:32:30 -0800577 }
578 }
579 env->CallVoidMethod(
580 mFilter,
shubang3e0c37b2020-02-19 19:09:10 -0800581 gFields.onFilterEventID,
shubangd49681e2020-02-17 21:32:30 -0800582 array);
shubang6f473d62019-11-01 15:42:21 -0700583 return Void();
584}
shubangcdf30de2019-11-06 17:28:38 -0800585
shubang3e0c37b2020-02-19 19:09:10 -0800586
shubangcdf30de2019-11-06 17:28:38 -0800587Return<void> FilterCallback::onFilterStatus(const DemuxFilterStatus status) {
588 ALOGD("FilterCallback::onFilterStatus");
589 JNIEnv *env = AndroidRuntime::getJNIEnv();
590 env->CallVoidMethod(
591 mFilter,
592 gFields.onFilterStatusID,
593 (jint)status);
shubang6f473d62019-11-01 15:42:21 -0700594 return Void();
595}
shubang8ab43b12019-10-18 15:55:55 -0700596
shubangcdf30de2019-11-06 17:28:38 -0800597void FilterCallback::setFilter(const jobject filter) {
598 ALOGD("FilterCallback::setFilter");
599 JNIEnv *env = AndroidRuntime::getJNIEnv();
600 mFilter = env->NewWeakGlobalRef(filter);
601}
602
shubang431e5612020-03-30 21:24:56 -0700603FilterCallback::~FilterCallback() {
604 JNIEnv *env = AndroidRuntime::getJNIEnv();
605 if (mFilter != NULL) {
606 env->DeleteWeakGlobalRef(mFilter);
607 mFilter = NULL;
608 }
609}
610
shubang7648a3c2019-11-25 18:16:45 -0800611/////////////// Filter ///////////////////////
612
shubang3e0c37b2020-02-19 19:09:10 -0800613Filter::Filter(sp<IFilter> sp, jobject obj) : mFilterSp(sp) {
614 JNIEnv *env = AndroidRuntime::getJNIEnv();
615 mFilterObj = env->NewWeakGlobalRef(obj);
616}
shubang7648a3c2019-11-25 18:16:45 -0800617
shubang964e6132019-11-26 15:05:22 -0800618Filter::~Filter() {
shubang3e0c37b2020-02-19 19:09:10 -0800619 JNIEnv *env = AndroidRuntime::getJNIEnv();
620
621 env->DeleteWeakGlobalRef(mFilterObj);
622 mFilterObj = NULL;
shubang964e6132019-11-26 15:05:22 -0800623 EventFlag::deleteEventFlag(&mFilterMQEventFlag);
624}
625
626int Filter::close() {
627 Result r = mFilterSp->close();
628 if (r == Result::SUCCESS) {
629 EventFlag::deleteEventFlag(&mFilterMQEventFlag);
630 }
631 return (int)r;
632}
633
shubang7648a3c2019-11-25 18:16:45 -0800634sp<IFilter> Filter::getIFilter() {
635 return mFilterSp;
636}
637
shubangf657da22020-02-05 16:27:06 -0800638/////////////// TimeFilter ///////////////////////
639
640TimeFilter::TimeFilter(sp<ITimeFilter> sp, jobject obj) : mTimeFilterSp(sp) {
641 JNIEnv *env = AndroidRuntime::getJNIEnv();
642 mTimeFilterObj = env->NewWeakGlobalRef(obj);
643}
644
645TimeFilter::~TimeFilter() {
646 ALOGD("~TimeFilter");
647 JNIEnv *env = AndroidRuntime::getJNIEnv();
648
649 env->DeleteWeakGlobalRef(mTimeFilterObj);
650 mTimeFilterObj = NULL;
651}
652
653sp<ITimeFilter> TimeFilter::getITimeFilter() {
654 return mTimeFilterSp;
655}
656
shubang4b8c5402019-10-24 17:49:53 -0700657/////////////// FrontendCallback ///////////////////////
658
659FrontendCallback::FrontendCallback(jweak tunerObj, FrontendId id) : mObject(tunerObj), mId(id) {}
660
661Return<void> FrontendCallback::onEvent(FrontendEventType frontendEventType) {
662 ALOGD("FrontendCallback::onEvent, type=%d", frontendEventType);
663 JNIEnv *env = AndroidRuntime::getJNIEnv();
664 env->CallVoidMethod(
665 mObject,
666 gFields.onFrontendEventID,
667 (jint)frontendEventType);
668 return Void();
669}
shubang4b8c5402019-10-24 17:49:53 -0700670
shubangc8736b72020-02-11 18:27:53 -0800671Return<void> FrontendCallback::onScanMessage(FrontendScanMessageType type, const FrontendScanMessage& message) {
shubang4b8c5402019-10-24 17:49:53 -0700672 ALOGD("FrontendCallback::onScanMessage, type=%d", type);
shubangc8736b72020-02-11 18:27:53 -0800673 JNIEnv *env = AndroidRuntime::getJNIEnv();
674 jclass clazz = env->FindClass("android/media/tv/tuner/Tuner");
675 switch(type) {
676 case FrontendScanMessageType::LOCKED: {
677 if (message.isLocked()) {
678 env->CallVoidMethod(
679 mObject,
680 env->GetMethodID(clazz, "onLocked", "()V"));
681 }
682 break;
683 }
684 case FrontendScanMessageType::END: {
685 if (message.isEnd()) {
686 env->CallVoidMethod(
687 mObject,
688 env->GetMethodID(clazz, "onScanStopped", "()V"));
689 }
690 break;
691 }
692 case FrontendScanMessageType::PROGRESS_PERCENT: {
693 env->CallVoidMethod(
694 mObject,
695 env->GetMethodID(clazz, "onProgress", "(I)V"),
696 (jint) message.progressPercent());
697 break;
698 }
699 case FrontendScanMessageType::FREQUENCY: {
700 std::vector<uint32_t> v = message.frequencies();
701 jintArray freqs = env->NewIntArray(v.size());
702 env->SetIntArrayRegion(freqs, 0, v.size(), reinterpret_cast<jint*>(&v[0]));
703
704 env->CallVoidMethod(
705 mObject,
706 env->GetMethodID(clazz, "onFrequenciesReport", "([I)V"),
707 freqs);
708 break;
709 }
710 case FrontendScanMessageType::SYMBOL_RATE: {
711 std::vector<uint32_t> v = message.symbolRates();
712 jintArray symbolRates = env->NewIntArray(v.size());
713 env->SetIntArrayRegion(symbolRates, 0, v.size(), reinterpret_cast<jint*>(&v[0]));
714
715 env->CallVoidMethod(
716 mObject,
717 env->GetMethodID(clazz, "onSymbolRates", "([I)V"),
718 symbolRates);
719 break;
720 }
721 case FrontendScanMessageType::HIERARCHY: {
722 env->CallVoidMethod(
723 mObject,
724 env->GetMethodID(clazz, "onHierarchy", "(I)V"),
725 (jint) message.hierarchy());
726 break;
727 }
728 case FrontendScanMessageType::ANALOG_TYPE: {
729 env->CallVoidMethod(
730 mObject,
731 env->GetMethodID(clazz, "onSignalType", "(I)V"),
732 (jint) message.analogType());
733 break;
734 }
735 case FrontendScanMessageType::PLP_IDS: {
736 std::vector<uint8_t> v = message.plpIds();
737 std::vector<jint> jintV(v.begin(), v.end());
738 jintArray plpIds = env->NewIntArray(v.size());
739 env->SetIntArrayRegion(plpIds, 0, jintV.size(), &jintV[0]);
740
741 env->CallVoidMethod(
742 mObject,
743 env->GetMethodID(clazz, "onPlpIds", "([I)V"),
744 plpIds);
745 break;
746 }
747 case FrontendScanMessageType::GROUP_IDS: {
748 std::vector<uint8_t> v = message.groupIds();
749 std::vector<jint> jintV(v.begin(), v.end());
750 jintArray groupIds = env->NewIntArray(v.size());
751 env->SetIntArrayRegion(groupIds, 0, jintV.size(), &jintV[0]);
752
753 env->CallVoidMethod(
754 mObject,
755 env->GetMethodID(clazz, "onGroupIds", "([I)V"),
756 groupIds);
757 break;
758 }
759 case FrontendScanMessageType::INPUT_STREAM_IDS: {
760 std::vector<uint16_t> v = message.inputStreamIds();
761 std::vector<jint> jintV(v.begin(), v.end());
762 jintArray streamIds = env->NewIntArray(v.size());
763 env->SetIntArrayRegion(streamIds, 0, jintV.size(), &jintV[0]);
764
765 env->CallVoidMethod(
766 mObject,
767 env->GetMethodID(clazz, "onInputStreamIds", "([I)V"),
768 streamIds);
769 break;
770 }
771 case FrontendScanMessageType::STANDARD: {
772 FrontendScanMessage::Standard std = message.std();
773 jint standard;
774 if (std.getDiscriminator() == FrontendScanMessage::Standard::hidl_discriminator::sStd) {
775 standard = (jint) std.sStd();
776 env->CallVoidMethod(
777 mObject,
778 env->GetMethodID(clazz, "onDvbsStandard", "(I)V"),
779 standard);
780 } else if (std.getDiscriminator() == FrontendScanMessage::Standard::hidl_discriminator::tStd) {
781 standard = (jint) std.tStd();
782 env->CallVoidMethod(
783 mObject,
784 env->GetMethodID(clazz, "onDvbtStandard", "(I)V"),
785 standard);
786 } else if (std.getDiscriminator() == FrontendScanMessage::Standard::hidl_discriminator::sifStd) {
787 standard = (jint) std.sifStd();
788 env->CallVoidMethod(
789 mObject,
790 env->GetMethodID(clazz, "onAnalogSifStandard", "(I)V"),
791 standard);
792 }
793 break;
794 }
795 case FrontendScanMessageType::ATSC3_PLP_INFO: {
796 jclass plpClazz = env->FindClass("android/media/tv/tuner/frontend/Atsc3PlpInfo");
797 jmethodID init = env->GetMethodID(plpClazz, "<init>", "(IZ)V");
798 std::vector<FrontendScanAtsc3PlpInfo> plpInfos = message.atsc3PlpInfos();
799 jobjectArray array = env->NewObjectArray(plpInfos.size(), plpClazz, NULL);
800
801 for (int i = 0; i < plpInfos.size(); i++) {
802 auto info = plpInfos[i];
803 jint plpId = (jint) info.plpId;
804 jboolean lls = (jboolean) info.bLlsFlag;
805
806 jobject obj = env->NewObject(plpClazz, init, plpId, lls);
807 env->SetObjectArrayElement(array, i, obj);
808 }
809 env->CallVoidMethod(
810 mObject,
811 env->GetMethodID(clazz, "onAtsc3PlpInfos", "([Landroid/media/tv/tuner/frontend/Atsc3PlpInfo;)V"),
812 array);
813 break;
814 }
815 }
shubang4b8c5402019-10-24 17:49:53 -0700816 return Void();
817}
818
shubang6f473d62019-11-01 15:42:21 -0700819/////////////// Tuner ///////////////////////
shubang4b8c5402019-10-24 17:49:53 -0700820
shubang8ab43b12019-10-18 15:55:55 -0700821sp<ITuner> JTuner::mTuner;
822
823JTuner::JTuner(JNIEnv *env, jobject thiz)
824 : mClass(NULL) {
825 jclass clazz = env->GetObjectClass(thiz);
826 CHECK(clazz != NULL);
827
828 mClass = (jclass)env->NewGlobalRef(clazz);
829 mObject = env->NewWeakGlobalRef(thiz);
830 if (mTuner == NULL) {
831 mTuner = getTunerService();
832 }
833}
834
835JTuner::~JTuner() {
shubang2f9cab32020-04-10 18:00:56 -0700836 if (mFe != NULL) {
837 mFe->close();
838 }
839 if (mDemux != NULL) {
840 mDemux->close();
841 }
shubang8ab43b12019-10-18 15:55:55 -0700842 JNIEnv *env = AndroidRuntime::getJNIEnv();
843
shubang431e5612020-03-30 21:24:56 -0700844 env->DeleteWeakGlobalRef(mObject);
shubang8ab43b12019-10-18 15:55:55 -0700845 env->DeleteGlobalRef(mClass);
846 mTuner = NULL;
847 mClass = NULL;
848 mObject = NULL;
849}
850
851sp<ITuner> JTuner::getTunerService() {
852 if (mTuner == nullptr) {
853 mTuner = ITuner::getService();
854
855 if (mTuner == nullptr) {
856 ALOGW("Failed to get tuner service.");
857 }
858 }
859 return mTuner;
860}
861
shubang7e849b02019-10-18 19:36:25 -0700862jobject JTuner::getFrontendIds() {
863 ALOGD("JTuner::getFrontendIds()");
shubang7e849b02019-10-18 19:36:25 -0700864 mTuner->getFrontendIds([&](Result, const hidl_vec<FrontendId>& frontendIds) {
shubang4b8c5402019-10-24 17:49:53 -0700865 mFeIds = frontendIds;
shubang7e849b02019-10-18 19:36:25 -0700866 });
shubang4b8c5402019-10-24 17:49:53 -0700867 if (mFeIds.size() == 0) {
shubang7e849b02019-10-18 19:36:25 -0700868 ALOGW("Frontend isn't available");
869 return NULL;
870 }
871
872 JNIEnv *env = AndroidRuntime::getJNIEnv();
873 jclass arrayListClazz = env->FindClass("java/util/ArrayList");
874 jmethodID arrayListAdd = env->GetMethodID(arrayListClazz, "add", "(Ljava/lang/Object;)Z");
875 jobject obj = env->NewObject(arrayListClazz, env->GetMethodID(arrayListClazz, "<init>", "()V"));
876
877 jclass integerClazz = env->FindClass("java/lang/Integer");
878 jmethodID intInit = env->GetMethodID(integerClazz, "<init>", "(I)V");
879
shubang4b8c5402019-10-24 17:49:53 -0700880 for (int i=0; i < mFeIds.size(); i++) {
881 jobject idObj = env->NewObject(integerClazz, intInit, mFeIds[i]);
shubang7e849b02019-10-18 19:36:25 -0700882 env->CallBooleanMethod(obj, arrayListAdd, idObj);
883 }
884 return obj;
885}
886
887jobject JTuner::openFrontendById(int id) {
shubang4b8c5402019-10-24 17:49:53 -0700888 sp<IFrontend> fe;
shubang66cc3aa2020-04-06 17:10:01 -0700889 Result res;
890 mTuner->openFrontendById(id, [&](Result r, const sp<IFrontend>& frontend) {
shubang4b8c5402019-10-24 17:49:53 -0700891 fe = frontend;
shubang66cc3aa2020-04-06 17:10:01 -0700892 res = r;
shubang7e849b02019-10-18 19:36:25 -0700893 });
shubang66cc3aa2020-04-06 17:10:01 -0700894 if (res != Result::SUCCESS || fe == nullptr) {
shubang7e849b02019-10-18 19:36:25 -0700895 ALOGE("Failed to open frontend");
896 return NULL;
897 }
shubang4b8c5402019-10-24 17:49:53 -0700898 mFe = fe;
shubangd295be02020-03-27 17:08:11 -0700899 mFeId = id;
900 if (mDemux != NULL) {
901 mDemux->setFrontendDataSource(mFeId);
902 }
shubang4b8c5402019-10-24 17:49:53 -0700903 sp<FrontendCallback> feCb = new FrontendCallback(mObject, id);
904 fe->setCallback(feCb);
shubang7e849b02019-10-18 19:36:25 -0700905
906 jint jId = (jint) id;
shubang964e6132019-11-26 15:05:22 -0800907
shubang7e849b02019-10-18 19:36:25 -0700908 JNIEnv *env = AndroidRuntime::getJNIEnv();
909 // TODO: add more fields to frontend
910 return env->NewObject(
911 env->FindClass("android/media/tv/tuner/Tuner$Frontend"),
912 gFields.frontendInitID,
shubang4b8c5402019-10-24 17:49:53 -0700913 mObject,
shubang7e849b02019-10-18 19:36:25 -0700914 (jint) jId);
915}
916
shubang2f9cab32020-04-10 18:00:56 -0700917jint JTuner::closeFrontendById(int id) {
918 if (mFe != NULL && mFeId == id) {
919 Result r = mFe->close();
920 return (jint) r;
921 }
922 return (jint) Result::SUCCESS;
923}
924
shubang66cc3aa2020-04-06 17:10:01 -0700925jobject JTuner::getAnalogFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) {
shubang51cc62f2020-01-28 18:00:22 -0800926 jclass clazz = env->FindClass("android/media/tv/tuner/frontend/AnalogFrontendCapabilities");
927 jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(II)V");
928
929 jint typeCap = caps.analogCaps().typeCap;
930 jint sifStandardCap = caps.analogCaps().sifStandardCap;
931 return env->NewObject(clazz, capsInit, typeCap, sifStandardCap);
932}
933
shubang66cc3aa2020-04-06 17:10:01 -0700934jobject JTuner::getAtsc3FrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) {
shubang51cc62f2020-01-28 18:00:22 -0800935 jclass clazz = env->FindClass("android/media/tv/tuner/frontend/Atsc3FrontendCapabilities");
936 jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(IIIIII)V");
937
938 jint bandwidthCap = caps.atsc3Caps().bandwidthCap;
939 jint modulationCap = caps.atsc3Caps().modulationCap;
940 jint timeInterleaveModeCap = caps.atsc3Caps().timeInterleaveModeCap;
941 jint codeRateCap = caps.atsc3Caps().codeRateCap;
942 jint fecCap = caps.atsc3Caps().fecCap;
943 jint demodOutputFormatCap = caps.atsc3Caps().demodOutputFormatCap;
944
945 return env->NewObject(clazz, capsInit, bandwidthCap, modulationCap, timeInterleaveModeCap,
946 codeRateCap, fecCap, demodOutputFormatCap);
947}
948
shubang66cc3aa2020-04-06 17:10:01 -0700949jobject JTuner::getAtscFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) {
shubang51cc62f2020-01-28 18:00:22 -0800950 jclass clazz = env->FindClass("android/media/tv/tuner/frontend/AtscFrontendCapabilities");
951 jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(I)V");
952
953 jint modulationCap = caps.atscCaps().modulationCap;
954
955 return env->NewObject(clazz, capsInit, modulationCap);
956}
957
shubang66cc3aa2020-04-06 17:10:01 -0700958jobject JTuner::getDvbcFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) {
shubang51cc62f2020-01-28 18:00:22 -0800959 jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbcFrontendCapabilities");
960 jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(III)V");
961
962 jint modulationCap = caps.dvbcCaps().modulationCap;
963 jint fecCap = caps.dvbcCaps().fecCap;
964 jint annexCap = caps.dvbcCaps().annexCap;
965
966 return env->NewObject(clazz, capsInit, modulationCap, fecCap, annexCap);
967}
968
shubang66cc3aa2020-04-06 17:10:01 -0700969jobject JTuner::getDvbsFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) {
shubang51cc62f2020-01-28 18:00:22 -0800970 jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbsFrontendCapabilities");
971 jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(IJI)V");
972
973 jint modulationCap = caps.dvbsCaps().modulationCap;
974 jlong innerfecCap = caps.dvbsCaps().innerfecCap;
975 jint standard = caps.dvbsCaps().standard;
976
977 return env->NewObject(clazz, capsInit, modulationCap, innerfecCap, standard);
978}
979
shubang66cc3aa2020-04-06 17:10:01 -0700980jobject JTuner::getDvbtFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) {
shubang51cc62f2020-01-28 18:00:22 -0800981 jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbtFrontendCapabilities");
982 jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(IIIIIIZZ)V");
983
984 jint transmissionModeCap = caps.dvbtCaps().transmissionModeCap;
985 jint bandwidthCap = caps.dvbtCaps().bandwidthCap;
986 jint constellationCap = caps.dvbtCaps().constellationCap;
987 jint coderateCap = caps.dvbtCaps().coderateCap;
988 jint hierarchyCap = caps.dvbtCaps().hierarchyCap;
989 jint guardIntervalCap = caps.dvbtCaps().guardIntervalCap;
990 jboolean isT2Supported = caps.dvbtCaps().isT2Supported;
991 jboolean isMisoSupported = caps.dvbtCaps().isMisoSupported;
992
993 return env->NewObject(clazz, capsInit, transmissionModeCap, bandwidthCap, constellationCap,
994 coderateCap, hierarchyCap, guardIntervalCap, isT2Supported, isMisoSupported);
995}
996
shubang66cc3aa2020-04-06 17:10:01 -0700997jobject JTuner::getIsdbs3FrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) {
shubang51cc62f2020-01-28 18:00:22 -0800998 jclass clazz = env->FindClass("android/media/tv/tuner/frontend/Isdbs3FrontendCapabilities");
999 jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(II)V");
1000
1001 jint modulationCap = caps.isdbs3Caps().modulationCap;
1002 jint coderateCap = caps.isdbs3Caps().coderateCap;
1003
1004 return env->NewObject(clazz, capsInit, modulationCap, coderateCap);
1005}
1006
shubang66cc3aa2020-04-06 17:10:01 -07001007jobject JTuner::getIsdbsFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) {
shubang51cc62f2020-01-28 18:00:22 -08001008 jclass clazz = env->FindClass("android/media/tv/tuner/frontend/IsdbsFrontendCapabilities");
1009 jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(II)V");
1010
1011 jint modulationCap = caps.isdbsCaps().modulationCap;
1012 jint coderateCap = caps.isdbsCaps().coderateCap;
1013
1014 return env->NewObject(clazz, capsInit, modulationCap, coderateCap);
1015}
1016
shubang66cc3aa2020-04-06 17:10:01 -07001017jobject JTuner::getIsdbtFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) {
shubang51cc62f2020-01-28 18:00:22 -08001018 jclass clazz = env->FindClass("android/media/tv/tuner/frontend/IsdbtFrontendCapabilities");
1019 jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(IIIII)V");
1020
1021 jint modeCap = caps.isdbtCaps().modeCap;
1022 jint bandwidthCap = caps.isdbtCaps().bandwidthCap;
1023 jint modulationCap = caps.isdbtCaps().modulationCap;
1024 jint coderateCap = caps.isdbtCaps().coderateCap;
1025 jint guardIntervalCap = caps.isdbtCaps().guardIntervalCap;
1026
1027 return env->NewObject(clazz, capsInit, modeCap, bandwidthCap, modulationCap, coderateCap,
1028 guardIntervalCap);
1029}
1030
1031jobject JTuner::getFrontendInfo(int id) {
1032 FrontendInfo feInfo;
1033 Result res;
1034 mTuner->getFrontendInfo(id, [&](Result r, const FrontendInfo& info) {
1035 feInfo = info;
1036 res = r;
1037 });
1038 if (res != Result::SUCCESS) {
1039 return NULL;
1040 }
1041
1042 JNIEnv *env = AndroidRuntime::getJNIEnv();
1043 jclass clazz = env->FindClass("android/media/tv/tuner/frontend/FrontendInfo");
1044 jmethodID infoInit = env->GetMethodID(clazz, "<init>",
1045 "(IIIIIIII[ILandroid/media/tv/tuner/frontend/FrontendCapabilities;)V");
1046
1047 jint type = (jint) feInfo.type;
1048 jint minFrequency = feInfo.minFrequency;
1049 jint maxFrequency = feInfo.maxFrequency;
1050 jint minSymbolRate = feInfo.minSymbolRate;
1051 jint maxSymbolRate = feInfo.maxSymbolRate;
1052 jint acquireRange = feInfo.acquireRange;
1053 jint exclusiveGroupId = feInfo.exclusiveGroupId;
1054 jintArray statusCaps = env->NewIntArray(feInfo.statusCaps.size());
1055 env->SetIntArrayRegion(
1056 statusCaps, 0, feInfo.statusCaps.size(),
1057 reinterpret_cast<jint*>(&feInfo.statusCaps[0]));
1058 FrontendInfo::FrontendCapabilities caps = feInfo.frontendCaps;
1059
1060 jobject jcaps = NULL;
1061 switch(feInfo.type) {
1062 case FrontendType::ANALOG:
shubang66cc3aa2020-04-06 17:10:01 -07001063 if (FrontendInfo::FrontendCapabilities::hidl_discriminator::analogCaps
1064 == caps.getDiscriminator()) {
1065 jcaps = getAnalogFrontendCaps(env, caps);
1066 }
shubang51cc62f2020-01-28 18:00:22 -08001067 break;
1068 case FrontendType::ATSC3:
shubang66cc3aa2020-04-06 17:10:01 -07001069 if (FrontendInfo::FrontendCapabilities::hidl_discriminator::atsc3Caps
1070 == caps.getDiscriminator()) {
1071 jcaps = getAtsc3FrontendCaps(env, caps);
1072 }
shubang51cc62f2020-01-28 18:00:22 -08001073 break;
1074 case FrontendType::ATSC:
shubang66cc3aa2020-04-06 17:10:01 -07001075 if (FrontendInfo::FrontendCapabilities::hidl_discriminator::atscCaps
1076 == caps.getDiscriminator()) {
1077 jcaps = getAtscFrontendCaps(env, caps);
1078 }
shubang51cc62f2020-01-28 18:00:22 -08001079 break;
1080 case FrontendType::DVBC:
shubang66cc3aa2020-04-06 17:10:01 -07001081 if (FrontendInfo::FrontendCapabilities::hidl_discriminator::dvbcCaps
1082 == caps.getDiscriminator()) {
1083 jcaps = getDvbcFrontendCaps(env, caps);
1084 }
shubang51cc62f2020-01-28 18:00:22 -08001085 break;
1086 case FrontendType::DVBS:
shubang66cc3aa2020-04-06 17:10:01 -07001087 if (FrontendInfo::FrontendCapabilities::hidl_discriminator::dvbsCaps
1088 == caps.getDiscriminator()) {
1089 jcaps = getDvbsFrontendCaps(env, caps);
1090 }
shubang51cc62f2020-01-28 18:00:22 -08001091 break;
1092 case FrontendType::DVBT:
shubang66cc3aa2020-04-06 17:10:01 -07001093 if (FrontendInfo::FrontendCapabilities::hidl_discriminator::dvbtCaps
1094 == caps.getDiscriminator()) {
1095 jcaps = getDvbtFrontendCaps(env, caps);
1096 }
shubang51cc62f2020-01-28 18:00:22 -08001097 break;
1098 case FrontendType::ISDBS:
shubang66cc3aa2020-04-06 17:10:01 -07001099 if (FrontendInfo::FrontendCapabilities::hidl_discriminator::isdbsCaps
1100 == caps.getDiscriminator()) {
1101 jcaps = getIsdbsFrontendCaps(env, caps);
1102 }
shubang51cc62f2020-01-28 18:00:22 -08001103 break;
1104 case FrontendType::ISDBS3:
shubang66cc3aa2020-04-06 17:10:01 -07001105 if (FrontendInfo::FrontendCapabilities::hidl_discriminator::isdbs3Caps
1106 == caps.getDiscriminator()) {
1107 jcaps = getIsdbs3FrontendCaps(env, caps);
1108 }
shubang51cc62f2020-01-28 18:00:22 -08001109 break;
1110 case FrontendType::ISDBT:
shubang66cc3aa2020-04-06 17:10:01 -07001111 if (FrontendInfo::FrontendCapabilities::hidl_discriminator::isdbtCaps
1112 == caps.getDiscriminator()) {
1113 jcaps = getIsdbtFrontendCaps(env, caps);
1114 }
shubang51cc62f2020-01-28 18:00:22 -08001115 break;
1116 default:
1117 break;
1118 }
1119
1120 return env->NewObject(
1121 clazz, infoInit, (jint) id, type, minFrequency, maxFrequency, minSymbolRate,
1122 maxSymbolRate, acquireRange, exclusiveGroupId, statusCaps, jcaps);
1123}
1124
shubang0dc83942020-04-02 17:19:31 -07001125jintArray JTuner::getLnbIds() {
shubang760f0312019-11-12 17:11:28 -08001126 ALOGD("JTuner::getLnbIds()");
shubang0dc83942020-04-02 17:19:31 -07001127 Result res;
1128 hidl_vec<LnbId> lnbIds;
1129 mTuner->getLnbIds([&](Result r, const hidl_vec<LnbId>& ids) {
1130 lnbIds = ids;
1131 res = r;
shubang760f0312019-11-12 17:11:28 -08001132 });
shubangb3bfffe2020-03-26 17:44:31 -07001133 if (res != Result::SUCCESS || lnbIds.size() == 0) {
shubang760f0312019-11-12 17:11:28 -08001134 ALOGW("Lnb isn't available");
1135 return NULL;
1136 }
1137
shubang0dc83942020-04-02 17:19:31 -07001138 mLnbIds = lnbIds;
shubang760f0312019-11-12 17:11:28 -08001139 JNIEnv *env = AndroidRuntime::getJNIEnv();
shubang760f0312019-11-12 17:11:28 -08001140
shubang0dc83942020-04-02 17:19:31 -07001141 jintArray ids = env->NewIntArray(mLnbIds.size());
1142 env->SetIntArrayRegion(ids, 0, mLnbIds.size(), reinterpret_cast<jint*>(&mLnbIds[0]));
shubang760f0312019-11-12 17:11:28 -08001143
shubang0dc83942020-04-02 17:19:31 -07001144 return ids;
shubang760f0312019-11-12 17:11:28 -08001145}
1146
1147jobject JTuner::openLnbById(int id) {
shubang1c1144e2020-03-03 18:00:17 -08001148 sp<ILnb> iLnbSp;
shubangd295be02020-03-27 17:08:11 -07001149 Result r;
1150 mTuner->openLnbById(id, [&](Result res, const sp<ILnb>& lnb) {
1151 r = res;
shubang1c1144e2020-03-03 18:00:17 -08001152 iLnbSp = lnb;
shubang760f0312019-11-12 17:11:28 -08001153 });
shubangd295be02020-03-27 17:08:11 -07001154 if (r != Result::SUCCESS || iLnbSp == nullptr) {
shubang760f0312019-11-12 17:11:28 -08001155 ALOGE("Failed to open lnb");
1156 return NULL;
1157 }
shubang1c1144e2020-03-03 18:00:17 -08001158 mLnb = iLnbSp;
shubang760f0312019-11-12 17:11:28 -08001159
1160 JNIEnv *env = AndroidRuntime::getJNIEnv();
shubang1c1144e2020-03-03 18:00:17 -08001161 jobject lnbObj = env->NewObject(
shubangd351b822020-01-22 17:29:18 -08001162 env->FindClass("android/media/tv/tuner/Lnb"),
shubang760f0312019-11-12 17:11:28 -08001163 gFields.lnbInitID,
shubang1c1144e2020-03-03 18:00:17 -08001164 (jint) id);
1165
shubangd295be02020-03-27 17:08:11 -07001166 sp<LnbCallback> lnbCb = new LnbCallback(lnbObj, id);
1167 mLnb->setCallback(lnbCb);
1168
shubang1c1144e2020-03-03 18:00:17 -08001169 sp<Lnb> lnbSp = new Lnb(iLnbSp, lnbObj);
1170 lnbSp->incStrong(lnbObj);
1171 env->SetLongField(lnbObj, gFields.lnbContext, (jlong) lnbSp.get());
1172
1173 return lnbObj;
shubang760f0312019-11-12 17:11:28 -08001174}
1175
shubang757602f2020-03-06 15:23:41 -08001176jobject JTuner::openLnbByName(jstring name) {
1177 JNIEnv *env = AndroidRuntime::getJNIEnv();
1178 std::string lnbName(env->GetStringUTFChars(name, nullptr));
1179 sp<ILnb> iLnbSp;
1180 Result res;
1181 LnbId id;
1182 mTuner->openLnbByName(lnbName, [&](Result r, LnbId lnbId, const sp<ILnb>& lnb) {
1183 res = r;
1184 iLnbSp = lnb;
1185 id = lnbId;
1186 });
1187 if (res != Result::SUCCESS || iLnbSp == nullptr) {
1188 ALOGE("Failed to open lnb");
1189 return NULL;
1190 }
1191 mLnb = iLnbSp;
shubang757602f2020-03-06 15:23:41 -08001192
1193 jobject lnbObj = env->NewObject(
1194 env->FindClass("android/media/tv/tuner/Lnb"),
1195 gFields.lnbInitID,
1196 id);
1197
shubangd295be02020-03-27 17:08:11 -07001198 sp<LnbCallback> lnbCb = new LnbCallback(lnbObj, id);
1199 mLnb->setCallback(lnbCb);
1200
shubang757602f2020-03-06 15:23:41 -08001201 sp<Lnb> lnbSp = new Lnb(iLnbSp, lnbObj);
1202 lnbSp->incStrong(lnbObj);
1203 env->SetLongField(lnbObj, gFields.lnbContext, (jlong) lnbSp.get());
1204
1205 return lnbObj;
1206}
1207
shubang74bfd482019-10-29 19:10:22 -07001208int JTuner::tune(const FrontendSettings& settings) {
1209 if (mFe == NULL) {
1210 ALOGE("frontend is not initialized");
1211 return (int)Result::INVALID_STATE;
1212 }
1213 Result result = mFe->tune(settings);
1214 return (int)result;
1215}
1216
shubange32fb412020-01-28 14:53:05 -08001217int JTuner::stopTune() {
1218 if (mFe == NULL) {
1219 ALOGE("frontend is not initialized");
1220 return (int)Result::INVALID_STATE;
1221 }
1222 Result result = mFe->stopTune();
1223 return (int)result;
1224}
1225
shubangd5b845f2019-12-11 15:29:09 -08001226int JTuner::scan(const FrontendSettings& settings, FrontendScanType scanType) {
1227 if (mFe == NULL) {
1228 ALOGE("frontend is not initialized");
1229 return (int)Result::INVALID_STATE;
1230 }
1231 Result result = mFe->scan(settings, scanType);
1232 return (int)result;
1233}
1234
shubange32fb412020-01-28 14:53:05 -08001235int JTuner::stopScan() {
1236 if (mFe == NULL) {
1237 ALOGE("frontend is not initialized");
1238 return (int)Result::INVALID_STATE;
1239 }
1240 Result result = mFe->stopScan();
1241 return (int)result;
1242}
1243
1244int JTuner::setLnb(int id) {
1245 if (mFe == NULL) {
1246 ALOGE("frontend is not initialized");
1247 return (int)Result::INVALID_STATE;
1248 }
1249 Result result = mFe->setLnb(id);
1250 return (int)result;
1251}
1252
1253int JTuner::setLna(bool enable) {
1254 if (mFe == NULL) {
1255 ALOGE("frontend is not initialized");
1256 return (int)Result::INVALID_STATE;
1257 }
1258 Result result = mFe->setLna(enable);
1259 return (int)result;
1260}
1261
shubangbee73462020-02-07 17:48:02 -08001262Result JTuner::openDemux() {
shubang6f473d62019-11-01 15:42:21 -07001263 if (mTuner == nullptr) {
shubangbee73462020-02-07 17:48:02 -08001264 return Result::NOT_INITIALIZED;
shubang6f473d62019-11-01 15:42:21 -07001265 }
1266 if (mDemux != nullptr) {
shubangbee73462020-02-07 17:48:02 -08001267 return Result::SUCCESS;
shubang6f473d62019-11-01 15:42:21 -07001268 }
shubangbee73462020-02-07 17:48:02 -08001269 Result res;
shubangd295be02020-03-27 17:08:11 -07001270 uint32_t id;
1271 sp<IDemux> demuxSp;
shubangbee73462020-02-07 17:48:02 -08001272 mTuner->openDemux([&](Result r, uint32_t demuxId, const sp<IDemux>& demux) {
shubangd295be02020-03-27 17:08:11 -07001273 demuxSp = demux;
1274 id = demuxId;
shubangbee73462020-02-07 17:48:02 -08001275 res = r;
shubang6f473d62019-11-01 15:42:21 -07001276 ALOGD("open demux, id = %d", demuxId);
1277 });
shubangd295be02020-03-27 17:08:11 -07001278 if (res == Result::SUCCESS) {
1279 mDemux = demuxSp;
1280 mDemuxId = id;
1281 if (mFe != NULL) {
1282 mDemux->setFrontendDataSource(mFeId);
1283 }
1284 }
shubangbee73462020-02-07 17:48:02 -08001285 return res;
1286}
1287
shubang2f9cab32020-04-10 18:00:56 -07001288jint JTuner::close() {
1289 Result res = Result::SUCCESS;
1290 if (mFe != NULL) {
1291 res = mFe->close();
1292 if (res != Result::SUCCESS) {
1293 return (jint) res;
1294 }
1295 }
1296 if (mDemux != NULL) {
1297 res = mDemux->close();
1298 if (res != Result::SUCCESS) {
1299 return (jint) res;
1300 }
1301 }
1302 return (jint) res;
1303}
1304
shubangbee73462020-02-07 17:48:02 -08001305jobject JTuner::getAvSyncHwId(sp<Filter> filter) {
1306 if (mDemux == NULL) {
1307 return NULL;
shubang6f473d62019-11-01 15:42:21 -07001308 }
shubangbee73462020-02-07 17:48:02 -08001309
1310 uint32_t avSyncHwId;
1311 Result res;
1312 sp<IFilter> iFilterSp = filter->getIFilter();
1313 mDemux->getAvSyncHwId(iFilterSp,
1314 [&](Result r, uint32_t id) {
1315 res = r;
1316 avSyncHwId = id;
1317 });
1318 if (res == Result::SUCCESS) {
1319 JNIEnv *env = AndroidRuntime::getJNIEnv();
1320 jclass integerClazz = env->FindClass("java/lang/Integer");
1321 jmethodID intInit = env->GetMethodID(integerClazz, "<init>", "(I)V");
1322 return env->NewObject(integerClazz, intInit, avSyncHwId);
1323 }
1324 return NULL;
1325}
1326
1327jobject JTuner::getAvSyncTime(jint id) {
1328 if (mDemux == NULL) {
1329 return NULL;
1330 }
1331 uint64_t time;
1332 Result res;
1333 mDemux->getAvSyncTime(static_cast<uint32_t>(id),
1334 [&](Result r, uint64_t ts) {
1335 res = r;
1336 time = ts;
1337 });
1338 if (res == Result::SUCCESS) {
1339 JNIEnv *env = AndroidRuntime::getJNIEnv();
1340 jclass longClazz = env->FindClass("java/lang/Long");
1341 jmethodID longInit = env->GetMethodID(longClazz, "<init>", "(J)V");
1342 return env->NewObject(longClazz, longInit, static_cast<jlong>(time));
1343 }
1344 return NULL;
1345}
1346
1347int JTuner::connectCiCam(jint id) {
1348 if (mDemux == NULL) {
1349 Result r = openDemux();
1350 if (r != Result::SUCCESS) {
1351 return (int) r;
1352 }
1353 }
1354 Result r = mDemux->connectCiCam(static_cast<uint32_t>(id));
1355 return (int) r;
1356}
1357
1358int JTuner::disconnectCiCam() {
1359 if (mDemux == NULL) {
1360 Result r = openDemux();
1361 if (r != Result::SUCCESS) {
1362 return (int) r;
1363 }
1364 }
1365 Result r = mDemux->disconnectCiCam();
1366 return (int) r;
shubang6f473d62019-11-01 15:42:21 -07001367}
1368
shubang13f15e02019-11-04 17:51:02 -08001369jobject JTuner::openDescrambler() {
1370 ALOGD("JTuner::openDescrambler");
shubang40454db2020-03-30 16:52:29 -07001371 if (mTuner == nullptr || mDemux == nullptr) {
shubang13f15e02019-11-04 17:51:02 -08001372 return NULL;
1373 }
1374 sp<IDescrambler> descramblerSp;
shubang40454db2020-03-30 16:52:29 -07001375 Result res;
1376 mTuner->openDescrambler([&](Result r, const sp<IDescrambler>& descrambler) {
1377 res = r;
shubang13f15e02019-11-04 17:51:02 -08001378 descramblerSp = descrambler;
1379 });
1380
shubang40454db2020-03-30 16:52:29 -07001381 if (res != Result::SUCCESS || descramblerSp == NULL) {
shubang13f15e02019-11-04 17:51:02 -08001382 return NULL;
1383 }
1384
shubang40454db2020-03-30 16:52:29 -07001385 descramblerSp->setDemuxSource(mDemuxId);
1386
shubang13f15e02019-11-04 17:51:02 -08001387 JNIEnv *env = AndroidRuntime::getJNIEnv();
1388 jobject descramblerObj =
1389 env->NewObject(
shubangd351b822020-01-22 17:29:18 -08001390 env->FindClass("android/media/tv/tuner/Descrambler"),
shubang40454db2020-03-30 16:52:29 -07001391 gFields.descramblerInitID);
shubang13f15e02019-11-04 17:51:02 -08001392
1393 descramblerSp->incStrong(descramblerObj);
1394 env->SetLongField(descramblerObj, gFields.descramblerContext, (jlong)descramblerSp.get());
1395
1396 return descramblerObj;
1397}
1398
shubang6f473d62019-11-01 15:42:21 -07001399jobject JTuner::openFilter(DemuxFilterType type, int bufferSize) {
1400 if (mDemux == NULL) {
shubangbee73462020-02-07 17:48:02 -08001401 if (openDemux() != Result::SUCCESS) {
shubang6f473d62019-11-01 15:42:21 -07001402 return NULL;
1403 }
1404 }
1405
shubang7648a3c2019-11-25 18:16:45 -08001406 sp<IFilter> iFilterSp;
shubangcdf30de2019-11-06 17:28:38 -08001407 sp<FilterCallback> callback = new FilterCallback();
shubang40454db2020-03-30 16:52:29 -07001408 Result res;
shubangcdf30de2019-11-06 17:28:38 -08001409 mDemux->openFilter(type, bufferSize, callback,
shubang40454db2020-03-30 16:52:29 -07001410 [&](Result r, const sp<IFilter>& filter) {
shubang7648a3c2019-11-25 18:16:45 -08001411 iFilterSp = filter;
shubang40454db2020-03-30 16:52:29 -07001412 res = r;
shubang6f473d62019-11-01 15:42:21 -07001413 });
shubang40454db2020-03-30 16:52:29 -07001414 if (res != Result::SUCCESS || iFilterSp == NULL) {
shubang6f473d62019-11-01 15:42:21 -07001415 ALOGD("Failed to open filter, type = %d", type.mainType);
1416 return NULL;
1417 }
1418 int fId;
shubang7648a3c2019-11-25 18:16:45 -08001419 iFilterSp->getId([&](Result, uint32_t filterId) {
shubang6f473d62019-11-01 15:42:21 -07001420 fId = filterId;
1421 });
shubang6f473d62019-11-01 15:42:21 -07001422
1423 JNIEnv *env = AndroidRuntime::getJNIEnv();
shubangcdf30de2019-11-06 17:28:38 -08001424 jobject filterObj =
1425 env->NewObject(
shubangd351b822020-01-22 17:29:18 -08001426 env->FindClass("android/media/tv/tuner/filter/Filter"),
shubangcdf30de2019-11-06 17:28:38 -08001427 gFields.filterInitID,
shubangcdf30de2019-11-06 17:28:38 -08001428 (jint) fId);
1429
shubang7648a3c2019-11-25 18:16:45 -08001430 sp<Filter> filterSp = new Filter(iFilterSp, filterObj);
shubangcdf30de2019-11-06 17:28:38 -08001431 filterSp->incStrong(filterObj);
1432 env->SetLongField(filterObj, gFields.filterContext, (jlong)filterSp.get());
1433
1434 callback->setFilter(filterObj);
1435
1436 return filterObj;
shubang6f473d62019-11-01 15:42:21 -07001437}
1438
shubangf657da22020-02-05 16:27:06 -08001439jobject JTuner::openTimeFilter() {
1440 if (mDemux == NULL) {
shubangbee73462020-02-07 17:48:02 -08001441 if (openDemux() != Result::SUCCESS) {
shubangf657da22020-02-05 16:27:06 -08001442 return NULL;
1443 }
1444 }
1445 sp<ITimeFilter> iTimeFilterSp;
1446 Result res;
1447 mDemux->openTimeFilter(
1448 [&](Result r, const sp<ITimeFilter>& filter) {
1449 iTimeFilterSp = filter;
1450 res = r;
1451 });
1452
1453 if (res != Result::SUCCESS || iTimeFilterSp == NULL) {
1454 return NULL;
1455 }
1456
1457 JNIEnv *env = AndroidRuntime::getJNIEnv();
1458 jobject timeFilterObj =
1459 env->NewObject(
1460 env->FindClass("android/media/tv/tuner/filter/TimeFilter"),
1461 gFields.timeFilterInitID);
1462 sp<TimeFilter> timeFilterSp = new TimeFilter(iTimeFilterSp, timeFilterObj);
1463 timeFilterSp->incStrong(timeFilterObj);
1464 env->SetLongField(timeFilterObj, gFields.timeFilterContext, (jlong)timeFilterSp.get());
1465
1466 return timeFilterObj;
1467}
1468
shubang5637a662020-02-27 18:06:21 -08001469jobject JTuner::openDvr(DvrType type, jlong bufferSize) {
shubang4a0eddf2019-11-08 17:10:18 -08001470 ALOGD("JTuner::openDvr");
1471 if (mDemux == NULL) {
shubangbee73462020-02-07 17:48:02 -08001472 if (openDemux() != Result::SUCCESS) {
shubang4a0eddf2019-11-08 17:10:18 -08001473 return NULL;
1474 }
1475 }
shubang9e700ff2019-12-04 16:26:51 -08001476 sp<IDvr> iDvrSp;
shubang4a0eddf2019-11-08 17:10:18 -08001477 sp<DvrCallback> callback = new DvrCallback();
shubang5637a662020-02-27 18:06:21 -08001478 Result res;
1479 mDemux->openDvr(type, (uint32_t) bufferSize, callback,
1480 [&](Result r, const sp<IDvr>& dvr) {
1481 res = r;
shubang9e700ff2019-12-04 16:26:51 -08001482 iDvrSp = dvr;
shubang4a0eddf2019-11-08 17:10:18 -08001483 });
1484
shubang5637a662020-02-27 18:06:21 -08001485 if (res != Result::SUCCESS || iDvrSp == NULL) {
shubang4a0eddf2019-11-08 17:10:18 -08001486 return NULL;
1487 }
1488
1489 JNIEnv *env = AndroidRuntime::getJNIEnv();
shubang5637a662020-02-27 18:06:21 -08001490 jobject dvrObj;
1491 if (type == DvrType::RECORD) {
1492 dvrObj =
1493 env->NewObject(
1494 env->FindClass("android/media/tv/tuner/dvr/DvrRecorder"),
1495 gFields.dvrRecorderInitID,
1496 mObject);
1497 sp<Dvr> dvrSp = new Dvr(iDvrSp, dvrObj);
1498 dvrSp->incStrong(dvrObj);
1499 env->SetLongField(dvrObj, gFields.dvrRecorderContext, (jlong)dvrSp.get());
1500 } else {
1501 dvrObj =
1502 env->NewObject(
1503 env->FindClass("android/media/tv/tuner/dvr/DvrPlayback"),
1504 gFields.dvrPlaybackInitID,
1505 mObject);
1506 sp<Dvr> dvrSp = new Dvr(iDvrSp, dvrObj);
1507 dvrSp->incStrong(dvrObj);
1508 env->SetLongField(dvrObj, gFields.dvrPlaybackContext, (jlong)dvrSp.get());
1509 }
shubang4a0eddf2019-11-08 17:10:18 -08001510
1511 callback->setDvr(dvrObj);
1512
1513 return dvrObj;
1514}
1515
shubangc4b45702020-03-23 18:48:12 -07001516jobject JTuner::getDemuxCaps() {
1517 DemuxCapabilities caps;
1518 Result res;
1519 mTuner->getDemuxCaps([&](Result r, const DemuxCapabilities& demuxCaps) {
1520 caps = demuxCaps;
1521 res = r;
1522 });
1523 if (res != Result::SUCCESS) {
1524 return NULL;
1525 }
1526 JNIEnv *env = AndroidRuntime::getJNIEnv();
1527 jclass clazz = env->FindClass("android/media/tv/tuner/DemuxCapabilities");
1528 jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(IIIIIIIIIJI[IZ)V");
1529
1530 jint numDemux = caps.numDemux;
1531 jint numRecord = caps.numRecord;
1532 jint numPlayback = caps.numPlayback;
1533 jint numTsFilter = caps.numTsFilter;
1534 jint numSectionFilter = caps.numSectionFilter;
1535 jint numAudioFilter = caps.numAudioFilter;
1536 jint numVideoFilter = caps.numVideoFilter;
1537 jint numPesFilter = caps.numPesFilter;
1538 jint numPcrFilter = caps.numPcrFilter;
1539 jlong numBytesInSectionFilter = caps.numBytesInSectionFilter;
1540 jint filterCaps = static_cast<jint>(caps.filterCaps);
1541 jboolean bTimeFilter = caps.bTimeFilter;
1542
1543 jintArray linkCaps = env->NewIntArray(caps.linkCaps.size());
1544 env->SetIntArrayRegion(
1545 linkCaps, 0, caps.linkCaps.size(), reinterpret_cast<jint*>(&caps.linkCaps[0]));
1546
1547 return env->NewObject(clazz, capsInit, numDemux, numRecord, numPlayback, numTsFilter,
1548 numSectionFilter, numAudioFilter, numVideoFilter, numPesFilter, numPcrFilter,
1549 numBytesInSectionFilter, filterCaps, linkCaps, bTimeFilter);
1550}
1551
shubangb83f8232020-03-24 18:04:35 -07001552jobject JTuner::getFrontendStatus(jintArray types) {
1553 if (mFe == NULL) {
1554 return NULL;
1555 }
1556 JNIEnv *env = AndroidRuntime::getJNIEnv();
1557 jsize size = env->GetArrayLength(types);
1558 std::vector<FrontendStatusType> v(size);
1559 env->GetIntArrayRegion(types, 0, size, reinterpret_cast<jint*>(&v[0]));
1560
1561 Result res;
1562 hidl_vec<FrontendStatus> status;
1563 mFe->getStatus(v,
1564 [&](Result r, const hidl_vec<FrontendStatus>& s) {
1565 res = r;
1566 status = s;
1567 });
1568 if (res != Result::SUCCESS) {
1569 return NULL;
1570 }
1571
1572 jclass clazz = env->FindClass("android/media/tv/tuner/frontend/FrontendStatus");
1573 jmethodID init = env->GetMethodID(clazz, "<init>", "()V");
1574 jobject statusObj = env->NewObject(clazz, init);
1575
1576 jclass intClazz = env->FindClass("java/lang/Integer");
1577 jmethodID initInt = env->GetMethodID(intClazz, "<init>", "(I)V");
1578 jclass booleanClazz = env->FindClass("java/lang/Boolean");
1579 jmethodID initBoolean = env->GetMethodID(booleanClazz, "<init>", "(Z)V");
1580
1581 for (auto s : status) {
1582 switch(s.getDiscriminator()) {
1583 case FrontendStatus::hidl_discriminator::isDemodLocked: {
1584 jfieldID field = env->GetFieldID(clazz, "mIsDemodLocked", "Ljava/lang/Boolean;");
1585 jobject newBooleanObj = env->NewObject(
1586 booleanClazz, initBoolean, static_cast<jboolean>(s.isDemodLocked()));
1587 env->SetObjectField(statusObj, field, newBooleanObj);
1588 break;
1589 }
1590 case FrontendStatus::hidl_discriminator::snr: {
1591 jfieldID field = env->GetFieldID(clazz, "mSnr", "Ljava/lang/Integer;");
1592 jobject newIntegerObj = env->NewObject(
1593 intClazz, initInt, static_cast<jint>(s.snr()));
1594 env->SetObjectField(statusObj, field, newIntegerObj);
1595 break;
1596 }
1597 case FrontendStatus::hidl_discriminator::ber: {
1598 jfieldID field = env->GetFieldID(clazz, "mBer", "Ljava/lang/Integer;");
1599 jobject newIntegerObj = env->NewObject(
1600 intClazz, initInt, static_cast<jint>(s.ber()));
1601 env->SetObjectField(statusObj, field, newIntegerObj);
1602 break;
1603 }
1604 case FrontendStatus::hidl_discriminator::per: {
1605 jfieldID field = env->GetFieldID(clazz, "mPer", "Ljava/lang/Integer;");
1606 jobject newIntegerObj = env->NewObject(
1607 intClazz, initInt, static_cast<jint>(s.per()));
1608 env->SetObjectField(statusObj, field, newIntegerObj);
1609 break;
1610 }
1611 case FrontendStatus::hidl_discriminator::preBer: {
1612 jfieldID field = env->GetFieldID(clazz, "mPerBer", "Ljava/lang/Integer;");
1613 jobject newIntegerObj = env->NewObject(
1614 intClazz, initInt, static_cast<jint>(s.preBer()));
1615 env->SetObjectField(statusObj, field, newIntegerObj);
1616 break;
1617 }
1618 case FrontendStatus::hidl_discriminator::signalQuality: {
1619 jfieldID field = env->GetFieldID(clazz, "mSignalQuality", "Ljava/lang/Integer;");
1620 jobject newIntegerObj = env->NewObject(
1621 intClazz, initInt, static_cast<jint>(s.signalQuality()));
1622 env->SetObjectField(statusObj, field, newIntegerObj);
1623 break;
1624 }
1625 case FrontendStatus::hidl_discriminator::signalStrength: {
1626 jfieldID field = env->GetFieldID(clazz, "mSignalStrength", "Ljava/lang/Integer;");
1627 jobject newIntegerObj = env->NewObject(
1628 intClazz, initInt, static_cast<jint>(s.signalStrength()));
1629 env->SetObjectField(statusObj, field, newIntegerObj);
1630 break;
1631 }
1632 case FrontendStatus::hidl_discriminator::symbolRate: {
1633 jfieldID field = env->GetFieldID(clazz, "mSymbolRate", "Ljava/lang/Integer;");
1634 jobject newIntegerObj = env->NewObject(
1635 intClazz, initInt, static_cast<jint>(s.symbolRate()));
1636 env->SetObjectField(statusObj, field, newIntegerObj);
1637 break;
1638 }
1639 case FrontendStatus::hidl_discriminator::innerFec: {
1640 jfieldID field = env->GetFieldID(clazz, "mInnerFec", "Ljava/lang/Long;");
1641 jclass longClazz = env->FindClass("java/lang/Long");
1642 jmethodID initLong = env->GetMethodID(longClazz, "<init>", "(J)V");
1643 jobject newLongObj = env->NewObject(
1644 longClazz, initLong, static_cast<jlong>(s.innerFec()));
1645 env->SetObjectField(statusObj, field, newLongObj);
1646 break;
1647 }
1648 case FrontendStatus::hidl_discriminator::modulation: {
1649 jfieldID field = env->GetFieldID(clazz, "mModulation", "Ljava/lang/Integer;");
1650 FrontendModulationStatus modulation = s.modulation();
1651 jint intModulation;
1652 bool valid = true;
1653 switch(modulation.getDiscriminator()) {
1654 case FrontendModulationStatus::hidl_discriminator::dvbc: {
1655 intModulation = static_cast<jint>(modulation.dvbc());
1656 break;
1657 }
1658 case FrontendModulationStatus::hidl_discriminator::dvbs: {
1659 intModulation = static_cast<jint>(modulation.dvbs());
1660 break;
1661 }
1662 case FrontendModulationStatus::hidl_discriminator::isdbs: {
1663 intModulation = static_cast<jint>(modulation.isdbs());
1664 break;
1665 }
1666 case FrontendModulationStatus::hidl_discriminator::isdbs3: {
1667 intModulation = static_cast<jint>(modulation.isdbs3());
1668 break;
1669 }
1670 case FrontendModulationStatus::hidl_discriminator::isdbt: {
1671 intModulation = static_cast<jint>(modulation.isdbt());
1672 break;
1673 }
1674 default: {
1675 valid = false;
1676 break;
1677 }
1678 }
1679 if (valid) {
1680 jobject newIntegerObj = env->NewObject(intClazz, initInt, intModulation);
1681 env->SetObjectField(statusObj, field, newIntegerObj);
1682 }
1683 break;
1684 }
1685 case FrontendStatus::hidl_discriminator::inversion: {
1686 jfieldID field = env->GetFieldID(clazz, "mInversion", "Ljava/lang/Integer;");
1687 jobject newIntegerObj = env->NewObject(
1688 intClazz, initInt, static_cast<jint>(s.inversion()));
1689 env->SetObjectField(statusObj, field, newIntegerObj);
1690 break;
1691 }
1692 case FrontendStatus::hidl_discriminator::lnbVoltage: {
1693 jfieldID field = env->GetFieldID(clazz, "mLnbVoltage", "Ljava/lang/Integer;");
1694 jobject newIntegerObj = env->NewObject(
1695 intClazz, initInt, static_cast<jint>(s.lnbVoltage()));
1696 env->SetObjectField(statusObj, field, newIntegerObj);
1697 break;
1698 }
1699 case FrontendStatus::hidl_discriminator::plpId: {
1700 jfieldID field = env->GetFieldID(clazz, "mPlpId", "Ljava/lang/Integer;");
1701 jobject newIntegerObj = env->NewObject(
1702 intClazz, initInt, static_cast<jint>(s.plpId()));
1703 env->SetObjectField(statusObj, field, newIntegerObj);
1704 break;
1705 }
1706 case FrontendStatus::hidl_discriminator::isEWBS: {
1707 jfieldID field = env->GetFieldID(clazz, "mIsEwbs", "Ljava/lang/Boolean;");
1708 jobject newBooleanObj = env->NewObject(
1709 booleanClazz, initBoolean, static_cast<jboolean>(s.isEWBS()));
1710 env->SetObjectField(statusObj, field, newBooleanObj);
1711 break;
1712 }
1713 case FrontendStatus::hidl_discriminator::agc: {
1714 jfieldID field = env->GetFieldID(clazz, "mAgc", "Ljava/lang/Integer;");
1715 jobject newIntegerObj = env->NewObject(
1716 intClazz, initInt, static_cast<jint>(s.agc()));
1717 env->SetObjectField(statusObj, field, newIntegerObj);
1718 break;
1719 }
1720 case FrontendStatus::hidl_discriminator::isLnaOn: {
1721 jfieldID field = env->GetFieldID(clazz, "mIsLnaOn", "Ljava/lang/Boolean;");
1722 jobject newBooleanObj = env->NewObject(
1723 booleanClazz, initBoolean, static_cast<jboolean>(s.isLnaOn()));
1724 env->SetObjectField(statusObj, field, newBooleanObj);
1725 break;
1726 }
1727 case FrontendStatus::hidl_discriminator::isLayerError: {
1728 jfieldID field = env->GetFieldID(clazz, "mIsLayerErrors", "[Z");
1729 hidl_vec<bool> layerErr = s.isLayerError();
1730
1731 jbooleanArray valObj = env->NewBooleanArray(layerErr.size());
1732
1733 for (size_t i = 0; i < layerErr.size(); i++) {
1734 jboolean x = layerErr[i];
1735 env->SetBooleanArrayRegion(valObj, i, 1, &x);
1736 }
1737 env->SetObjectField(statusObj, field, valObj);
1738 break;
1739 }
1740 case FrontendStatus::hidl_discriminator::mer: {
1741 jfieldID field = env->GetFieldID(clazz, "mMer", "Ljava/lang/Integer;");
1742 jobject newIntegerObj = env->NewObject(
1743 intClazz, initInt, static_cast<jint>(s.mer()));
1744 env->SetObjectField(statusObj, field, newIntegerObj);
1745 break;
1746 }
1747 case FrontendStatus::hidl_discriminator::freqOffset: {
1748 jfieldID field = env->GetFieldID(clazz, "mFreqOffset", "Ljava/lang/Integer;");
1749 jobject newIntegerObj = env->NewObject(
1750 intClazz, initInt, static_cast<jint>(s.freqOffset()));
1751 env->SetObjectField(statusObj, field, newIntegerObj);
1752 break;
1753 }
1754 case FrontendStatus::hidl_discriminator::hierarchy: {
1755 jfieldID field = env->GetFieldID(clazz, "mHierarchy", "Ljava/lang/Integer;");
1756 jobject newIntegerObj = env->NewObject(
1757 intClazz, initInt, static_cast<jint>(s.hierarchy()));
1758 env->SetObjectField(statusObj, field, newIntegerObj);
1759 break;
1760 }
1761 case FrontendStatus::hidl_discriminator::isRfLocked: {
1762 jfieldID field = env->GetFieldID(clazz, "mIsRfLocked", "Ljava/lang/Boolean;");
1763 jobject newBooleanObj = env->NewObject(
1764 booleanClazz, initBoolean, static_cast<jboolean>(s.isRfLocked()));
1765 env->SetObjectField(statusObj, field, newBooleanObj);
1766 break;
1767 }
1768 case FrontendStatus::hidl_discriminator::plpInfo: {
1769 jfieldID field = env->GetFieldID(clazz, "mPlpInfo",
1770 "[Landroid/media/tv/tuner/frontend/FrontendStatus$Atsc3PlpTuningInfo;");
1771 jclass plpClazz = env->FindClass(
1772 "android/media/tv/tuner/frontend/FrontendStatus$Atsc3PlpTuningInfo");
1773 jmethodID initPlp = env->GetMethodID(plpClazz, "<init>", "(IZI)V");
1774
1775 hidl_vec<FrontendStatusAtsc3PlpInfo> plpInfos = s.plpInfo();
1776
1777 jobjectArray valObj = env->NewObjectArray(plpInfos.size(), plpClazz, NULL);
1778 for (int i = 0; i < plpInfos.size(); i++) {
1779 auto info = plpInfos[i];
1780 jint plpId = (jint) info.plpId;
1781 jboolean isLocked = (jboolean) info.isLocked;
1782 jint uec = (jint) info.uec;
1783
1784 jobject plpObj = env->NewObject(plpClazz, initPlp, plpId, isLocked, uec);
1785 env->SetObjectArrayElement(valObj, i, plpObj);
1786 }
1787
1788 env->SetObjectField(statusObj, field, valObj);
1789 break;
1790 }
1791 default: {
1792 break;
1793 }
1794 }
1795 }
1796
1797 return statusObj;
1798}
1799
shubangb3bfffe2020-03-26 17:44:31 -07001800jint JTuner::closeFrontend() {
1801 Result r = Result::SUCCESS;
1802 if (mFe != NULL) {
1803 r = mFe->close();
1804 }
1805 return (jint) r;
1806}
1807
1808jint JTuner::closeDemux() {
1809 Result r = Result::SUCCESS;
1810 if (mDemux != NULL) {
1811 r = mDemux->close();
1812 }
1813 return (jint) r;
1814}
1815
shubang8ab43b12019-10-18 15:55:55 -07001816} // namespace android
1817
1818////////////////////////////////////////////////////////////////////////////////
1819
1820using namespace android;
1821
1822static sp<JTuner> setTuner(JNIEnv *env, jobject thiz, const sp<JTuner> &tuner) {
shubang13f15e02019-11-04 17:51:02 -08001823 sp<JTuner> old = (JTuner *)env->GetLongField(thiz, gFields.tunerContext);
shubang8ab43b12019-10-18 15:55:55 -07001824
1825 if (tuner != NULL) {
1826 tuner->incStrong(thiz);
1827 }
1828 if (old != NULL) {
1829 old->decStrong(thiz);
1830 }
shubang13f15e02019-11-04 17:51:02 -08001831 env->SetLongField(thiz, gFields.tunerContext, (jlong)tuner.get());
shubang8ab43b12019-10-18 15:55:55 -07001832
1833 return old;
1834}
1835
1836static sp<JTuner> getTuner(JNIEnv *env, jobject thiz) {
shubang13f15e02019-11-04 17:51:02 -08001837 return (JTuner *)env->GetLongField(thiz, gFields.tunerContext);
1838}
1839
1840static sp<IDescrambler> getDescrambler(JNIEnv *env, jobject descrambler) {
1841 return (IDescrambler *)env->GetLongField(descrambler, gFields.descramblerContext);
1842}
1843
shubangc18cc102020-03-12 16:28:45 -07001844static uint32_t getResourceIdFromHandle(jint handle) {
1845 return (handle & 0x00ff0000) >> 16;
1846}
1847
shubang13f15e02019-11-04 17:51:02 -08001848static DemuxPid getDemuxPid(int pidType, int pid) {
1849 DemuxPid demuxPid;
1850 if ((int)pidType == 1) {
1851 demuxPid.tPid(static_cast<DemuxTpid>(pid));
1852 } else if ((int)pidType == 2) {
1853 demuxPid.mmtpPid(static_cast<DemuxMmtpPid>(pid));
1854 }
1855 return demuxPid;
shubang8ab43b12019-10-18 15:55:55 -07001856}
1857
shubangdeb067c2020-01-27 13:21:55 -08001858static uint32_t getFrontendSettingsFreq(JNIEnv *env, const jobject& settings) {
shubangd351b822020-01-22 17:29:18 -08001859 jclass clazz = env->FindClass("android/media/tv/tuner/frontend/FrontendSettings");
shubang964e6132019-11-26 15:05:22 -08001860 jfieldID freqField = env->GetFieldID(clazz, "mFrequency", "I");
shubangdeb067c2020-01-27 13:21:55 -08001861 uint32_t freq = static_cast<uint32_t>(env->GetIntField(settings, freqField));
1862 return freq;
1863}
shubang74bfd482019-10-29 19:10:22 -07001864
shubangdeb067c2020-01-27 13:21:55 -08001865static FrontendSettings getAnalogFrontendSettings(JNIEnv *env, const jobject& settings) {
1866 FrontendSettings frontendSettings;
1867 uint32_t freq = getFrontendSettingsFreq(env, settings);
1868 jclass clazz = env->FindClass("android/media/tv/tuner/frontend/AnalogFrontendSettings");
1869 FrontendAnalogType analogType =
1870 static_cast<FrontendAnalogType>(
1871 env->GetIntField(settings, env->GetFieldID(clazz, "mSignalType", "I")));
1872 FrontendAnalogSifStandard sifStandard =
1873 static_cast<FrontendAnalogSifStandard>(
1874 env->GetIntField(settings, env->GetFieldID(clazz, "mSifStandard", "I")));
1875 FrontendAnalogSettings frontendAnalogSettings {
1876 .frequency = freq,
1877 .type = analogType,
1878 .sifStandard = sifStandard,
1879 };
1880 frontendSettings.analog(frontendAnalogSettings);
shubang74bfd482019-10-29 19:10:22 -07001881 return frontendSettings;
1882}
1883
shubangdeb067c2020-01-27 13:21:55 -08001884static hidl_vec<FrontendAtsc3PlpSettings> getAtsc3PlpSettings(
1885 JNIEnv *env, const jobject& settings) {
1886 jclass clazz = env->FindClass("android/media/tv/tuner/frontend/Atsc3FrontendSettings");
1887 jobjectArray plpSettings =
1888 reinterpret_cast<jobjectArray>(
1889 env->GetObjectField(settings,
1890 env->GetFieldID(
1891 clazz,
1892 "mPlpSettings",
1893 "[Landroid/media/tv/tuner/frontend/Atsc3PlpSettings;")));
1894 int len = env->GetArrayLength(plpSettings);
1895
1896 jclass plpClazz = env->FindClass("android/media/tv/tuner/frontend/Atsc3PlpSettings");
1897 hidl_vec<FrontendAtsc3PlpSettings> plps = hidl_vec<FrontendAtsc3PlpSettings>(len);
1898 // parse PLP settings
1899 for (int i = 0; i < len; i++) {
1900 jobject plp = env->GetObjectArrayElement(plpSettings, i);
1901 uint8_t plpId =
1902 static_cast<uint8_t>(
1903 env->GetIntField(plp, env->GetFieldID(plpClazz, "mPlpId", "I")));
1904 FrontendAtsc3Modulation modulation =
1905 static_cast<FrontendAtsc3Modulation>(
1906 env->GetIntField(plp, env->GetFieldID(plpClazz, "mModulation", "I")));
1907 FrontendAtsc3TimeInterleaveMode interleaveMode =
1908 static_cast<FrontendAtsc3TimeInterleaveMode>(
1909 env->GetIntField(
1910 plp, env->GetFieldID(plpClazz, "mInterleaveMode", "I")));
1911 FrontendAtsc3CodeRate codeRate =
1912 static_cast<FrontendAtsc3CodeRate>(
1913 env->GetIntField(plp, env->GetFieldID(plpClazz, "mCodeRate", "I")));
1914 FrontendAtsc3Fec fec =
1915 static_cast<FrontendAtsc3Fec>(
1916 env->GetIntField(plp, env->GetFieldID(plpClazz, "mFec", "I")));
1917 FrontendAtsc3PlpSettings frontendAtsc3PlpSettings {
1918 .plpId = plpId,
1919 .modulation = modulation,
1920 .interleaveMode = interleaveMode,
1921 .codeRate = codeRate,
1922 .fec = fec,
1923 };
1924 plps[i] = frontendAtsc3PlpSettings;
1925 }
1926 return plps;
1927}
1928
1929static FrontendSettings getAtsc3FrontendSettings(JNIEnv *env, const jobject& settings) {
1930 FrontendSettings frontendSettings;
1931 uint32_t freq = getFrontendSettingsFreq(env, settings);
1932 jclass clazz = env->FindClass("android/media/tv/tuner/frontend/Atsc3FrontendSettings");
1933
1934 FrontendAtsc3Bandwidth bandwidth =
1935 static_cast<FrontendAtsc3Bandwidth>(
1936 env->GetIntField(settings, env->GetFieldID(clazz, "mBandwidth", "I")));
1937 FrontendAtsc3DemodOutputFormat demod =
1938 static_cast<FrontendAtsc3DemodOutputFormat>(
1939 env->GetIntField(
1940 settings, env->GetFieldID(clazz, "mDemodOutputFormat", "I")));
1941 hidl_vec<FrontendAtsc3PlpSettings> plps = getAtsc3PlpSettings(env, settings);
1942 FrontendAtsc3Settings frontendAtsc3Settings {
1943 .frequency = freq,
1944 .bandwidth = bandwidth,
1945 .demodOutputFormat = demod,
1946 .plpSettings = plps,
1947 };
1948 frontendSettings.atsc3(frontendAtsc3Settings);
1949 return frontendSettings;
1950}
1951
1952static FrontendSettings getAtscFrontendSettings(JNIEnv *env, const jobject& settings) {
1953 FrontendSettings frontendSettings;
1954 uint32_t freq = getFrontendSettingsFreq(env, settings);
1955 jclass clazz = env->FindClass("android/media/tv/tuner/frontend/AtscFrontendSettings");
1956 FrontendAtscModulation modulation =
1957 static_cast<FrontendAtscModulation>(
1958 env->GetIntField(settings, env->GetFieldID(clazz, "mModulation", "I")));
1959 FrontendAtscSettings frontendAtscSettings {
1960 .frequency = freq,
1961 .modulation = modulation,
1962 };
1963 frontendSettings.atsc(frontendAtscSettings);
1964 return frontendSettings;
1965}
1966
1967static FrontendSettings getDvbcFrontendSettings(JNIEnv *env, const jobject& settings) {
1968 FrontendSettings frontendSettings;
1969 uint32_t freq = getFrontendSettingsFreq(env, settings);
1970 jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbcFrontendSettings");
1971 FrontendDvbcModulation modulation =
1972 static_cast<FrontendDvbcModulation>(
1973 env->GetIntField(settings, env->GetFieldID(clazz, "mModulation", "I")));
1974 FrontendInnerFec innerFec =
1975 static_cast<FrontendInnerFec>(
1976 env->GetLongField(settings, env->GetFieldID(clazz, "mFec", "J")));
1977 uint32_t symbolRate =
1978 static_cast<uint32_t>(
1979 env->GetIntField(settings, env->GetFieldID(clazz, "mSymbolRate", "I")));
1980 FrontendDvbcOuterFec outerFec =
1981 static_cast<FrontendDvbcOuterFec>(
1982 env->GetIntField(settings, env->GetFieldID(clazz, "mOuterFec", "I")));
1983 FrontendDvbcAnnex annex =
1984 static_cast<FrontendDvbcAnnex>(
1985 env->GetByteField(settings, env->GetFieldID(clazz, "mAnnex", "B")));
1986 FrontendDvbcSpectralInversion spectralInversion =
1987 static_cast<FrontendDvbcSpectralInversion>(
1988 env->GetIntField(
1989 settings, env->GetFieldID(clazz, "mSpectralInversion", "I")));
1990 FrontendDvbcSettings frontendDvbcSettings {
1991 .frequency = freq,
1992 .modulation = modulation,
1993 .fec = innerFec,
1994 .symbolRate = symbolRate,
1995 .outerFec = outerFec,
1996 .annex = annex,
1997 .spectralInversion = spectralInversion,
1998 };
1999 frontendSettings.dvbc(frontendDvbcSettings);
2000 return frontendSettings;
2001}
2002
2003static FrontendDvbsCodeRate getDvbsCodeRate(JNIEnv *env, const jobject& settings) {
2004 jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbsFrontendSettings");
2005 jobject jcodeRate =
2006 env->GetObjectField(settings,
2007 env->GetFieldID(
2008 clazz,
2009 "mCodeRate",
2010 "Landroid/media/tv/tuner/frontend/DvbsCodeRate;"));
2011
2012 jclass codeRateClazz = env->FindClass("android/media/tv/tuner/frontend/DvbsCodeRate");
2013 FrontendInnerFec innerFec =
2014 static_cast<FrontendInnerFec>(
2015 env->GetLongField(
2016 jcodeRate, env->GetFieldID(codeRateClazz, "mInnerFec", "J")));
2017 bool isLinear =
2018 static_cast<bool>(
2019 env->GetBooleanField(
2020 jcodeRate, env->GetFieldID(codeRateClazz, "mIsLinear", "Z")));
2021 bool isShortFrames =
2022 static_cast<bool>(
2023 env->GetBooleanField(
2024 jcodeRate, env->GetFieldID(codeRateClazz, "mIsShortFrames", "Z")));
2025 uint32_t bitsPer1000Symbol =
2026 static_cast<uint32_t>(
2027 env->GetIntField(
2028 jcodeRate, env->GetFieldID(
2029 codeRateClazz, "mBitsPer1000Symbol", "I")));
2030 FrontendDvbsCodeRate coderate {
2031 .fec = innerFec,
2032 .isLinear = isLinear,
2033 .isShortFrames = isShortFrames,
2034 .bitsPer1000Symbol = bitsPer1000Symbol,
2035 };
2036 return coderate;
2037}
2038
2039static FrontendSettings getDvbsFrontendSettings(JNIEnv *env, const jobject& settings) {
2040 FrontendSettings frontendSettings;
2041 uint32_t freq = getFrontendSettingsFreq(env, settings);
2042 jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbsFrontendSettings");
2043
2044
2045 FrontendDvbsModulation modulation =
2046 static_cast<FrontendDvbsModulation>(
2047 env->GetIntField(settings, env->GetFieldID(clazz, "mModulation", "I")));
2048 uint32_t symbolRate =
2049 static_cast<uint32_t>(
2050 env->GetIntField(settings, env->GetFieldID(clazz, "mSymbolRate", "I")));
2051 FrontendDvbsRolloff rolloff =
2052 static_cast<FrontendDvbsRolloff>(
2053 env->GetIntField(settings, env->GetFieldID(clazz, "mRolloff", "I")));
2054 FrontendDvbsPilot pilot =
2055 static_cast<FrontendDvbsPilot>(
2056 env->GetIntField(settings, env->GetFieldID(clazz, "mPilot", "I")));
2057 uint32_t inputStreamId =
2058 static_cast<uint32_t>(
2059 env->GetIntField(settings, env->GetFieldID(clazz, "mInputStreamId", "I")));
2060 FrontendDvbsStandard standard =
2061 static_cast<FrontendDvbsStandard>(
2062 env->GetIntField(settings, env->GetFieldID(clazz, "mStandard", "I")));
2063 FrontendDvbsVcmMode vcmMode =
2064 static_cast<FrontendDvbsVcmMode>(
2065 env->GetIntField(settings, env->GetFieldID(clazz, "mVcmMode", "I")));
2066 FrontendDvbsCodeRate coderate = getDvbsCodeRate(env, settings);
2067
2068 FrontendDvbsSettings frontendDvbsSettings {
2069 .frequency = freq,
2070 .modulation = modulation,
2071 .coderate = coderate,
2072 .symbolRate = symbolRate,
2073 .rolloff = rolloff,
2074 .pilot = pilot,
2075 .inputStreamId = inputStreamId,
2076 .standard = standard,
2077 .vcmMode = vcmMode,
2078 };
2079 frontendSettings.dvbs(frontendDvbsSettings);
2080 return frontendSettings;
2081}
2082
2083static FrontendSettings getDvbtFrontendSettings(JNIEnv *env, const jobject& settings) {
2084 FrontendSettings frontendSettings;
2085 uint32_t freq = getFrontendSettingsFreq(env, settings);
2086 jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbtFrontendSettings");
2087 FrontendDvbtTransmissionMode transmissionMode =
2088 static_cast<FrontendDvbtTransmissionMode>(
2089 env->GetIntField(
2090 settings, env->GetFieldID(clazz, "mTransmissionMode", "I")));
2091 FrontendDvbtBandwidth bandwidth =
2092 static_cast<FrontendDvbtBandwidth>(
2093 env->GetIntField(settings, env->GetFieldID(clazz, "mBandwidth", "I")));
2094 FrontendDvbtConstellation constellation =
2095 static_cast<FrontendDvbtConstellation>(
2096 env->GetIntField(settings, env->GetFieldID(clazz, "mConstellation", "I")));
2097 FrontendDvbtHierarchy hierarchy =
2098 static_cast<FrontendDvbtHierarchy>(
2099 env->GetIntField(settings, env->GetFieldID(clazz, "mHierarchy", "I")));
2100 FrontendDvbtCoderate hpCoderate =
2101 static_cast<FrontendDvbtCoderate>(
2102 env->GetIntField(settings, env->GetFieldID(clazz, "mHpCodeRate", "I")));
2103 FrontendDvbtCoderate lpCoderate =
2104 static_cast<FrontendDvbtCoderate>(
2105 env->GetIntField(settings, env->GetFieldID(clazz, "mLpCodeRate", "I")));
2106 FrontendDvbtGuardInterval guardInterval =
2107 static_cast<FrontendDvbtGuardInterval>(
2108 env->GetIntField(settings, env->GetFieldID(clazz, "mGuardInterval", "I")));
2109 bool isHighPriority =
2110 static_cast<bool>(
2111 env->GetBooleanField(
2112 settings, env->GetFieldID(clazz, "mIsHighPriority", "Z")));
2113 FrontendDvbtStandard standard =
2114 static_cast<FrontendDvbtStandard>(
2115 env->GetIntField(settings, env->GetFieldID(clazz, "mStandard", "I")));
2116 bool isMiso =
2117 static_cast<bool>(
2118 env->GetBooleanField(settings, env->GetFieldID(clazz, "mIsMiso", "Z")));
2119 FrontendDvbtPlpMode plpMode =
2120 static_cast<FrontendDvbtPlpMode>(
2121 env->GetIntField(settings, env->GetFieldID(clazz, "mPlpMode", "I")));
2122 uint8_t plpId =
2123 static_cast<uint8_t>(
2124 env->GetIntField(settings, env->GetFieldID(clazz, "mPlpId", "I")));
2125 uint8_t plpGroupId =
2126 static_cast<uint8_t>(
2127 env->GetIntField(settings, env->GetFieldID(clazz, "mPlpGroupId", "I")));
2128
2129 FrontendDvbtSettings frontendDvbtSettings {
2130 .frequency = freq,
2131 .transmissionMode = transmissionMode,
2132 .bandwidth = bandwidth,
2133 .constellation = constellation,
2134 .hierarchy = hierarchy,
2135 .hpCoderate = hpCoderate,
2136 .lpCoderate = lpCoderate,
2137 .guardInterval = guardInterval,
2138 .isHighPriority = isHighPriority,
2139 .standard = standard,
2140 .isMiso = isMiso,
2141 .plpMode = plpMode,
2142 .plpId = plpId,
2143 .plpGroupId = plpGroupId,
2144 };
2145 frontendSettings.dvbt(frontendDvbtSettings);
2146 return frontendSettings;
2147}
2148
2149static FrontendSettings getIsdbsFrontendSettings(JNIEnv *env, const jobject& settings) {
2150 FrontendSettings frontendSettings;
2151 uint32_t freq = getFrontendSettingsFreq(env, settings);
2152 jclass clazz = env->FindClass("android/media/tv/tuner/frontend/IsdbsFrontendSettings");
2153 uint16_t streamId =
2154 static_cast<uint16_t>(
2155 env->GetIntField(settings, env->GetFieldID(clazz, "mStreamId", "I")));
2156 FrontendIsdbsStreamIdType streamIdType =
2157 static_cast<FrontendIsdbsStreamIdType>(
2158 env->GetIntField(settings, env->GetFieldID(clazz, "mStreamIdType", "I")));
2159 FrontendIsdbsModulation modulation =
2160 static_cast<FrontendIsdbsModulation>(
2161 env->GetIntField(settings, env->GetFieldID(clazz, "mModulation", "I")));
2162 FrontendIsdbsCoderate coderate =
2163 static_cast<FrontendIsdbsCoderate>(
2164 env->GetIntField(settings, env->GetFieldID(clazz, "mCodeRate", "I")));
2165 uint32_t symbolRate =
2166 static_cast<uint32_t>(
2167 env->GetIntField(settings, env->GetFieldID(clazz, "mSymbolRate", "I")));
2168 FrontendIsdbsRolloff rolloff =
2169 static_cast<FrontendIsdbsRolloff>(
2170 env->GetIntField(settings, env->GetFieldID(clazz, "mRolloff", "I")));
2171
2172 FrontendIsdbsSettings frontendIsdbsSettings {
2173 .frequency = freq,
2174 .streamId = streamId,
2175 .streamIdType = streamIdType,
2176 .modulation = modulation,
2177 .coderate = coderate,
2178 .symbolRate = symbolRate,
2179 .rolloff = rolloff,
2180 };
2181 frontendSettings.isdbs(frontendIsdbsSettings);
2182 return frontendSettings;
2183}
2184
2185static FrontendSettings getIsdbs3FrontendSettings(JNIEnv *env, const jobject& settings) {
2186 FrontendSettings frontendSettings;
2187 uint32_t freq = getFrontendSettingsFreq(env, settings);
2188 jclass clazz = env->FindClass("android/media/tv/tuner/frontend/Isdbs3FrontendSettings");
2189 uint16_t streamId =
2190 static_cast<uint16_t>(
2191 env->GetIntField(settings, env->GetFieldID(clazz, "mStreamId", "I")));
2192 FrontendIsdbsStreamIdType streamIdType =
2193 static_cast<FrontendIsdbsStreamIdType>(
2194 env->GetIntField(settings, env->GetFieldID(clazz, "mStreamIdType", "I")));
2195 FrontendIsdbs3Modulation modulation =
2196 static_cast<FrontendIsdbs3Modulation>(
2197 env->GetIntField(settings, env->GetFieldID(clazz, "mModulation", "I")));
2198 FrontendIsdbs3Coderate coderate =
2199 static_cast<FrontendIsdbs3Coderate>(
2200 env->GetIntField(settings, env->GetFieldID(clazz, "mCodeRate", "I")));
2201 uint32_t symbolRate =
2202 static_cast<uint32_t>(
2203 env->GetIntField(settings, env->GetFieldID(clazz, "mSymbolRate", "I")));
2204 FrontendIsdbs3Rolloff rolloff =
2205 static_cast<FrontendIsdbs3Rolloff>(
2206 env->GetIntField(settings, env->GetFieldID(clazz, "mRolloff", "I")));
2207
2208 FrontendIsdbs3Settings frontendIsdbs3Settings {
2209 .frequency = freq,
2210 .streamId = streamId,
2211 .streamIdType = streamIdType,
2212 .modulation = modulation,
2213 .coderate = coderate,
2214 .symbolRate = symbolRate,
2215 .rolloff = rolloff,
2216 };
2217 frontendSettings.isdbs3(frontendIsdbs3Settings);
2218 return frontendSettings;
2219}
2220
2221static FrontendSettings getIsdbtFrontendSettings(JNIEnv *env, const jobject& settings) {
2222 FrontendSettings frontendSettings;
2223 uint32_t freq = getFrontendSettingsFreq(env, settings);
2224 jclass clazz = env->FindClass("android/media/tv/tuner/frontend/IsdbtFrontendSettings");
2225 FrontendIsdbtModulation modulation =
2226 static_cast<FrontendIsdbtModulation>(
2227 env->GetIntField(settings, env->GetFieldID(clazz, "mModulation", "I")));
2228 FrontendIsdbtBandwidth bandwidth =
2229 static_cast<FrontendIsdbtBandwidth>(
2230 env->GetIntField(settings, env->GetFieldID(clazz, "mBandwidth", "I")));
2231 FrontendIsdbtMode mode =
2232 static_cast<FrontendIsdbtMode>(
2233 env->GetIntField(settings, env->GetFieldID(clazz, "mMode", "I")));
2234 FrontendIsdbtCoderate coderate =
2235 static_cast<FrontendIsdbtCoderate>(
2236 env->GetIntField(settings, env->GetFieldID(clazz, "mCodeRate", "I")));
2237 FrontendIsdbtGuardInterval guardInterval =
2238 static_cast<FrontendIsdbtGuardInterval>(
2239 env->GetIntField(settings, env->GetFieldID(clazz, "mGuardInterval", "I")));
2240 uint32_t serviceAreaId =
2241 static_cast<uint32_t>(
2242 env->GetIntField(settings, env->GetFieldID(clazz, "mServiceAreaId", "I")));
2243
2244 FrontendIsdbtSettings frontendIsdbtSettings {
2245 .frequency = freq,
2246 .modulation = modulation,
2247 .bandwidth = bandwidth,
2248 .mode = mode,
2249 .coderate = coderate,
2250 .guardInterval = guardInterval,
2251 .serviceAreaId = serviceAreaId,
2252 };
2253 frontendSettings.isdbt(frontendIsdbtSettings);
2254 return frontendSettings;
2255}
2256
2257static FrontendSettings getFrontendSettings(JNIEnv *env, int type, jobject settings) {
2258 ALOGD("getFrontendSettings %d", type);
2259
2260 FrontendType feType = static_cast<FrontendType>(type);
2261 switch(feType) {
2262 case FrontendType::ANALOG:
2263 return getAnalogFrontendSettings(env, settings);
2264 case FrontendType::ATSC3:
2265 return getAtsc3FrontendSettings(env, settings);
2266 case FrontendType::ATSC:
2267 return getAtscFrontendSettings(env, settings);
2268 case FrontendType::DVBC:
2269 return getDvbcFrontendSettings(env, settings);
2270 case FrontendType::DVBS:
2271 return getDvbsFrontendSettings(env, settings);
2272 case FrontendType::DVBT:
2273 return getDvbtFrontendSettings(env, settings);
2274 case FrontendType::ISDBS:
2275 return getIsdbsFrontendSettings(env, settings);
2276 case FrontendType::ISDBS3:
2277 return getIsdbs3FrontendSettings(env, settings);
2278 case FrontendType::ISDBT:
2279 return getIsdbtFrontendSettings(env, settings);
2280 default:
2281 // should never happen because a type is associated with a subclass of
2282 // FrontendSettings and not set by users
2283 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
2284 "Unsupported frontend type %d", type);
2285 return FrontendSettings();
2286 }
2287}
2288
shubang7648a3c2019-11-25 18:16:45 -08002289static sp<Filter> getFilter(JNIEnv *env, jobject filter) {
2290 return (Filter *)env->GetLongField(filter, gFields.filterContext);
shubangcdf30de2019-11-06 17:28:38 -08002291}
2292
shubang030afb52019-11-27 16:09:02 -08002293static DvrSettings getDvrSettings(JNIEnv *env, jobject settings) {
2294 DvrSettings dvrSettings;
shubangd351b822020-01-22 17:29:18 -08002295 jclass clazz = env->FindClass("android/media/tv/tuner/dvr/DvrSettings");
shubang030afb52019-11-27 16:09:02 -08002296 uint32_t statusMask =
2297 static_cast<uint32_t>(env->GetIntField(
2298 settings, env->GetFieldID(clazz, "mStatusMask", "I")));
2299 uint32_t lowThreshold =
2300 static_cast<uint32_t>(env->GetIntField(
2301 settings, env->GetFieldID(clazz, "mLowThreshold", "I")));
2302 uint32_t highThreshold =
2303 static_cast<uint32_t>(env->GetIntField(
2304 settings, env->GetFieldID(clazz, "mHighThreshold", "I")));
2305 uint8_t packetSize =
2306 static_cast<uint8_t>(env->GetIntField(
2307 settings, env->GetFieldID(clazz, "mPacketSize", "I")));
2308 DataFormat dataFormat =
2309 static_cast<DataFormat>(env->GetIntField(
2310 settings, env->GetFieldID(clazz, "mDataFormat", "I")));
2311 DvrType type =
2312 static_cast<DvrType>(env->GetIntField(
2313 settings, env->GetFieldID(clazz, "mType", "I")));
2314 if (type == DvrType::RECORD) {
2315 RecordSettings recordSettings {
2316 .statusMask = static_cast<unsigned char>(statusMask),
2317 .lowThreshold = lowThreshold,
2318 .highThreshold = highThreshold,
2319 .dataFormat = dataFormat,
2320 .packetSize = packetSize,
2321 };
2322 dvrSettings.record(recordSettings);
2323 } else if (type == DvrType::PLAYBACK) {
2324 PlaybackSettings PlaybackSettings {
2325 .statusMask = statusMask,
2326 .lowThreshold = lowThreshold,
2327 .highThreshold = highThreshold,
2328 .dataFormat = dataFormat,
2329 .packetSize = packetSize,
2330 };
2331 dvrSettings.playback(PlaybackSettings);
2332 }
2333 return dvrSettings;
2334}
2335
shubang9e700ff2019-12-04 16:26:51 -08002336static sp<Dvr> getDvr(JNIEnv *env, jobject dvr) {
shubang5637a662020-02-27 18:06:21 -08002337 bool isRecorder =
2338 env->IsInstanceOf(dvr, env->FindClass("android/media/tv/tuner/dvr/DvrRecorder"));
2339 jfieldID fieldId =
2340 isRecorder ? gFields.dvrRecorderContext : gFields.dvrPlaybackContext;
2341 return (Dvr *)env->GetLongField(dvr, fieldId);
shubang4a0eddf2019-11-08 17:10:18 -08002342}
2343
shubang8ab43b12019-10-18 15:55:55 -07002344static void android_media_tv_Tuner_native_init(JNIEnv *env) {
2345 jclass clazz = env->FindClass("android/media/tv/tuner/Tuner");
2346 CHECK(clazz != NULL);
2347
shubang13f15e02019-11-04 17:51:02 -08002348 gFields.tunerContext = env->GetFieldID(clazz, "mNativeContext", "J");
2349 CHECK(gFields.tunerContext != NULL);
shubang7e849b02019-10-18 19:36:25 -07002350
shubang4b8c5402019-10-24 17:49:53 -07002351 gFields.onFrontendEventID = env->GetMethodID(clazz, "onFrontendEvent", "(I)V");
2352
shubang7e849b02019-10-18 19:36:25 -07002353 jclass frontendClazz = env->FindClass("android/media/tv/tuner/Tuner$Frontend");
shubang4b8c5402019-10-24 17:49:53 -07002354 gFields.frontendInitID =
2355 env->GetMethodID(frontendClazz, "<init>", "(Landroid/media/tv/tuner/Tuner;I)V");
shubang6f473d62019-11-01 15:42:21 -07002356
shubangd351b822020-01-22 17:29:18 -08002357 jclass lnbClazz = env->FindClass("android/media/tv/tuner/Lnb");
shubang1c1144e2020-03-03 18:00:17 -08002358 gFields.lnbContext = env->GetFieldID(lnbClazz, "mNativeContext", "J");
shubang757602f2020-03-06 15:23:41 -08002359 gFields.lnbInitID = env->GetMethodID(lnbClazz, "<init>", "(I)V");
shubangd295be02020-03-27 17:08:11 -07002360 gFields.onLnbEventID = env->GetMethodID(lnbClazz, "onEvent", "(I)V");
2361 gFields.onLnbDiseqcMessageID = env->GetMethodID(lnbClazz, "onDiseqcMessage", "([B)V");
shubang760f0312019-11-12 17:11:28 -08002362
shubangd351b822020-01-22 17:29:18 -08002363 jclass filterClazz = env->FindClass("android/media/tv/tuner/filter/Filter");
shubangcdf30de2019-11-06 17:28:38 -08002364 gFields.filterContext = env->GetFieldID(filterClazz, "mNativeContext", "J");
shubang6f473d62019-11-01 15:42:21 -07002365 gFields.filterInitID =
shubangdeb067c2020-01-27 13:21:55 -08002366 env->GetMethodID(filterClazz, "<init>", "(I)V");
shubangcdf30de2019-11-06 17:28:38 -08002367 gFields.onFilterStatusID =
2368 env->GetMethodID(filterClazz, "onFilterStatus", "(I)V");
shubang3e0c37b2020-02-19 19:09:10 -08002369 gFields.onFilterEventID =
2370 env->GetMethodID(filterClazz, "onFilterEvent",
2371 "([Landroid/media/tv/tuner/filter/FilterEvent;)V");
shubang13f15e02019-11-04 17:51:02 -08002372
shubangf657da22020-02-05 16:27:06 -08002373 jclass timeFilterClazz = env->FindClass("android/media/tv/tuner/filter/TimeFilter");
2374 gFields.timeFilterContext = env->GetFieldID(timeFilterClazz, "mNativeContext", "J");
2375 gFields.timeFilterInitID = env->GetMethodID(timeFilterClazz, "<init>", "()V");
2376
shubangd351b822020-01-22 17:29:18 -08002377 jclass descramblerClazz = env->FindClass("android/media/tv/tuner/Descrambler");
shubang13f15e02019-11-04 17:51:02 -08002378 gFields.descramblerContext = env->GetFieldID(descramblerClazz, "mNativeContext", "J");
shubang40454db2020-03-30 16:52:29 -07002379 gFields.descramblerInitID = env->GetMethodID(descramblerClazz, "<init>", "()V");
shubang4a0eddf2019-11-08 17:10:18 -08002380
shubang5637a662020-02-27 18:06:21 -08002381 jclass dvrRecorderClazz = env->FindClass("android/media/tv/tuner/dvr/DvrRecorder");
2382 gFields.dvrRecorderContext = env->GetFieldID(dvrRecorderClazz, "mNativeContext", "J");
2383 gFields.dvrRecorderInitID = env->GetMethodID(dvrRecorderClazz, "<init>", "()V");
shubang431e5612020-03-30 21:24:56 -07002384 gFields.onDvrRecordStatusID =
2385 env->GetMethodID(dvrRecorderClazz, "onRecordStatusChanged", "(I)V");
shubang5637a662020-02-27 18:06:21 -08002386
2387 jclass dvrPlaybackClazz = env->FindClass("android/media/tv/tuner/dvr/DvrPlayback");
2388 gFields.dvrPlaybackContext = env->GetFieldID(dvrPlaybackClazz, "mNativeContext", "J");
2389 gFields.dvrPlaybackInitID = env->GetMethodID(dvrPlaybackClazz, "<init>", "()V");
shubang431e5612020-03-30 21:24:56 -07002390 gFields.onDvrPlaybackStatusID =
shubang66cc3aa2020-04-06 17:10:01 -07002391 env->GetMethodID(dvrPlaybackClazz, "onPlaybackStatusChanged", "(I)V");
shubangd49681e2020-02-17 21:32:30 -08002392
2393 jclass linearBlockClazz = env->FindClass("android/media/MediaCodec$LinearBlock");
2394 gFields.linearBlockInitID = env->GetMethodID(linearBlockClazz, "<init>", "()V");
2395 gFields.linearBlockSetInternalStateID =
2396 env->GetMethodID(linearBlockClazz, "setInternalStateLocked", "(JZ)V");
shubang8ab43b12019-10-18 15:55:55 -07002397}
2398
2399static void android_media_tv_Tuner_native_setup(JNIEnv *env, jobject thiz) {
2400 sp<JTuner> tuner = new JTuner(env, thiz);
2401 setTuner(env,thiz, tuner);
2402}
2403
shubang7e849b02019-10-18 19:36:25 -07002404static jobject android_media_tv_Tuner_get_frontend_ids(JNIEnv *env, jobject thiz) {
2405 sp<JTuner> tuner = getTuner(env, thiz);
2406 return tuner->getFrontendIds();
2407}
2408
shubangc18cc102020-03-12 16:28:45 -07002409static jobject android_media_tv_Tuner_open_frontend_by_handle(
2410 JNIEnv *env, jobject thiz, jint handle) {
shubang7e849b02019-10-18 19:36:25 -07002411 sp<JTuner> tuner = getTuner(env, thiz);
shubangc18cc102020-03-12 16:28:45 -07002412 uint32_t id = getResourceIdFromHandle(handle);
shubang7e849b02019-10-18 19:36:25 -07002413 return tuner->openFrontendById(id);
2414}
2415
shubang2f9cab32020-04-10 18:00:56 -07002416static jint android_media_tv_Tuner_close_frontend_by_handle(
2417 JNIEnv *env, jobject thiz, jint handle) {
2418 sp<JTuner> tuner = getTuner(env, thiz);
2419 uint32_t id = getResourceIdFromHandle(handle);
2420 return tuner->closeFrontendById(id);
2421}
2422
shubang74bfd482019-10-29 19:10:22 -07002423static int android_media_tv_Tuner_tune(JNIEnv *env, jobject thiz, jint type, jobject settings) {
2424 sp<JTuner> tuner = getTuner(env, thiz);
2425 return tuner->tune(getFrontendSettings(env, type, settings));
2426}
2427
shubange32fb412020-01-28 14:53:05 -08002428static int android_media_tv_Tuner_stop_tune(JNIEnv *env, jobject thiz) {
2429 sp<JTuner> tuner = getTuner(env, thiz);
2430 return tuner->stopTune();
shubange65b6862019-12-17 15:43:35 -08002431}
2432
shubangd5b845f2019-12-11 15:29:09 -08002433static int android_media_tv_Tuner_scan(
2434 JNIEnv *env, jobject thiz, jint settingsType, jobject settings, jint scanType) {
2435 sp<JTuner> tuner = getTuner(env, thiz);
2436 return tuner->scan(getFrontendSettings(
2437 env, settingsType, settings), static_cast<FrontendScanType>(scanType));
2438}
2439
shubange32fb412020-01-28 14:53:05 -08002440static int android_media_tv_Tuner_stop_scan(JNIEnv *env, jobject thiz) {
2441 sp<JTuner> tuner = getTuner(env, thiz);
2442 return tuner->stopScan();
shubange65b6862019-12-17 15:43:35 -08002443}
2444
shubange32fb412020-01-28 14:53:05 -08002445static int android_media_tv_Tuner_set_lnb(JNIEnv *env, jobject thiz, jint id) {
2446 sp<JTuner> tuner = getTuner(env, thiz);
2447 return tuner->setLnb(id);
shubang793e5702019-12-26 15:15:46 -08002448}
2449
shubange32fb412020-01-28 14:53:05 -08002450static int android_media_tv_Tuner_set_lna(JNIEnv *env, jobject thiz, jboolean enable) {
2451 sp<JTuner> tuner = getTuner(env, thiz);
2452 return tuner->setLna(enable);
shubange65b6862019-12-17 15:43:35 -08002453}
2454
shubangb83f8232020-03-24 18:04:35 -07002455static jobject android_media_tv_Tuner_get_frontend_status(
2456 JNIEnv* env, jobject thiz, jintArray types) {
2457 sp<JTuner> tuner = getTuner(env, thiz);
2458 return tuner->getFrontendStatus(types);
shubang1512ec12019-12-23 18:22:42 -08002459}
2460
shubangbee73462020-02-07 17:48:02 -08002461static jobject android_media_tv_Tuner_get_av_sync_hw_id(
2462 JNIEnv *env, jobject thiz, jobject filter) {
2463 sp<Filter> filterSp = getFilter(env, filter);
2464 if (filterSp == NULL) {
2465 ALOGD("Failed to get sync ID. Filter not found");
2466 return NULL;
2467 }
2468 sp<JTuner> tuner = getTuner(env, thiz);
2469 return tuner->getAvSyncHwId(filterSp);
shubang7343fee2019-12-27 12:02:08 -08002470}
2471
shubangbee73462020-02-07 17:48:02 -08002472static jobject android_media_tv_Tuner_get_av_sync_time(JNIEnv *env, jobject thiz, jint id) {
2473 sp<JTuner> tuner = getTuner(env, thiz);
2474 return tuner->getAvSyncTime(id);
shubang7343fee2019-12-27 12:02:08 -08002475}
2476
shubangbee73462020-02-07 17:48:02 -08002477static int android_media_tv_Tuner_connect_cicam(JNIEnv *env, jobject thiz, jint id) {
2478 sp<JTuner> tuner = getTuner(env, thiz);
2479 return tuner->connectCiCam(id);
shubang7343fee2019-12-27 12:02:08 -08002480}
2481
shubangbee73462020-02-07 17:48:02 -08002482static int android_media_tv_Tuner_disconnect_cicam(JNIEnv *env, jobject thiz) {
2483 sp<JTuner> tuner = getTuner(env, thiz);
2484 return tuner->disconnectCiCam();
shubang7343fee2019-12-27 12:02:08 -08002485}
2486
shubang51cc62f2020-01-28 18:00:22 -08002487static jobject android_media_tv_Tuner_get_frontend_info(JNIEnv *env, jobject thiz, jint id) {
2488 sp<JTuner> tuner = getTuner(env, thiz);
2489 return tuner->getFrontendInfo(id);
shubang95c1f752019-12-27 16:29:48 -08002490}
2491
shubang0dc83942020-04-02 17:19:31 -07002492static jintArray android_media_tv_Tuner_get_lnb_ids(JNIEnv *env, jobject thiz) {
shubang760f0312019-11-12 17:11:28 -08002493 sp<JTuner> tuner = getTuner(env, thiz);
2494 return tuner->getLnbIds();
2495}
2496
shubangc18cc102020-03-12 16:28:45 -07002497static jobject android_media_tv_Tuner_open_lnb_by_handle(JNIEnv *env, jobject thiz, jint handle) {
shubang760f0312019-11-12 17:11:28 -08002498 sp<JTuner> tuner = getTuner(env, thiz);
shubangc18cc102020-03-12 16:28:45 -07002499 uint32_t id = getResourceIdFromHandle(handle);
shubang760f0312019-11-12 17:11:28 -08002500 return tuner->openLnbById(id);
2501}
2502
shubang757602f2020-03-06 15:23:41 -08002503static jobject android_media_tv_Tuner_open_lnb_by_name(JNIEnv *env, jobject thiz, jstring name) {
2504 sp<JTuner> tuner = getTuner(env, thiz);
2505 return tuner->openLnbByName(name);
2506}
2507
2508
shubang6f473d62019-11-01 15:42:21 -07002509static jobject android_media_tv_Tuner_open_filter(
shubangd351b822020-01-22 17:29:18 -08002510 JNIEnv *env, jobject thiz, jint type, jint subType, jlong bufferSize) {
shubang6f473d62019-11-01 15:42:21 -07002511 sp<JTuner> tuner = getTuner(env, thiz);
shubangf657da22020-02-05 16:27:06 -08002512 DemuxFilterMainType mainType = static_cast<DemuxFilterMainType>(type);
shubang6f473d62019-11-01 15:42:21 -07002513 DemuxFilterType filterType {
shubangf657da22020-02-05 16:27:06 -08002514 .mainType = mainType,
shubang6f473d62019-11-01 15:42:21 -07002515 };
2516
shubangf657da22020-02-05 16:27:06 -08002517 switch(mainType) {
2518 case DemuxFilterMainType::TS:
2519 filterType.subType.tsFilterType(static_cast<DemuxTsFilterType>(subType));
2520 break;
2521 case DemuxFilterMainType::MMTP:
2522 filterType.subType.mmtpFilterType(static_cast<DemuxMmtpFilterType>(subType));
2523 break;
2524 case DemuxFilterMainType::IP:
2525 filterType.subType.ipFilterType(static_cast<DemuxIpFilterType>(subType));
2526 break;
2527 case DemuxFilterMainType::TLV:
2528 filterType.subType.tlvFilterType(static_cast<DemuxTlvFilterType>(subType));
2529 break;
2530 case DemuxFilterMainType::ALP:
2531 filterType.subType.alpFilterType(static_cast<DemuxAlpFilterType>(subType));
2532 break;
2533 }
shubang6f473d62019-11-01 15:42:21 -07002534
2535 return tuner->openFilter(filterType, bufferSize);
2536}
2537
shubangf657da22020-02-05 16:27:06 -08002538static jobject android_media_tv_Tuner_open_time_filter(JNIEnv *env, jobject thiz) {
2539 sp<JTuner> tuner = getTuner(env, thiz);
2540 return tuner->openTimeFilter();
shubang4347e2e2019-12-13 17:20:40 -08002541}
2542
shubang44fa1422020-01-30 11:42:59 -08002543static DemuxFilterSectionBits getFilterSectionBits(JNIEnv *env, const jobject& settings) {
2544 jclass clazz = env->FindClass("android/media/tv/tuner/filter/SectionSettingsWithSectionBits");
2545 jbyteArray jfilterBytes = static_cast<jbyteArray>(
2546 env->GetObjectField(settings, env->GetFieldID(clazz, "mFilter", "[B")));
2547 jsize size = env->GetArrayLength(jfilterBytes);
2548 std::vector<uint8_t> filterBytes(size);
2549 env->GetByteArrayRegion(
2550 jfilterBytes, 0, size, reinterpret_cast<jbyte*>(&filterBytes[0]));
2551
2552 jbyteArray jmask = static_cast<jbyteArray>(
2553 env->GetObjectField(settings, env->GetFieldID(clazz, "mMask", "[B")));
2554 size = env->GetArrayLength(jmask);
2555 std::vector<uint8_t> mask(size);
2556 env->GetByteArrayRegion(jmask, 0, size, reinterpret_cast<jbyte*>(&mask[0]));
2557
2558 jbyteArray jmode = static_cast<jbyteArray>(
2559 env->GetObjectField(settings, env->GetFieldID(clazz, "mMode", "[B")));
2560 size = env->GetArrayLength(jmode);
2561 std::vector<uint8_t> mode(size);
2562 env->GetByteArrayRegion(jmode, 0, size, reinterpret_cast<jbyte*>(&mode[0]));
2563
2564 DemuxFilterSectionBits filterSectionBits {
2565 .filter = filterBytes,
2566 .mask = mask,
2567 .mode = mode,
2568 };
2569 return filterSectionBits;
2570}
2571
2572static DemuxFilterSectionSettings::Condition::TableInfo getFilterTableInfo(
2573 JNIEnv *env, const jobject& settings) {
2574 jclass clazz = env->FindClass("android/media/tv/tuner/filter/SectionSettingsWithTableInfo");
2575 uint16_t tableId = static_cast<uint16_t>(
2576 env->GetIntField(settings, env->GetFieldID(clazz, "mTableId", "I")));
2577 uint16_t version = static_cast<uint16_t>(
2578 env->GetIntField(settings, env->GetFieldID(clazz, "mVersion", "I")));
2579 DemuxFilterSectionSettings::Condition::TableInfo tableInfo {
2580 .tableId = tableId,
2581 .version = version,
2582 };
2583 return tableInfo;
2584}
2585
2586static DemuxFilterSectionSettings getFilterSectionSettings(JNIEnv *env, const jobject& settings) {
2587 jclass clazz = env->FindClass("android/media/tv/tuner/filter/SectionSettings");
2588 bool isCheckCrc = static_cast<bool>(
2589 env->GetBooleanField(settings, env->GetFieldID(clazz, "mCrcEnabled", "Z")));
2590 bool isRepeat = static_cast<bool>(
2591 env->GetBooleanField(settings, env->GetFieldID(clazz, "mIsRepeat", "Z")));
2592 bool isRaw = static_cast<bool>(
2593 env->GetBooleanField(settings, env->GetFieldID(clazz, "mIsRaw", "Z")));
2594
2595 DemuxFilterSectionSettings filterSectionSettings {
2596 .isCheckCrc = isCheckCrc,
2597 .isRepeat = isRepeat,
2598 .isRaw = isRaw,
2599 };
2600 if (env->IsInstanceOf(
2601 settings,
2602 env->FindClass("android/media/tv/tuner/filter/SectionSettingsWithSectionBits"))) {
2603 filterSectionSettings.condition.sectionBits(getFilterSectionBits(env, settings));
2604 } else if (env->IsInstanceOf(
2605 settings,
2606 env->FindClass("android/media/tv/tuner/filter/SectionSettingsWithTableInfo"))) {
2607 filterSectionSettings.condition.tableInfo(getFilterTableInfo(env, settings));
2608 }
2609 return filterSectionSettings;
2610}
2611
2612static DemuxFilterAvSettings getFilterAvSettings(JNIEnv *env, const jobject& settings) {
2613 jclass clazz = env->FindClass("android/media/tv/tuner/filter/AvSettings");
2614 bool isPassthrough = static_cast<bool>(
2615 env->GetBooleanField(settings, env->GetFieldID(clazz, "mIsPassthrough", "Z")));
2616 DemuxFilterAvSettings filterAvSettings {
2617 .isPassthrough = isPassthrough,
2618 };
2619 return filterAvSettings;
2620}
2621
2622static DemuxFilterPesDataSettings getFilterPesDataSettings(JNIEnv *env, const jobject& settings) {
2623 jclass clazz = env->FindClass("android/media/tv/tuner/filter/PesSettings");
2624 uint16_t streamId = static_cast<uint16_t>(
2625 env->GetIntField(settings, env->GetFieldID(clazz, "mStreamId", "I")));
2626 bool isRaw = static_cast<bool>(
2627 env->GetBooleanField(settings, env->GetFieldID(clazz, "mIsRaw", "Z")));
2628 DemuxFilterPesDataSettings filterPesDataSettings {
2629 .streamId = streamId,
2630 .isRaw = isRaw,
2631 };
2632 return filterPesDataSettings;
2633}
2634
2635static DemuxFilterRecordSettings getFilterRecordSettings(JNIEnv *env, const jobject& settings) {
2636 jclass clazz = env->FindClass("android/media/tv/tuner/filter/RecordSettings");
2637 hidl_bitfield<DemuxTsIndex> tsIndexMask = static_cast<hidl_bitfield<DemuxTsIndex>>(
2638 env->GetIntField(settings, env->GetFieldID(clazz, "mTsIndexMask", "I")));
2639 DemuxRecordScIndexType scIndexType = static_cast<DemuxRecordScIndexType>(
2640 env->GetIntField(settings, env->GetFieldID(clazz, "mScIndexType", "I")));
2641 jint scIndexMask = env->GetIntField(settings, env->GetFieldID(clazz, "mScIndexMask", "I"));
2642
2643 DemuxFilterRecordSettings filterRecordSettings {
2644 .tsIndexMask = tsIndexMask,
2645 .scIndexType = scIndexType,
2646 };
2647 if (scIndexType == DemuxRecordScIndexType::SC) {
2648 filterRecordSettings.scIndexMask.sc(static_cast<hidl_bitfield<DemuxScIndex>>(scIndexMask));
2649 } else if (scIndexType == DemuxRecordScIndexType::SC_HEVC) {
2650 filterRecordSettings.scIndexMask.scHevc(
2651 static_cast<hidl_bitfield<DemuxScHevcIndex>>(scIndexMask));
2652 }
2653 return filterRecordSettings;
2654}
2655
2656static DemuxFilterDownloadSettings getFilterDownloadSettings(JNIEnv *env, const jobject& settings) {
2657 jclass clazz = env->FindClass("android/media/tv/tuner/filter/DownloadSettings");
2658 uint32_t downloadId = static_cast<uint32_t>(
2659 env->GetIntField(settings, env->GetFieldID(clazz, "mDownloadId", "I")));
2660
2661 DemuxFilterDownloadSettings filterDownloadSettings {
2662 .downloadId = downloadId,
2663 };
2664 return filterDownloadSettings;
2665}
2666
shubang87788c32020-02-04 13:55:23 -08002667static DemuxIpAddress getDemuxIpAddress(JNIEnv *env, const jobject& config) {
2668 jclass clazz = env->FindClass("android/media/tv/tuner/filter/IpFilterConfiguration");
2669
2670 jbyteArray jsrcIpAddress = static_cast<jbyteArray>(
2671 env->GetObjectField(config, env->GetFieldID(clazz, "mSrcIpAddress", "[B")));
2672 jsize srcSize = env->GetArrayLength(jsrcIpAddress);
2673 jbyteArray jdstIpAddress = static_cast<jbyteArray>(
2674 env->GetObjectField(config, env->GetFieldID(clazz, "mDstIpAddress", "[B")));
2675 jsize dstSize = env->GetArrayLength(jdstIpAddress);
2676
2677 DemuxIpAddress res;
2678
2679 if (srcSize != dstSize) {
2680 // should never happen. Validated on Java size.
2681 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
2682 "IP address lengths don't match. srcLength=%d, dstLength=%d", srcSize, dstSize);
2683 return res;
2684 }
2685
2686 if (srcSize == IP_V4_LENGTH) {
2687 uint8_t srcAddr[IP_V4_LENGTH];
2688 uint8_t dstAddr[IP_V4_LENGTH];
2689 env->GetByteArrayRegion(
2690 jsrcIpAddress, 0, srcSize, reinterpret_cast<jbyte*>(srcAddr));
2691 env->GetByteArrayRegion(
2692 jdstIpAddress, 0, dstSize, reinterpret_cast<jbyte*>(dstAddr));
2693 res.srcIpAddress.v4(srcAddr);
2694 res.dstIpAddress.v4(dstAddr);
2695 } else if (srcSize == IP_V6_LENGTH) {
2696 uint8_t srcAddr[IP_V6_LENGTH];
2697 uint8_t dstAddr[IP_V6_LENGTH];
2698 env->GetByteArrayRegion(
2699 jsrcIpAddress, 0, srcSize, reinterpret_cast<jbyte*>(srcAddr));
2700 env->GetByteArrayRegion(
2701 jdstIpAddress, 0, dstSize, reinterpret_cast<jbyte*>(dstAddr));
2702 res.srcIpAddress.v6(srcAddr);
2703 res.dstIpAddress.v6(dstAddr);
2704 } else {
2705 // should never happen. Validated on Java size.
2706 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
2707 "Invalid IP address length %d", srcSize);
2708 return res;
2709 }
2710
2711 uint16_t srcPort = static_cast<uint16_t>(
2712 env->GetIntField(config, env->GetFieldID(clazz, "mSrcPort", "I")));
2713 uint16_t dstPort = static_cast<uint16_t>(
2714 env->GetIntField(config, env->GetFieldID(clazz, "mDstPort", "I")));
2715
2716 res.srcPort = srcPort;
2717 res.dstPort = dstPort;
2718
2719 return res;
2720}
2721
shubang44fa1422020-01-30 11:42:59 -08002722static DemuxFilterSettings getFilterConfiguration(
shubang87788c32020-02-04 13:55:23 -08002723 JNIEnv *env, int type, int subtype, jobject filterConfigObj) {
shubang75c87082019-11-15 11:26:56 -08002724 DemuxFilterSettings filterSettings;
shubang75c87082019-11-15 11:26:56 -08002725 jobject settingsObj =
2726 env->GetObjectField(
shubang87788c32020-02-04 13:55:23 -08002727 filterConfigObj,
shubang75c87082019-11-15 11:26:56 -08002728 env->GetFieldID(
shubangd351b822020-01-22 17:29:18 -08002729 env->FindClass("android/media/tv/tuner/filter/FilterConfiguration"),
shubang75c87082019-11-15 11:26:56 -08002730 "mSettings",
shubangd351b822020-01-22 17:29:18 -08002731 "Landroid/media/tv/tuner/filter/Settings;"));
shubang44fa1422020-01-30 11:42:59 -08002732 DemuxFilterMainType mainType = static_cast<DemuxFilterMainType>(type);
2733 switch (mainType) {
2734 case DemuxFilterMainType::TS: {
2735 jclass clazz = env->FindClass("android/media/tv/tuner/filter/TsFilterConfiguration");
shubang87788c32020-02-04 13:55:23 -08002736 uint16_t tpid = static_cast<uint16_t>(
2737 env->GetIntField(filterConfigObj, env->GetFieldID(clazz, "mTpid", "I")));
shubang75c87082019-11-15 11:26:56 -08002738 DemuxTsFilterSettings tsFilterSettings {
shubang87788c32020-02-04 13:55:23 -08002739 .tpid = tpid,
shubang75c87082019-11-15 11:26:56 -08002740 };
shubang44fa1422020-01-30 11:42:59 -08002741
2742 DemuxTsFilterType tsType = static_cast<DemuxTsFilterType>(subtype);
2743 switch (tsType) {
2744 case DemuxTsFilterType::SECTION:
2745 tsFilterSettings.filterSettings.section(
2746 getFilterSectionSettings(env, settingsObj));
2747 break;
2748 case DemuxTsFilterType::AUDIO:
2749 case DemuxTsFilterType::VIDEO:
2750 tsFilterSettings.filterSettings.av(getFilterAvSettings(env, settingsObj));
2751 break;
2752 case DemuxTsFilterType::PES:
2753 tsFilterSettings.filterSettings.pesData(
2754 getFilterPesDataSettings(env, settingsObj));
2755 break;
2756 case DemuxTsFilterType::RECORD:
2757 tsFilterSettings.filterSettings.record(
2758 getFilterRecordSettings(env, settingsObj));
2759 break;
2760 default:
2761 break;
2762 }
shubang75c87082019-11-15 11:26:56 -08002763 filterSettings.ts(tsFilterSettings);
shubang44fa1422020-01-30 11:42:59 -08002764 break;
2765 }
2766 case DemuxFilterMainType::MMTP: {
shubang87788c32020-02-04 13:55:23 -08002767 jclass clazz = env->FindClass("android/media/tv/tuner/filter/MmtpFilterConfiguration");
2768 uint16_t mmtpPid = static_cast<uint16_t>(
2769 env->GetIntField(filterConfigObj, env->GetFieldID(clazz, "mMmtpPid", "I")));
2770 DemuxMmtpFilterSettings mmtpFilterSettings {
2771 .mmtpPid = mmtpPid,
2772 };
shubang44fa1422020-01-30 11:42:59 -08002773 DemuxMmtpFilterType mmtpType = static_cast<DemuxMmtpFilterType>(subtype);
2774 switch (mmtpType) {
2775 case DemuxMmtpFilterType::SECTION:
2776 mmtpFilterSettings.filterSettings.section(
2777 getFilterSectionSettings(env, settingsObj));
2778 break;
2779 case DemuxMmtpFilterType::AUDIO:
2780 case DemuxMmtpFilterType::VIDEO:
2781 mmtpFilterSettings.filterSettings.av(getFilterAvSettings(env, settingsObj));
2782 break;
2783 case DemuxMmtpFilterType::PES:
2784 mmtpFilterSettings.filterSettings.pesData(
2785 getFilterPesDataSettings(env, settingsObj));
2786 break;
2787 case DemuxMmtpFilterType::RECORD:
2788 mmtpFilterSettings.filterSettings.record(
2789 getFilterRecordSettings(env, settingsObj));
2790 break;
2791 case DemuxMmtpFilterType::DOWNLOAD:
2792 mmtpFilterSettings.filterSettings.download(
2793 getFilterDownloadSettings(env, settingsObj));
2794 break;
2795 default:
2796 break;
2797 }
2798 filterSettings.mmtp(mmtpFilterSettings);
2799 break;
2800 }
2801 case DemuxFilterMainType::IP: {
shubang87788c32020-02-04 13:55:23 -08002802 DemuxIpAddress ipAddr = getDemuxIpAddress(env, filterConfigObj);
2803
2804 DemuxIpFilterSettings ipFilterSettings {
2805 .ipAddr = ipAddr,
2806 };
shubang44fa1422020-01-30 11:42:59 -08002807 DemuxIpFilterType ipType = static_cast<DemuxIpFilterType>(subtype);
2808 switch (ipType) {
shubang87788c32020-02-04 13:55:23 -08002809 case DemuxIpFilterType::SECTION: {
shubang44fa1422020-01-30 11:42:59 -08002810 ipFilterSettings.filterSettings.section(
2811 getFilterSectionSettings(env, settingsObj));
2812 break;
shubang87788c32020-02-04 13:55:23 -08002813 }
2814 case DemuxIpFilterType::IP: {
2815 jclass clazz = env->FindClass(
2816 "android/media/tv/tuner/filter/IpFilterConfiguration");
2817 bool bPassthrough = static_cast<bool>(
2818 env->GetBooleanField(
2819 filterConfigObj, env->GetFieldID(
2820 clazz, "mPassthrough", "Z")));
2821 ipFilterSettings.filterSettings.bPassthrough(bPassthrough);
shubang44fa1422020-01-30 11:42:59 -08002822 break;
shubang87788c32020-02-04 13:55:23 -08002823 }
2824 default: {
shubang44fa1422020-01-30 11:42:59 -08002825 break;
shubang87788c32020-02-04 13:55:23 -08002826 }
shubang44fa1422020-01-30 11:42:59 -08002827 }
2828 filterSettings.ip(ipFilterSettings);
2829 break;
2830 }
2831 case DemuxFilterMainType::TLV: {
shubang87788c32020-02-04 13:55:23 -08002832 jclass clazz = env->FindClass("android/media/tv/tuner/filter/TlvFilterConfiguration");
2833 uint8_t packetType = static_cast<uint8_t>(
2834 env->GetIntField(filterConfigObj, env->GetFieldID(clazz, "mPacketType", "I")));
2835 bool isCompressedIpPacket = static_cast<bool>(
2836 env->GetBooleanField(
2837 filterConfigObj, env->GetFieldID(clazz, "mIsCompressedIpPacket", "Z")));
2838
2839 DemuxTlvFilterSettings tlvFilterSettings {
2840 .packetType = packetType,
2841 .isCompressedIpPacket = isCompressedIpPacket,
2842 };
shubang44fa1422020-01-30 11:42:59 -08002843 DemuxTlvFilterType tlvType = static_cast<DemuxTlvFilterType>(subtype);
2844 switch (tlvType) {
shubang87788c32020-02-04 13:55:23 -08002845 case DemuxTlvFilterType::SECTION: {
shubang44fa1422020-01-30 11:42:59 -08002846 tlvFilterSettings.filterSettings.section(
2847 getFilterSectionSettings(env, settingsObj));
2848 break;
shubang87788c32020-02-04 13:55:23 -08002849 }
2850 case DemuxTlvFilterType::TLV: {
2851 bool bPassthrough = static_cast<bool>(
2852 env->GetBooleanField(
2853 filterConfigObj, env->GetFieldID(
2854 clazz, "mPassthrough", "Z")));
2855 tlvFilterSettings.filterSettings.bPassthrough(bPassthrough);
shubang44fa1422020-01-30 11:42:59 -08002856 break;
shubang87788c32020-02-04 13:55:23 -08002857 }
2858 default: {
shubang44fa1422020-01-30 11:42:59 -08002859 break;
shubang87788c32020-02-04 13:55:23 -08002860 }
shubang44fa1422020-01-30 11:42:59 -08002861 }
2862 filterSettings.tlv(tlvFilterSettings);
2863 break;
2864 }
2865 case DemuxFilterMainType::ALP: {
shubang87788c32020-02-04 13:55:23 -08002866 jclass clazz = env->FindClass("android/media/tv/tuner/filter/AlpFilterConfiguration");
2867 uint8_t packetType = static_cast<uint8_t>(
2868 env->GetIntField(filterConfigObj, env->GetFieldID(clazz, "mPacketType", "I")));
2869 DemuxAlpLengthType lengthType = static_cast<DemuxAlpLengthType>(
2870 env->GetIntField(filterConfigObj, env->GetFieldID(clazz, "mLengthType", "I")));
2871 DemuxAlpFilterSettings alpFilterSettings {
2872 .packetType = packetType,
2873 .lengthType = lengthType,
2874 };
shubang44fa1422020-01-30 11:42:59 -08002875 DemuxAlpFilterType alpType = static_cast<DemuxAlpFilterType>(subtype);
2876 switch (alpType) {
2877 case DemuxAlpFilterType::SECTION:
2878 alpFilterSettings.filterSettings.section(
2879 getFilterSectionSettings(env, settingsObj));
2880 break;
2881 default:
2882 break;
2883 }
2884 filterSettings.alp(alpFilterSettings);
2885 break;
2886 }
2887 default: {
2888 break;
shubang75c87082019-11-15 11:26:56 -08002889 }
2890 }
2891 return filterSettings;
2892}
2893
shubang431e5612020-03-30 21:24:56 -07002894static jint copyData(JNIEnv *env, std::unique_ptr<MQ>& mq, EventFlag* flag, jbyteArray buffer,
2895 jlong offset, jlong size) {
shubanga06cfe52020-02-24 18:53:41 -08002896 ALOGD("copyData, size=%ld, offset=%ld", (long) size, (long) offset);
shubang964e6132019-11-26 15:05:22 -08002897
shubang431e5612020-03-30 21:24:56 -07002898 jlong available = mq->availableToRead();
shubanga06cfe52020-02-24 18:53:41 -08002899 ALOGD("copyData, available=%ld", (long) available);
shubang964e6132019-11-26 15:05:22 -08002900 size = std::min(size, available);
2901
2902 jboolean isCopy;
2903 jbyte *dst = env->GetByteArrayElements(buffer, &isCopy);
2904 ALOGD("copyData, isCopy=%d", isCopy);
2905 if (dst == nullptr) {
2906 ALOGD("Failed to GetByteArrayElements");
2907 return 0;
2908 }
2909
shubang431e5612020-03-30 21:24:56 -07002910 if (mq->read(reinterpret_cast<unsigned char*>(dst) + offset, size)) {
shubang964e6132019-11-26 15:05:22 -08002911 env->ReleaseByteArrayElements(buffer, dst, 0);
shubang431e5612020-03-30 21:24:56 -07002912 flag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
shubang964e6132019-11-26 15:05:22 -08002913 } else {
2914 ALOGD("Failed to read FMQ");
2915 env->ReleaseByteArrayElements(buffer, dst, 0);
2916 return 0;
2917 }
2918 return size;
2919}
2920
shubanga06cfe52020-02-24 18:53:41 -08002921static jint android_media_tv_Tuner_configure_filter(
shubang75c87082019-11-15 11:26:56 -08002922 JNIEnv *env, jobject filter, int type, int subtype, jobject settings) {
2923 ALOGD("configure filter type=%d, subtype=%d", type, subtype);
shubang964e6132019-11-26 15:05:22 -08002924 sp<Filter> filterSp = getFilter(env, filter);
2925 sp<IFilter> iFilterSp = filterSp->getIFilter();
2926 if (iFilterSp == NULL) {
shubang75c87082019-11-15 11:26:56 -08002927 ALOGD("Failed to configure filter: filter not found");
shubang40454db2020-03-30 16:52:29 -07002928 return (jint) Result::NOT_INITIALIZED;
shubang75c87082019-11-15 11:26:56 -08002929 }
shubang44fa1422020-01-30 11:42:59 -08002930 DemuxFilterSettings filterSettings = getFilterConfiguration(env, type, subtype, settings);
shubang964e6132019-11-26 15:05:22 -08002931 Result res = iFilterSp->configure(filterSettings);
shubanga06cfe52020-02-24 18:53:41 -08002932
2933 if (res != Result::SUCCESS) {
2934 return (jint) res;
2935 }
2936
shubang964e6132019-11-26 15:05:22 -08002937 MQDescriptorSync<uint8_t> filterMQDesc;
shubanga06cfe52020-02-24 18:53:41 -08002938 Result getQueueDescResult = Result::UNKNOWN_ERROR;
2939 if (filterSp->mFilterMQ == NULL) {
shubang964e6132019-11-26 15:05:22 -08002940 iFilterSp->getQueueDesc(
2941 [&](Result r, const MQDescriptorSync<uint8_t>& desc) {
2942 filterMQDesc = desc;
2943 getQueueDescResult = r;
2944 ALOGD("getFilterQueueDesc");
2945 });
2946 if (getQueueDescResult == Result::SUCCESS) {
shubang431e5612020-03-30 21:24:56 -07002947 filterSp->mFilterMQ = std::make_unique<MQ>(filterMQDesc, true);
shubang964e6132019-11-26 15:05:22 -08002948 EventFlag::createEventFlag(
2949 filterSp->mFilterMQ->getEventFlagWord(), &(filterSp->mFilterMQEventFlag));
2950 }
2951 }
shubanga06cfe52020-02-24 18:53:41 -08002952 return (jint) getQueueDescResult;
shubang75c87082019-11-15 11:26:56 -08002953}
2954
shubanga06cfe52020-02-24 18:53:41 -08002955static jint android_media_tv_Tuner_get_filter_id(JNIEnv* env, jobject filter) {
2956 sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
2957 if (iFilterSp == NULL) {
2958 ALOGD("Failed to get filter ID: filter not found");
shubang40454db2020-03-30 16:52:29 -07002959 return (int) Result::NOT_INITIALIZED;
shubanga06cfe52020-02-24 18:53:41 -08002960 }
2961 Result res;
2962 uint32_t id;
2963 iFilterSp->getId(
2964 [&](Result r, uint32_t filterId) {
2965 res = r;
2966 id = filterId;
2967 });
2968 if (res != Result::SUCCESS) {
2969 return (jint) Constant::INVALID_FILTER_ID;
2970 }
2971 return (jint) id;
shubang793e5702019-12-26 15:15:46 -08002972}
2973
shubanga06cfe52020-02-24 18:53:41 -08002974static jint android_media_tv_Tuner_set_filter_data_source(
2975 JNIEnv* env, jobject filter, jobject srcFilter) {
2976 sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
2977 if (iFilterSp == NULL) {
2978 ALOGD("Failed to set filter data source: filter not found");
shubang40454db2020-03-30 16:52:29 -07002979 return (jint) Result::NOT_INITIALIZED;
shubanga06cfe52020-02-24 18:53:41 -08002980 }
2981 Result r;
2982 if (srcFilter == NULL) {
2983 r = iFilterSp->setDataSource(NULL);
2984 } else {
2985 sp<IFilter> srcSp = getFilter(env, srcFilter)->getIFilter();
2986 if (iFilterSp == NULL) {
2987 ALOGD("Failed to set filter data source: src filter not found");
shubang40454db2020-03-30 16:52:29 -07002988 return (jint) Result::INVALID_ARGUMENT;
shubanga06cfe52020-02-24 18:53:41 -08002989 }
2990 r = iFilterSp->setDataSource(srcSp);
2991 }
2992 return (jint) r;
shubang793e5702019-12-26 15:15:46 -08002993}
2994
shubanga06cfe52020-02-24 18:53:41 -08002995static jint android_media_tv_Tuner_start_filter(JNIEnv *env, jobject filter) {
2996 sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
2997 if (iFilterSp == NULL) {
shubangd0977902019-11-07 18:58:43 -08002998 ALOGD("Failed to start filter: filter not found");
shubang40454db2020-03-30 16:52:29 -07002999 return (jint) Result::NOT_INITIALIZED;
shubangd0977902019-11-07 18:58:43 -08003000 }
shubanga06cfe52020-02-24 18:53:41 -08003001 Result r = iFilterSp->start();
3002 return (jint) r;
shubangd0977902019-11-07 18:58:43 -08003003}
3004
shubanga06cfe52020-02-24 18:53:41 -08003005static jint android_media_tv_Tuner_stop_filter(JNIEnv *env, jobject filter) {
3006 sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
3007 if (iFilterSp == NULL) {
shubangd0977902019-11-07 18:58:43 -08003008 ALOGD("Failed to stop filter: filter not found");
shubang40454db2020-03-30 16:52:29 -07003009 return (jint) Result::NOT_INITIALIZED;
shubangd0977902019-11-07 18:58:43 -08003010 }
shubanga06cfe52020-02-24 18:53:41 -08003011 Result r = iFilterSp->stop();
3012 return (jint) r;
shubangd0977902019-11-07 18:58:43 -08003013}
3014
shubanga06cfe52020-02-24 18:53:41 -08003015static jint android_media_tv_Tuner_flush_filter(JNIEnv *env, jobject filter) {
3016 sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
3017 if (iFilterSp == NULL) {
shubangd0977902019-11-07 18:58:43 -08003018 ALOGD("Failed to flush filter: filter not found");
shubang40454db2020-03-30 16:52:29 -07003019 return (jint) Result::NOT_INITIALIZED;
shubangd0977902019-11-07 18:58:43 -08003020 }
shubanga06cfe52020-02-24 18:53:41 -08003021 Result r = iFilterSp->flush();
3022 return (jint) r;
shubangd0977902019-11-07 18:58:43 -08003023}
3024
shubanga06cfe52020-02-24 18:53:41 -08003025static jint android_media_tv_Tuner_read_filter_fmq(
shubangd351b822020-01-22 17:29:18 -08003026 JNIEnv *env, jobject filter, jbyteArray buffer, jlong offset, jlong size) {
shubang964e6132019-11-26 15:05:22 -08003027 sp<Filter> filterSp = getFilter(env, filter);
3028 if (filterSp == NULL) {
3029 ALOGD("Failed to read filter FMQ: filter not found");
shubanga06cfe52020-02-24 18:53:41 -08003030 return (jint) Result::INVALID_STATE;
shubang964e6132019-11-26 15:05:22 -08003031 }
shubang431e5612020-03-30 21:24:56 -07003032 return copyData(env, filterSp->mFilterMQ, filterSp->mFilterMQEventFlag, buffer, offset, size);
shubang964e6132019-11-26 15:05:22 -08003033}
3034
shubanga06cfe52020-02-24 18:53:41 -08003035static jint android_media_tv_Tuner_close_filter(JNIEnv *env, jobject filter) {
3036 sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
3037 if (iFilterSp == NULL) {
3038 ALOGD("Failed to close filter: filter not found");
shubang40454db2020-03-30 16:52:29 -07003039 return (jint) Result::NOT_INITIALIZED;
shubanga06cfe52020-02-24 18:53:41 -08003040 }
3041 Result r = iFilterSp->close();
3042 return (jint) r;
shubang793e5702019-12-26 15:15:46 -08003043}
3044
shubangf657da22020-02-05 16:27:06 -08003045static sp<TimeFilter> getTimeFilter(JNIEnv *env, jobject filter) {
3046 return (TimeFilter *)env->GetLongField(filter, gFields.timeFilterContext);
3047}
3048
shubang4347e2e2019-12-13 17:20:40 -08003049static int android_media_tv_Tuner_time_filter_set_timestamp(
shubangf657da22020-02-05 16:27:06 -08003050 JNIEnv *env, jobject filter, jlong timestamp) {
3051 sp<TimeFilter> filterSp = getTimeFilter(env, filter);
3052 if (filterSp == NULL) {
3053 ALOGD("Failed set timestamp: time filter not found");
3054 return (int) Result::INVALID_STATE;
3055 }
3056 sp<ITimeFilter> iFilterSp = filterSp->getITimeFilter();
3057 Result r = iFilterSp->setTimeStamp(static_cast<uint64_t>(timestamp));
3058 return (int) r;
shubang4347e2e2019-12-13 17:20:40 -08003059}
3060
shubangf657da22020-02-05 16:27:06 -08003061static int android_media_tv_Tuner_time_filter_clear_timestamp(JNIEnv *env, jobject filter) {
3062 sp<TimeFilter> filterSp = getTimeFilter(env, filter);
3063 if (filterSp == NULL) {
3064 ALOGD("Failed clear timestamp: time filter not found");
3065 return (int) Result::INVALID_STATE;
3066 }
3067 sp<ITimeFilter> iFilterSp = filterSp->getITimeFilter();
3068 Result r = iFilterSp->clearTimeStamp();
3069 return (int) r;
shubang4347e2e2019-12-13 17:20:40 -08003070}
3071
shubangf657da22020-02-05 16:27:06 -08003072static jobject android_media_tv_Tuner_time_filter_get_timestamp(JNIEnv *env, jobject filter) {
3073 sp<TimeFilter> filterSp = getTimeFilter(env, filter);
3074 if (filterSp == NULL) {
3075 ALOGD("Failed get timestamp: time filter not found");
3076 return NULL;
3077 }
3078
3079 sp<ITimeFilter> iFilterSp = filterSp->getITimeFilter();
3080 Result res;
3081 uint64_t timestamp;
3082 iFilterSp->getTimeStamp(
3083 [&](Result r, uint64_t t) {
3084 res = r;
3085 timestamp = t;
3086 });
3087 if (res != Result::SUCCESS) {
3088 return NULL;
3089 }
3090
3091 jclass longClazz = env->FindClass("java/lang/Long");
3092 jmethodID longInit = env->GetMethodID(longClazz, "<init>", "(J)V");
3093
3094 jobject longObj = env->NewObject(longClazz, longInit, static_cast<jlong>(timestamp));
3095 return longObj;
shubang4347e2e2019-12-13 17:20:40 -08003096}
3097
shubangf657da22020-02-05 16:27:06 -08003098static jobject android_media_tv_Tuner_time_filter_get_source_time(JNIEnv *env, jobject filter) {
3099 sp<TimeFilter> filterSp = getTimeFilter(env, filter);
3100 if (filterSp == NULL) {
3101 ALOGD("Failed get source time: time filter not found");
3102 return NULL;
3103 }
3104
3105 sp<ITimeFilter> iFilterSp = filterSp->getITimeFilter();
3106 Result res;
3107 uint64_t timestamp;
3108 iFilterSp->getSourceTime(
3109 [&](Result r, uint64_t t) {
3110 res = r;
3111 timestamp = t;
3112 });
3113 if (res != Result::SUCCESS) {
3114 return NULL;
3115 }
3116
3117 jclass longClazz = env->FindClass("java/lang/Long");
3118 jmethodID longInit = env->GetMethodID(longClazz, "<init>", "(J)V");
3119
3120 jobject longObj = env->NewObject(longClazz, longInit, static_cast<jlong>(timestamp));
3121 return longObj;
shubang4347e2e2019-12-13 17:20:40 -08003122}
3123
shubangf657da22020-02-05 16:27:06 -08003124static int android_media_tv_Tuner_time_filter_close(JNIEnv *env, jobject filter) {
3125 sp<TimeFilter> filterSp = getTimeFilter(env, filter);
3126 if (filterSp == NULL) {
3127 ALOGD("Failed close time filter: time filter not found");
3128 return (int) Result::INVALID_STATE;
3129 }
3130
3131 Result r = filterSp->getITimeFilter()->close();
3132 if (r == Result::SUCCESS) {
3133 filterSp->decStrong(filter);
3134 env->SetLongField(filter, gFields.timeFilterContext, 0);
3135 }
3136 return (int) r;
shubang4347e2e2019-12-13 17:20:40 -08003137}
3138
shubangf159a832020-03-18 21:57:49 -07003139static jobject android_media_tv_Tuner_open_descrambler(JNIEnv *env, jobject thiz, jint) {
shubang13f15e02019-11-04 17:51:02 -08003140 sp<JTuner> tuner = getTuner(env, thiz);
3141 return tuner->openDescrambler();
3142}
3143
shubang40454db2020-03-30 16:52:29 -07003144static jint android_media_tv_Tuner_descrambler_add_pid(
shubang13f15e02019-11-04 17:51:02 -08003145 JNIEnv *env, jobject descrambler, jint pidType, jint pid, jobject filter) {
3146 sp<IDescrambler> descramblerSp = getDescrambler(env, descrambler);
3147 if (descramblerSp == NULL) {
shubang40454db2020-03-30 16:52:29 -07003148 return (jint) Result::NOT_INITIALIZED;
shubang13f15e02019-11-04 17:51:02 -08003149 }
shubanga06cfe52020-02-24 18:53:41 -08003150 sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
3151 Result result = descramblerSp->addPid(getDemuxPid((int)pidType, (int)pid), iFilterSp);
shubang40454db2020-03-30 16:52:29 -07003152 return (jint) result;
shubang13f15e02019-11-04 17:51:02 -08003153}
3154
shubang40454db2020-03-30 16:52:29 -07003155static jint android_media_tv_Tuner_descrambler_remove_pid(
shubang13f15e02019-11-04 17:51:02 -08003156 JNIEnv *env, jobject descrambler, jint pidType, jint pid, jobject filter) {
3157 sp<IDescrambler> descramblerSp = getDescrambler(env, descrambler);
3158 if (descramblerSp == NULL) {
shubang40454db2020-03-30 16:52:29 -07003159 return (jint) Result::NOT_INITIALIZED;
shubang13f15e02019-11-04 17:51:02 -08003160 }
shubanga06cfe52020-02-24 18:53:41 -08003161 sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
3162 Result result = descramblerSp->removePid(getDemuxPid((int)pidType, (int)pid), iFilterSp);
shubang40454db2020-03-30 16:52:29 -07003163 return (jint) result;
shubang99c89922019-12-17 17:33:15 -08003164}
3165
shubang40454db2020-03-30 16:52:29 -07003166static jint android_media_tv_Tuner_descrambler_set_key_token(
3167 JNIEnv* env, jobject descrambler, jbyteArray keyToken) {
3168 sp<IDescrambler> descramblerSp = getDescrambler(env, descrambler);
3169 if (descramblerSp == NULL) {
3170 return (jint) Result::NOT_INITIALIZED;
3171 }
3172 int size = env->GetArrayLength(keyToken);
3173 std::vector<uint8_t> v(size);
3174 env->GetByteArrayRegion(keyToken, 0, size, reinterpret_cast<jbyte*>(&v[0]));
3175 Result result = descramblerSp->setKeyToken(v);
3176 return (jint) result;
shubang99c89922019-12-17 17:33:15 -08003177}
3178
shubang40454db2020-03-30 16:52:29 -07003179static jint android_media_tv_Tuner_close_descrambler(JNIEnv* env, jobject descrambler) {
3180 sp<IDescrambler> descramblerSp = getDescrambler(env, descrambler);
3181 if (descramblerSp == NULL) {
3182 return (jint) Result::NOT_INITIALIZED;
3183 }
3184 Result r = descramblerSp->close();
3185 if (r == Result::SUCCESS) {
3186 descramblerSp->decStrong(descrambler);
3187 }
3188 return (jint) r;
shubang13f15e02019-11-04 17:51:02 -08003189}
3190
shubangd351b822020-01-22 17:29:18 -08003191static jobject android_media_tv_Tuner_open_dvr_recorder(
shubang5637a662020-02-27 18:06:21 -08003192 JNIEnv* env, jobject thiz, jlong bufferSize) {
3193 sp<JTuner> tuner = getTuner(env, thiz);
3194 return tuner->openDvr(DvrType::RECORD, bufferSize);
shubangd351b822020-01-22 17:29:18 -08003195}
3196
3197static jobject android_media_tv_Tuner_open_dvr_playback(
shubang5637a662020-02-27 18:06:21 -08003198 JNIEnv* env, jobject thiz, jlong bufferSize) {
3199 sp<JTuner> tuner = getTuner(env, thiz);
3200 return tuner->openDvr(DvrType::PLAYBACK, bufferSize);
shubang4a0eddf2019-11-08 17:10:18 -08003201}
3202
shubangc4b45702020-03-23 18:48:12 -07003203static jobject android_media_tv_Tuner_get_demux_caps(JNIEnv* env, jobject thiz) {
3204 sp<JTuner> tuner = getTuner(env, thiz);
3205 return tuner->getDemuxCaps();
shubang34258932019-12-27 13:59:23 -08003206}
3207
shubang66cc3aa2020-04-06 17:10:01 -07003208static jint android_media_tv_Tuner_open_demux(JNIEnv* env, jobject thiz, jint /* handle */) {
3209 sp<JTuner> tuner = getTuner(env, thiz);
3210 return (jint) tuner->openDemux();
3211}
3212
shubang2f9cab32020-04-10 18:00:56 -07003213static jint android_media_tv_Tuner_close_tuner(JNIEnv* env, jobject thiz) {
3214 sp<JTuner> tuner = getTuner(env, thiz);
3215 return (jint) tuner->close();
3216}
3217
shubangb3bfffe2020-03-26 17:44:31 -07003218static jint android_media_tv_Tuner_close_demux(JNIEnv* env, jobject thiz, jint /* handle */) {
3219 sp<JTuner> tuner = getTuner(env, thiz);
3220 return tuner->closeDemux();
3221}
3222
3223static jint android_media_tv_Tuner_close_frontend(JNIEnv* env, jobject thiz, jint /* handle */) {
3224 sp<JTuner> tuner = getTuner(env, thiz);
3225 return tuner->closeFrontend();
3226}
3227
shubang431e5612020-03-30 21:24:56 -07003228static jint android_media_tv_Tuner_attach_filter(JNIEnv *env, jobject dvr, jobject filter) {
shubangba21a7f2019-12-05 16:58:55 -08003229 sp<Dvr> dvrSp = getDvr(env, dvr);
shubang431e5612020-03-30 21:24:56 -07003230 if (dvrSp == NULL) {
3231 return (jint) Result::NOT_INITIALIZED;
3232 }
3233 sp<Filter> filterSp = getFilter(env, filter);
3234 if (filterSp == NULL) {
3235 return (jint) Result::INVALID_ARGUMENT;
3236 }
shubangba21a7f2019-12-05 16:58:55 -08003237 sp<IDvr> iDvrSp = dvrSp->getIDvr();
shubang431e5612020-03-30 21:24:56 -07003238 sp<IFilter> iFilterSp = filterSp->getIFilter();
3239 Result result = iDvrSp->attachFilter(iFilterSp);
3240 return (jint) result;
3241}
3242
3243static jint android_media_tv_Tuner_detach_filter(JNIEnv *env, jobject dvr, jobject filter) {
3244 sp<Dvr> dvrSp = getDvr(env, dvr);
3245 if (dvrSp == NULL) {
3246 return (jint) Result::NOT_INITIALIZED;
3247 }
3248 sp<Filter> filterSp = getFilter(env, filter);
3249 if (filterSp == NULL) {
3250 return (jint) Result::INVALID_ARGUMENT;
3251 }
3252 sp<IDvr> iDvrSp = dvrSp->getIDvr();
3253 sp<IFilter> iFilterSp = filterSp->getIFilter();
3254 Result result = iDvrSp->detachFilter(iFilterSp);
3255 return (jint) result;
3256}
3257
3258static jint android_media_tv_Tuner_configure_dvr(JNIEnv *env, jobject dvr, jobject settings) {
3259 sp<Dvr> dvrSp = getDvr(env, dvr);
shubang030afb52019-11-27 16:09:02 -08003260 if (dvrSp == NULL) {
3261 ALOGD("Failed to configure dvr: dvr not found");
shubang431e5612020-03-30 21:24:56 -07003262 return (int)Result::NOT_INITIALIZED;
shubang030afb52019-11-27 16:09:02 -08003263 }
shubang431e5612020-03-30 21:24:56 -07003264 sp<IDvr> iDvrSp = dvrSp->getIDvr();
shubangba21a7f2019-12-05 16:58:55 -08003265 Result result = iDvrSp->configure(getDvrSettings(env, settings));
shubang431e5612020-03-30 21:24:56 -07003266 if (result != Result::SUCCESS) {
3267 return (jint) result;
shubangba21a7f2019-12-05 16:58:55 -08003268 }
shubang431e5612020-03-30 21:24:56 -07003269 MQDescriptorSync<uint8_t> dvrMQDesc;
3270 Result getQueueDescResult = Result::UNKNOWN_ERROR;
3271 iDvrSp->getQueueDesc(
3272 [&](Result r, const MQDescriptorSync<uint8_t>& desc) {
3273 dvrMQDesc = desc;
3274 getQueueDescResult = r;
3275 ALOGD("getDvrQueueDesc");
3276 });
3277 if (getQueueDescResult == Result::SUCCESS) {
3278 dvrSp->mDvrMQ = std::make_unique<MQ>(dvrMQDesc, true);
3279 EventFlag::createEventFlag(
3280 dvrSp->mDvrMQ->getEventFlagWord(), &(dvrSp->mDvrMQEventFlag));
3281 }
3282 return (jint) getQueueDescResult;
shubang030afb52019-11-27 16:09:02 -08003283}
3284
shubang431e5612020-03-30 21:24:56 -07003285static jint android_media_tv_Tuner_start_dvr(JNIEnv *env, jobject dvr) {
3286 sp<Dvr> dvrSp = getDvr(env, dvr);
shubang4a0eddf2019-11-08 17:10:18 -08003287 if (dvrSp == NULL) {
3288 ALOGD("Failed to start dvr: dvr not found");
shubang431e5612020-03-30 21:24:56 -07003289 return (jint) Result::NOT_INITIALIZED;
shubang4a0eddf2019-11-08 17:10:18 -08003290 }
shubang431e5612020-03-30 21:24:56 -07003291 sp<IDvr> iDvrSp = dvrSp->getIDvr();
3292 Result result = iDvrSp->start();
3293 return (jint) result;
shubang4a0eddf2019-11-08 17:10:18 -08003294}
3295
shubang431e5612020-03-30 21:24:56 -07003296static jint android_media_tv_Tuner_stop_dvr(JNIEnv *env, jobject dvr) {
3297 sp<Dvr> dvrSp = getDvr(env, dvr);
shubang4a0eddf2019-11-08 17:10:18 -08003298 if (dvrSp == NULL) {
3299 ALOGD("Failed to stop dvr: dvr not found");
shubang431e5612020-03-30 21:24:56 -07003300 return (jint) Result::NOT_INITIALIZED;
shubang4a0eddf2019-11-08 17:10:18 -08003301 }
shubang431e5612020-03-30 21:24:56 -07003302 sp<IDvr> iDvrSp = dvrSp->getIDvr();
3303 Result result = iDvrSp->stop();
3304 return (jint) result;
shubang4a0eddf2019-11-08 17:10:18 -08003305}
3306
shubang431e5612020-03-30 21:24:56 -07003307static jint android_media_tv_Tuner_flush_dvr(JNIEnv *env, jobject dvr) {
3308 sp<Dvr> dvrSp = getDvr(env, dvr);
shubang4a0eddf2019-11-08 17:10:18 -08003309 if (dvrSp == NULL) {
3310 ALOGD("Failed to flush dvr: dvr not found");
shubang431e5612020-03-30 21:24:56 -07003311 return (jint) Result::NOT_INITIALIZED;
shubang4a0eddf2019-11-08 17:10:18 -08003312 }
shubang431e5612020-03-30 21:24:56 -07003313 sp<IDvr> iDvrSp = dvrSp->getIDvr();
3314 Result result = iDvrSp->flush();
3315 return (jint) result;
shubang793e5702019-12-26 15:15:46 -08003316}
3317
shubang431e5612020-03-30 21:24:56 -07003318static jint android_media_tv_Tuner_close_dvr(JNIEnv* env, jobject dvr) {
3319 sp<Dvr> dvrSp = getDvr(env, dvr);
3320 if (dvrSp == NULL) {
3321 ALOGD("Failed to close dvr: dvr not found");
3322 return (jint) Result::NOT_INITIALIZED;
3323 }
3324 return dvrSp->close();
shubang4a0eddf2019-11-08 17:10:18 -08003325}
3326
shubang1c1144e2020-03-03 18:00:17 -08003327static sp<Lnb> getLnb(JNIEnv *env, jobject lnb) {
3328 return (Lnb *)env->GetLongField(lnb, gFields.lnbContext);
shubang847fc0a2019-12-26 16:54:10 -08003329}
3330
shubang1c1144e2020-03-03 18:00:17 -08003331static jint android_media_tv_Tuner_lnb_set_voltage(JNIEnv* env, jobject lnb, jint voltage) {
3332 sp<ILnb> iLnbSp = getLnb(env, lnb)->getILnb();
3333 Result r = iLnbSp->setVoltage(static_cast<LnbVoltage>(voltage));
3334 return (jint) r;
shubang847fc0a2019-12-26 16:54:10 -08003335}
3336
shubang1c1144e2020-03-03 18:00:17 -08003337static int android_media_tv_Tuner_lnb_set_tone(JNIEnv* env, jobject lnb, jint tone) {
3338 sp<ILnb> iLnbSp = getLnb(env, lnb)->getILnb();
3339 Result r = iLnbSp->setTone(static_cast<LnbTone>(tone));
3340 return (jint) r;
shubang847fc0a2019-12-26 16:54:10 -08003341}
3342
shubang1c1144e2020-03-03 18:00:17 -08003343static int android_media_tv_Tuner_lnb_set_position(JNIEnv* env, jobject lnb, jint position) {
3344 sp<ILnb> iLnbSp = getLnb(env, lnb)->getILnb();
3345 Result r = iLnbSp->setSatellitePosition(static_cast<LnbPosition>(position));
3346 return (jint) r;
3347}
3348
3349static int android_media_tv_Tuner_lnb_send_diseqc_msg(JNIEnv* env, jobject lnb, jbyteArray msg) {
3350 sp<ILnb> iLnbSp = getLnb(env, lnb)->getILnb();
3351 int size = env->GetArrayLength(msg);
3352 std::vector<uint8_t> v(size);
3353 env->GetByteArrayRegion(msg, 0, size, reinterpret_cast<jbyte*>(&v[0]));
3354 Result r = iLnbSp->sendDiseqcMessage(v);
3355 return (jint) r;
shubang847fc0a2019-12-26 16:54:10 -08003356}
3357
shubangd295be02020-03-27 17:08:11 -07003358static int android_media_tv_Tuner_close_lnb(JNIEnv* env, jobject lnb) {
3359 sp<Lnb> lnbSp = getLnb(env, lnb);
3360 Result r = lnbSp->getILnb()->close();
3361 if (r == Result::SUCCESS) {
3362 lnbSp->decStrong(lnb);
3363 env->SetLongField(lnb, gFields.lnbContext, 0);
3364 }
3365 return (jint) r;
shubang847fc0a2019-12-26 16:54:10 -08003366}
3367
shubangba21a7f2019-12-05 16:58:55 -08003368static void android_media_tv_Tuner_dvr_set_fd(JNIEnv *env, jobject dvr, jobject jfd) {
3369 sp<Dvr> dvrSp = getDvr(env, dvr);
3370 if (dvrSp == NULL) {
3371 ALOGD("Failed to set FD for dvr: dvr not found");
3372 }
3373 dvrSp->mFd = jniGetFDFromFileDescriptor(env, jfd);
3374 ALOGD("set fd = %d", dvrSp->mFd);
3375}
3376
shubangd351b822020-01-22 17:29:18 -08003377static jlong android_media_tv_Tuner_read_dvr(JNIEnv *env, jobject dvr, jlong size) {
shubangba21a7f2019-12-05 16:58:55 -08003378 sp<Dvr> dvrSp = getDvr(env, dvr);
3379 if (dvrSp == NULL) {
3380 ALOGD("Failed to read dvr: dvr not found");
3381 }
3382
shubangd351b822020-01-22 17:29:18 -08003383 long available = dvrSp->mDvrMQ->availableToWrite();
3384 long write = std::min((long) size, available);
shubangba21a7f2019-12-05 16:58:55 -08003385
shubang431e5612020-03-30 21:24:56 -07003386 MQ::MemTransaction tx;
shubangd351b822020-01-22 17:29:18 -08003387 long ret = 0;
shubangba21a7f2019-12-05 16:58:55 -08003388 if (dvrSp->mDvrMQ->beginWrite(write, &tx)) {
3389 auto first = tx.getFirstRegion();
3390 auto data = first.getAddress();
shubangd351b822020-01-22 17:29:18 -08003391 long length = first.getLength();
3392 long firstToWrite = std::min(length, write);
shubangba21a7f2019-12-05 16:58:55 -08003393 ret = read(dvrSp->mFd, data, firstToWrite);
3394 if (ret < firstToWrite) {
shubangd351b822020-01-22 17:29:18 -08003395 ALOGW("[DVR] file to MQ, first region: %ld bytes to write, but %ld bytes written",
shubangba21a7f2019-12-05 16:58:55 -08003396 firstToWrite, ret);
3397 } else if (firstToWrite < write) {
shubangd351b822020-01-22 17:29:18 -08003398 ALOGD("[DVR] write second region: %ld bytes written, %ld bytes in total", ret, write);
shubangba21a7f2019-12-05 16:58:55 -08003399 auto second = tx.getSecondRegion();
3400 data = second.getAddress();
3401 length = second.getLength();
3402 int secondToWrite = std::min(length, write - firstToWrite);
3403 ret += read(dvrSp->mFd, data, secondToWrite);
3404 }
shubangd351b822020-01-22 17:29:18 -08003405 ALOGD("[DVR] file to MQ: %ld bytes need to be written, %ld bytes written", write, ret);
shubangba21a7f2019-12-05 16:58:55 -08003406 if (!dvrSp->mDvrMQ->commitWrite(ret)) {
3407 ALOGE("[DVR] Error: failed to commit write!");
3408 }
3409
3410 } else {
3411 ALOGE("dvrMq.beginWrite failed");
3412 }
shubangd351b822020-01-22 17:29:18 -08003413 return (jlong) ret;
shubangba21a7f2019-12-05 16:58:55 -08003414}
3415
shubangd351b822020-01-22 17:29:18 -08003416static jlong android_media_tv_Tuner_read_dvr_from_array(
shubang431e5612020-03-30 21:24:56 -07003417 JNIEnv* env, jobject dvr, jbyteArray buffer, jlong offset, jlong size) {
3418 sp<Dvr> dvrSp = getDvr(env, dvr);
3419 if (dvrSp == NULL) {
3420 ALOGW("Failed to read dvr: dvr not found");
3421 return 0;
3422 }
3423 if (dvrSp->mDvrMQ == NULL) {
3424 ALOGW("Failed to read dvr: dvr not configured");
3425 return 0;
3426 }
3427
3428 jlong available = dvrSp->mDvrMQ->availableToWrite();
3429 size = std::min(size, available);
3430
3431 jboolean isCopy;
3432 jbyte *src = env->GetByteArrayElements(buffer, &isCopy);
3433 if (src == nullptr) {
3434 ALOGD("Failed to GetByteArrayElements");
3435 return 0;
3436 }
3437
3438 if (dvrSp->mDvrMQ->write(reinterpret_cast<unsigned char*>(src) + offset, size)) {
3439 env->ReleaseByteArrayElements(buffer, src, 0);
3440 dvrSp->mDvrMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
3441 } else {
3442 ALOGD("Failed to write FMQ");
3443 env->ReleaseByteArrayElements(buffer, src, 0);
3444 return 0;
3445 }
3446 return size;
shubangba21a7f2019-12-05 16:58:55 -08003447}
3448
shubangd351b822020-01-22 17:29:18 -08003449static jlong android_media_tv_Tuner_write_dvr(JNIEnv *env, jobject dvr, jlong size) {
shubang5f4ea352019-12-09 15:12:10 -08003450 sp<Dvr> dvrSp = getDvr(env, dvr);
3451 if (dvrSp == NULL) {
3452 ALOGW("Failed to write dvr: dvr not found");
3453 return 0;
3454 }
3455
3456 if (dvrSp->mDvrMQ == NULL) {
3457 ALOGW("Failed to write dvr: dvr not configured");
3458 return 0;
3459 }
3460
shubang431e5612020-03-30 21:24:56 -07003461 MQ& dvrMq = dvrSp->getDvrMQ();
shubang5f4ea352019-12-09 15:12:10 -08003462
shubangd351b822020-01-22 17:29:18 -08003463 long available = dvrMq.availableToRead();
3464 long toRead = std::min((long) size, available);
shubang5f4ea352019-12-09 15:12:10 -08003465
shubangd351b822020-01-22 17:29:18 -08003466 long ret = 0;
shubang431e5612020-03-30 21:24:56 -07003467 MQ::MemTransaction tx;
shubang5f4ea352019-12-09 15:12:10 -08003468 if (dvrMq.beginRead(toRead, &tx)) {
3469 auto first = tx.getFirstRegion();
3470 auto data = first.getAddress();
shubangd351b822020-01-22 17:29:18 -08003471 long length = first.getLength();
3472 long firstToRead = std::min(length, toRead);
shubang5f4ea352019-12-09 15:12:10 -08003473 ret = write(dvrSp->mFd, data, firstToRead);
3474 if (ret < firstToRead) {
shubangd351b822020-01-22 17:29:18 -08003475 ALOGW("[DVR] MQ to file: %ld bytes read, but %ld bytes written", firstToRead, ret);
shubang5f4ea352019-12-09 15:12:10 -08003476 } else if (firstToRead < toRead) {
shubangd351b822020-01-22 17:29:18 -08003477 ALOGD("[DVR] read second region: %ld bytes read, %ld bytes in total", ret, toRead);
shubang5f4ea352019-12-09 15:12:10 -08003478 auto second = tx.getSecondRegion();
3479 data = second.getAddress();
3480 length = second.getLength();
3481 int secondToRead = toRead - firstToRead;
3482 ret += write(dvrSp->mFd, data, secondToRead);
3483 }
shubangd351b822020-01-22 17:29:18 -08003484 ALOGD("[DVR] MQ to file: %ld bytes to be read, %ld bytes written", toRead, ret);
shubang5f4ea352019-12-09 15:12:10 -08003485 if (!dvrMq.commitRead(ret)) {
3486 ALOGE("[DVR] Error: failed to commit read!");
3487 }
3488
3489 } else {
3490 ALOGE("dvrMq.beginRead failed");
3491 }
3492
shubangd351b822020-01-22 17:29:18 -08003493 return (jlong) ret;
shubang5f4ea352019-12-09 15:12:10 -08003494}
3495
shubangd351b822020-01-22 17:29:18 -08003496static jlong android_media_tv_Tuner_write_dvr_to_array(
shubang431e5612020-03-30 21:24:56 -07003497 JNIEnv *env, jobject dvr, jbyteArray buffer, jlong offset, jlong size) {
3498 sp<Dvr> dvrSp = getDvr(env, dvr);
3499 if (dvrSp == NULL) {
3500 ALOGW("Failed to write dvr: dvr not found");
3501 return 0;
3502 }
3503 if (dvrSp->mDvrMQ == NULL) {
3504 ALOGW("Failed to write dvr: dvr not configured");
3505 return 0;
3506 }
3507 return copyData(env, dvrSp->mDvrMQ, dvrSp->mDvrMQEventFlag, buffer, offset, size);
shubang5f4ea352019-12-09 15:12:10 -08003508}
shubangba21a7f2019-12-05 16:58:55 -08003509
shubangd0977902019-11-07 18:58:43 -08003510static const JNINativeMethod gTunerMethods[] = {
shubang8ab43b12019-10-18 15:55:55 -07003511 { "nativeInit", "()V", (void *)android_media_tv_Tuner_native_init },
3512 { "nativeSetup", "()V", (void *)android_media_tv_Tuner_native_setup },
shubang7e849b02019-10-18 19:36:25 -07003513 { "nativeGetFrontendIds", "()Ljava/util/List;",
3514 (void *)android_media_tv_Tuner_get_frontend_ids },
shubangc18cc102020-03-12 16:28:45 -07003515 { "nativeOpenFrontendByHandle", "(I)Landroid/media/tv/tuner/Tuner$Frontend;",
3516 (void *)android_media_tv_Tuner_open_frontend_by_handle },
shubang2f9cab32020-04-10 18:00:56 -07003517 { "nativeCloseFrontendByHandle", "(I)I",
3518 (void *)android_media_tv_Tuner_close_frontend_by_handle },
shubangd351b822020-01-22 17:29:18 -08003519 { "nativeTune", "(ILandroid/media/tv/tuner/frontend/FrontendSettings;)I",
shubang74bfd482019-10-29 19:10:22 -07003520 (void *)android_media_tv_Tuner_tune },
shubange65b6862019-12-17 15:43:35 -08003521 { "nativeStopTune", "()I", (void *)android_media_tv_Tuner_stop_tune },
shubangd351b822020-01-22 17:29:18 -08003522 { "nativeScan", "(ILandroid/media/tv/tuner/frontend/FrontendSettings;I)I",
shubangd5b845f2019-12-11 15:29:09 -08003523 (void *)android_media_tv_Tuner_scan },
shubang793e5702019-12-26 15:15:46 -08003524 { "nativeStopScan", "()I", (void *)android_media_tv_Tuner_stop_scan },
shubange65b6862019-12-17 15:43:35 -08003525 { "nativeSetLnb", "(I)I", (void *)android_media_tv_Tuner_set_lnb },
3526 { "nativeSetLna", "(Z)I", (void *)android_media_tv_Tuner_set_lna },
shubangd351b822020-01-22 17:29:18 -08003527 { "nativeGetFrontendStatus", "([I)Landroid/media/tv/tuner/frontend/FrontendStatus;",
shubang1512ec12019-12-23 18:22:42 -08003528 (void *)android_media_tv_Tuner_get_frontend_status },
shubangbee73462020-02-07 17:48:02 -08003529 { "nativeGetAvSyncHwId", "(Landroid/media/tv/tuner/filter/Filter;)Ljava/lang/Integer;",
3530 (void *)android_media_tv_Tuner_get_av_sync_hw_id },
3531 { "nativeGetAvSyncTime", "(I)Ljava/lang/Long;",
3532 (void *)android_media_tv_Tuner_get_av_sync_time },
shubang7343fee2019-12-27 12:02:08 -08003533 { "nativeConnectCiCam", "(I)I", (void *)android_media_tv_Tuner_connect_cicam },
3534 { "nativeDisconnectCiCam", "()I", (void *)android_media_tv_Tuner_disconnect_cicam },
shubangdeb067c2020-01-27 13:21:55 -08003535 { "nativeGetFrontendInfo", "(I)Landroid/media/tv/tuner/frontend/FrontendInfo;",
shubang95c1f752019-12-27 16:29:48 -08003536 (void *)android_media_tv_Tuner_get_frontend_info },
shubangdeb067c2020-01-27 13:21:55 -08003537 { "nativeOpenFilter", "(IIJ)Landroid/media/tv/tuner/filter/Filter;",
shubang6f473d62019-11-01 15:42:21 -07003538 (void *)android_media_tv_Tuner_open_filter },
shubangdeb067c2020-01-27 13:21:55 -08003539 { "nativeOpenTimeFilter", "()Landroid/media/tv/tuner/filter/TimeFilter;",
shubang4347e2e2019-12-13 17:20:40 -08003540 (void *)android_media_tv_Tuner_open_time_filter },
shubang0dc83942020-04-02 17:19:31 -07003541 { "nativeGetLnbIds", "()[I", (void *)android_media_tv_Tuner_get_lnb_ids },
shubangc18cc102020-03-12 16:28:45 -07003542 { "nativeOpenLnbByHandle", "(I)Landroid/media/tv/tuner/Lnb;",
3543 (void *)android_media_tv_Tuner_open_lnb_by_handle },
shubang757602f2020-03-06 15:23:41 -08003544 { "nativeOpenLnbByName", "(Ljava/lang/String;)Landroid/media/tv/tuner/Lnb;",
3545 (void *)android_media_tv_Tuner_open_lnb_by_name },
shubangf159a832020-03-18 21:57:49 -07003546 { "nativeOpenDescramblerByHandle", "(I)Landroid/media/tv/tuner/Descrambler;",
shubang13f15e02019-11-04 17:51:02 -08003547 (void *)android_media_tv_Tuner_open_descrambler },
shubangd351b822020-01-22 17:29:18 -08003548 { "nativeOpenDvrRecorder", "(J)Landroid/media/tv/tuner/dvr/DvrRecorder;",
3549 (void *)android_media_tv_Tuner_open_dvr_recorder },
3550 { "nativeOpenDvrPlayback", "(J)Landroid/media/tv/tuner/dvr/DvrPlayback;",
3551 (void *)android_media_tv_Tuner_open_dvr_playback },
shubang34258932019-12-27 13:59:23 -08003552 { "nativeGetDemuxCapabilities", "()Landroid/media/tv/tuner/DemuxCapabilities;",
3553 (void *)android_media_tv_Tuner_get_demux_caps },
shubang66cc3aa2020-04-06 17:10:01 -07003554 { "nativeOpenDemuxByhandle", "(I)I", (void *)android_media_tv_Tuner_open_demux },
shubangb3bfffe2020-03-26 17:44:31 -07003555 { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_tuner },
3556 { "nativeCloseFrontend", "(I)I", (void *)android_media_tv_Tuner_close_frontend },
3557 { "nativeCloseDemux", "(I)I", (void *)android_media_tv_Tuner_close_demux },
shubang8ab43b12019-10-18 15:55:55 -07003558};
3559
shubangd0977902019-11-07 18:58:43 -08003560static const JNINativeMethod gFilterMethods[] = {
shubangd351b822020-01-22 17:29:18 -08003561 { "nativeConfigureFilter", "(IILandroid/media/tv/tuner/filter/FilterConfiguration;)I",
shubang75c87082019-11-15 11:26:56 -08003562 (void *)android_media_tv_Tuner_configure_filter },
shubang793e5702019-12-26 15:15:46 -08003563 { "nativeGetId", "()I", (void *)android_media_tv_Tuner_get_filter_id },
shubangd351b822020-01-22 17:29:18 -08003564 { "nativeSetDataSource", "(Landroid/media/tv/tuner/filter/Filter;)I",
shubang793e5702019-12-26 15:15:46 -08003565 (void *)android_media_tv_Tuner_set_filter_data_source },
3566 { "nativeStartFilter", "()I", (void *)android_media_tv_Tuner_start_filter },
3567 { "nativeStopFilter", "()I", (void *)android_media_tv_Tuner_stop_filter },
3568 { "nativeFlushFilter", "()I", (void *)android_media_tv_Tuner_flush_filter },
shubangd351b822020-01-22 17:29:18 -08003569 { "nativeRead", "([BJJ)I", (void *)android_media_tv_Tuner_read_filter_fmq },
Amy1b301f42020-01-02 11:07:56 -08003570 { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_filter },
shubangd0977902019-11-07 18:58:43 -08003571};
3572
shubang4347e2e2019-12-13 17:20:40 -08003573static const JNINativeMethod gTimeFilterMethods[] = {
shubangdeb067c2020-01-27 13:21:55 -08003574 { "nativeSetTimestamp", "(J)I", (void *)android_media_tv_Tuner_time_filter_set_timestamp },
3575 { "nativeClearTimestamp", "()I", (void *)android_media_tv_Tuner_time_filter_clear_timestamp },
3576 { "nativeGetTimestamp", "()Ljava/lang/Long;",
shubang4347e2e2019-12-13 17:20:40 -08003577 (void *)android_media_tv_Tuner_time_filter_get_timestamp },
3578 { "nativeGetSourceTime", "()Ljava/lang/Long;",
3579 (void *)android_media_tv_Tuner_time_filter_get_source_time },
3580 { "nativeClose", "()I", (void *)android_media_tv_Tuner_time_filter_close },
3581};
3582
shubang13f15e02019-11-04 17:51:02 -08003583static const JNINativeMethod gDescramblerMethods[] = {
shubangd351b822020-01-22 17:29:18 -08003584 { "nativeAddPid", "(IILandroid/media/tv/tuner/filter/Filter;)I",
shubang40454db2020-03-30 16:52:29 -07003585 (void *)android_media_tv_Tuner_descrambler_add_pid },
shubangd351b822020-01-22 17:29:18 -08003586 { "nativeRemovePid", "(IILandroid/media/tv/tuner/filter/Filter;)I",
shubang40454db2020-03-30 16:52:29 -07003587 (void *)android_media_tv_Tuner_descrambler_remove_pid },
3588 { "nativeSetKeyToken", "([B)I", (void *)android_media_tv_Tuner_descrambler_set_key_token },
Amy1b301f42020-01-02 11:07:56 -08003589 { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_descrambler },
shubang13f15e02019-11-04 17:51:02 -08003590};
3591
shubang5637a662020-02-27 18:06:21 -08003592static const JNINativeMethod gDvrRecorderMethods[] = {
shubangd351b822020-01-22 17:29:18 -08003593 { "nativeAttachFilter", "(Landroid/media/tv/tuner/filter/Filter;)I",
shubang4a0eddf2019-11-08 17:10:18 -08003594 (void *)android_media_tv_Tuner_attach_filter },
shubangd351b822020-01-22 17:29:18 -08003595 { "nativeDetachFilter", "(Landroid/media/tv/tuner/filter/Filter;)I",
shubang4a0eddf2019-11-08 17:10:18 -08003596 (void *)android_media_tv_Tuner_detach_filter },
shubangd351b822020-01-22 17:29:18 -08003597 { "nativeConfigureDvr", "(Landroid/media/tv/tuner/dvr/DvrSettings;)I",
shubang030afb52019-11-27 16:09:02 -08003598 (void *)android_media_tv_Tuner_configure_dvr },
shubang793e5702019-12-26 15:15:46 -08003599 { "nativeStartDvr", "()I", (void *)android_media_tv_Tuner_start_dvr },
3600 { "nativeStopDvr", "()I", (void *)android_media_tv_Tuner_stop_dvr },
3601 { "nativeFlushDvr", "()I", (void *)android_media_tv_Tuner_flush_dvr },
3602 { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_dvr },
shubangd351b822020-01-22 17:29:18 -08003603 { "nativeSetFileDescriptor", "(I)V", (void *)android_media_tv_Tuner_dvr_set_fd },
shubangd351b822020-01-22 17:29:18 -08003604 { "nativeWrite", "(J)J", (void *)android_media_tv_Tuner_write_dvr },
3605 { "nativeWrite", "([BJJ)J", (void *)android_media_tv_Tuner_write_dvr_to_array },
3606};
3607
3608static const JNINativeMethod gDvrPlaybackMethods[] = {
shubang5637a662020-02-27 18:06:21 -08003609 { "nativeAttachFilter", "(Landroid/media/tv/tuner/filter/Filter;)I",
3610 (void *)android_media_tv_Tuner_attach_filter },
3611 { "nativeDetachFilter", "(Landroid/media/tv/tuner/filter/Filter;)I",
3612 (void *)android_media_tv_Tuner_detach_filter },
3613 { "nativeConfigureDvr", "(Landroid/media/tv/tuner/dvr/DvrSettings;)I",
3614 (void *)android_media_tv_Tuner_configure_dvr },
3615 { "nativeStartDvr", "()I", (void *)android_media_tv_Tuner_start_dvr },
3616 { "nativeStopDvr", "()I", (void *)android_media_tv_Tuner_stop_dvr },
3617 { "nativeFlushDvr", "()I", (void *)android_media_tv_Tuner_flush_dvr },
3618 { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_dvr },
3619 { "nativeSetFileDescriptor", "(I)V", (void *)android_media_tv_Tuner_dvr_set_fd },
shubangd351b822020-01-22 17:29:18 -08003620 { "nativeRead", "(J)J", (void *)android_media_tv_Tuner_read_dvr },
3621 { "nativeRead", "([BJJ)J", (void *)android_media_tv_Tuner_read_dvr_from_array },
shubang4a0eddf2019-11-08 17:10:18 -08003622};
3623
shubang847fc0a2019-12-26 16:54:10 -08003624static const JNINativeMethod gLnbMethods[] = {
3625 { "nativeSetVoltage", "(I)I", (void *)android_media_tv_Tuner_lnb_set_voltage },
3626 { "nativeSetTone", "(I)I", (void *)android_media_tv_Tuner_lnb_set_tone },
3627 { "nativeSetSatellitePosition", "(I)I", (void *)android_media_tv_Tuner_lnb_set_position },
3628 { "nativeSendDiseqcMessage", "([B)I", (void *)android_media_tv_Tuner_lnb_send_diseqc_msg },
3629 { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_lnb },
3630};
3631
shubangd0977902019-11-07 18:58:43 -08003632static bool register_android_media_tv_Tuner(JNIEnv *env) {
3633 if (AndroidRuntime::registerNativeMethods(
3634 env, "android/media/tv/tuner/Tuner", gTunerMethods, NELEM(gTunerMethods)) != JNI_OK) {
3635 ALOGE("Failed to register tuner native methods");
3636 return false;
3637 }
3638 if (AndroidRuntime::registerNativeMethods(
shubangd351b822020-01-22 17:29:18 -08003639 env, "android/media/tv/tuner/filter/Filter",
shubangd0977902019-11-07 18:58:43 -08003640 gFilterMethods,
3641 NELEM(gFilterMethods)) != JNI_OK) {
3642 ALOGE("Failed to register filter native methods");
3643 return false;
3644 }
shubang13f15e02019-11-04 17:51:02 -08003645 if (AndroidRuntime::registerNativeMethods(
shubangd351b822020-01-22 17:29:18 -08003646 env, "android/media/tv/tuner/filter/TimeFilter",
shubang4347e2e2019-12-13 17:20:40 -08003647 gTimeFilterMethods,
3648 NELEM(gTimeFilterMethods)) != JNI_OK) {
3649 ALOGE("Failed to register time filter native methods");
3650 return false;
3651 }
3652 if (AndroidRuntime::registerNativeMethods(
shubangd351b822020-01-22 17:29:18 -08003653 env, "android/media/tv/tuner/Descrambler",
shubang13f15e02019-11-04 17:51:02 -08003654 gDescramblerMethods,
3655 NELEM(gDescramblerMethods)) != JNI_OK) {
3656 ALOGE("Failed to register descrambler native methods");
3657 return false;
3658 }
shubang4a0eddf2019-11-08 17:10:18 -08003659 if (AndroidRuntime::registerNativeMethods(
shubangd351b822020-01-22 17:29:18 -08003660 env, "android/media/tv/tuner/dvr/DvrRecorder",
3661 gDvrRecorderMethods,
3662 NELEM(gDvrRecorderMethods)) != JNI_OK) {
3663 ALOGE("Failed to register dvr recorder native methods");
3664 return false;
3665 }
3666 if (AndroidRuntime::registerNativeMethods(
3667 env, "android/media/tv/tuner/dvr/DvrPlayback",
3668 gDvrPlaybackMethods,
3669 NELEM(gDvrPlaybackMethods)) != JNI_OK) {
3670 ALOGE("Failed to register dvr playback native methods");
3671 return false;
3672 }
3673 if (AndroidRuntime::registerNativeMethods(
3674 env, "android/media/tv/tuner/Lnb",
shubang847fc0a2019-12-26 16:54:10 -08003675 gLnbMethods,
3676 NELEM(gLnbMethods)) != JNI_OK) {
3677 ALOGE("Failed to register lnb native methods");
3678 return false;
3679 }
shubangd0977902019-11-07 18:58:43 -08003680 return true;
shubang8ab43b12019-10-18 15:55:55 -07003681}
3682
3683jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
3684{
3685 JNIEnv* env = NULL;
3686 jint result = -1;
3687
3688 if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
3689 ALOGE("ERROR: GetEnv failed\n");
3690 return result;
3691 }
3692 assert(env != NULL);
3693
shubangd0977902019-11-07 18:58:43 -08003694 if (!register_android_media_tv_Tuner(env)) {
shubang8ab43b12019-10-18 15:55:55 -07003695 ALOGE("ERROR: Tuner native registration failed\n");
3696 return result;
3697 }
3698 return JNI_VERSION_1_4;
3699}