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