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