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