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