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