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