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