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