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