shubang | 8ab43b1 | 2019-10-18 15:55:55 -0700 | [diff] [blame] | 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_TAG "TvTuner-JNI" |
| 18 | #include <utils/Log.h> |
| 19 | |
shubang | d49681e | 2020-02-17 21:32:30 -0800 | [diff] [blame] | 20 | #include "android_media_MediaCodecLinearBlock.h" |
shubang | 8ab43b1 | 2019-10-18 15:55:55 -0700 | [diff] [blame] | 21 | #include "android_media_tv_Tuner.h" |
| 22 | #include "android_runtime/AndroidRuntime.h" |
| 23 | |
shubang | d49681e | 2020-02-17 21:32:30 -0800 | [diff] [blame] | 24 | #include <C2BlockInternal.h> |
| 25 | #include <C2HandleIonInternal.h> |
shubang | 8ab43b1 | 2019-10-18 15:55:55 -0700 | [diff] [blame] | 26 | #include <android/hardware/tv/tuner/1.0/ITuner.h> |
| 27 | #include <media/stagefright/foundation/ADebug.h> |
shubang | ba21a7f | 2019-12-05 16:58:55 -0800 | [diff] [blame] | 28 | #include <nativehelper/JNIHelp.h> |
shubang | d49681e | 2020-02-17 21:32:30 -0800 | [diff] [blame] | 29 | #include <nativehelper/ScopedLocalRef.h> |
| 30 | #include <utils/NativeHandle.h> |
shubang | 8ab43b1 | 2019-10-18 15:55:55 -0700 | [diff] [blame] | 31 | |
| 32 | #pragma GCC diagnostic ignored "-Wunused-function" |
| 33 | |
shubang | 6f473d6 | 2019-11-01 15:42:21 -0700 | [diff] [blame] | 34 | using ::android::hardware::Void; |
shubang | 44fa142 | 2020-01-30 11:42:59 -0800 | [diff] [blame] | 35 | using ::android::hardware::hidl_bitfield; |
shubang | 7e849b0 | 2019-10-18 19:36:25 -0700 | [diff] [blame] | 36 | using ::android::hardware::hidl_vec; |
shubang | 3e0c37b | 2020-02-19 19:09:10 -0800 | [diff] [blame] | 37 | using ::android::hardware::tv::tuner::V1_0::AudioExtraMetaData; |
| 38 | using ::android::hardware::tv::tuner::V1_0::Constant; |
shubang | 030afb5 | 2019-11-27 16:09:02 -0800 | [diff] [blame] | 39 | using ::android::hardware::tv::tuner::V1_0::DataFormat; |
shubang | 44fa142 | 2020-01-30 11:42:59 -0800 | [diff] [blame] | 40 | using ::android::hardware::tv::tuner::V1_0::DemuxAlpFilterSettings; |
| 41 | using ::android::hardware::tv::tuner::V1_0::DemuxAlpFilterType; |
shubang | 87788c3 | 2020-02-04 13:55:23 -0800 | [diff] [blame] | 42 | using ::android::hardware::tv::tuner::V1_0::DemuxAlpLengthType; |
shubang | c4b4570 | 2020-03-23 18:48:12 -0700 | [diff] [blame] | 43 | using ::android::hardware::tv::tuner::V1_0::DemuxCapabilities; |
shubang | 44fa142 | 2020-01-30 11:42:59 -0800 | [diff] [blame] | 44 | using ::android::hardware::tv::tuner::V1_0::DemuxFilterAvSettings; |
shubang | 3e0c37b | 2020-02-19 19:09:10 -0800 | [diff] [blame] | 45 | using ::android::hardware::tv::tuner::V1_0::DemuxFilterDownloadEvent; |
shubang | 44fa142 | 2020-01-30 11:42:59 -0800 | [diff] [blame] | 46 | using ::android::hardware::tv::tuner::V1_0::DemuxFilterDownloadSettings; |
shubang | 3e0c37b | 2020-02-19 19:09:10 -0800 | [diff] [blame] | 47 | using ::android::hardware::tv::tuner::V1_0::DemuxFilterIpPayloadEvent; |
shubang | 6f473d6 | 2019-11-01 15:42:21 -0700 | [diff] [blame] | 48 | using ::android::hardware::tv::tuner::V1_0::DemuxFilterMainType; |
shubang | d49681e | 2020-02-17 21:32:30 -0800 | [diff] [blame] | 49 | using ::android::hardware::tv::tuner::V1_0::DemuxFilterMediaEvent; |
shubang | 3e0c37b | 2020-02-19 19:09:10 -0800 | [diff] [blame] | 50 | using ::android::hardware::tv::tuner::V1_0::DemuxFilterMmtpRecordEvent; |
shubang | 75c8708 | 2019-11-15 11:26:56 -0800 | [diff] [blame] | 51 | using ::android::hardware::tv::tuner::V1_0::DemuxFilterPesDataSettings; |
shubang | 3e0c37b | 2020-02-19 19:09:10 -0800 | [diff] [blame] | 52 | using ::android::hardware::tv::tuner::V1_0::DemuxFilterPesEvent; |
shubang | 44fa142 | 2020-01-30 11:42:59 -0800 | [diff] [blame] | 53 | using ::android::hardware::tv::tuner::V1_0::DemuxFilterRecordSettings; |
| 54 | using ::android::hardware::tv::tuner::V1_0::DemuxFilterSectionBits; |
shubang | 3e0c37b | 2020-02-19 19:09:10 -0800 | [diff] [blame] | 55 | using ::android::hardware::tv::tuner::V1_0::DemuxFilterSectionEvent; |
shubang | 44fa142 | 2020-01-30 11:42:59 -0800 | [diff] [blame] | 56 | using ::android::hardware::tv::tuner::V1_0::DemuxFilterSectionSettings; |
shubang | 75c8708 | 2019-11-15 11:26:56 -0800 | [diff] [blame] | 57 | using ::android::hardware::tv::tuner::V1_0::DemuxFilterSettings; |
shubang | 3e0c37b | 2020-02-19 19:09:10 -0800 | [diff] [blame] | 58 | using ::android::hardware::tv::tuner::V1_0::DemuxFilterTemiEvent; |
| 59 | using ::android::hardware::tv::tuner::V1_0::DemuxFilterTsRecordEvent; |
shubang | 87788c3 | 2020-02-04 13:55:23 -0800 | [diff] [blame] | 60 | using ::android::hardware::tv::tuner::V1_0::DemuxIpAddress; |
shubang | 44fa142 | 2020-01-30 11:42:59 -0800 | [diff] [blame] | 61 | using ::android::hardware::tv::tuner::V1_0::DemuxIpFilterSettings; |
| 62 | using ::android::hardware::tv::tuner::V1_0::DemuxIpFilterType; |
| 63 | using ::android::hardware::tv::tuner::V1_0::DemuxMmtpFilterSettings; |
| 64 | using ::android::hardware::tv::tuner::V1_0::DemuxMmtpFilterType; |
shubang | 13f15e0 | 2019-11-04 17:51:02 -0800 | [diff] [blame] | 65 | using ::android::hardware::tv::tuner::V1_0::DemuxMmtpPid; |
shubang | 964e613 | 2019-11-26 15:05:22 -0800 | [diff] [blame] | 66 | using ::android::hardware::tv::tuner::V1_0::DemuxQueueNotifyBits; |
shubang | 44fa142 | 2020-01-30 11:42:59 -0800 | [diff] [blame] | 67 | using ::android::hardware::tv::tuner::V1_0::DemuxRecordScIndexType; |
| 68 | using ::android::hardware::tv::tuner::V1_0::DemuxScHevcIndex; |
| 69 | using ::android::hardware::tv::tuner::V1_0::DemuxScIndex; |
| 70 | using ::android::hardware::tv::tuner::V1_0::DemuxTlvFilterSettings; |
| 71 | using ::android::hardware::tv::tuner::V1_0::DemuxTlvFilterType; |
shubang | 13f15e0 | 2019-11-04 17:51:02 -0800 | [diff] [blame] | 72 | using ::android::hardware::tv::tuner::V1_0::DemuxTpid; |
shubang | 75c8708 | 2019-11-15 11:26:56 -0800 | [diff] [blame] | 73 | using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterSettings; |
shubang | 6f473d6 | 2019-11-01 15:42:21 -0700 | [diff] [blame] | 74 | using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterType; |
shubang | 44fa142 | 2020-01-30 11:42:59 -0800 | [diff] [blame] | 75 | using ::android::hardware::tv::tuner::V1_0::DemuxTsIndex; |
shubang | 030afb5 | 2019-11-27 16:09:02 -0800 | [diff] [blame] | 76 | using ::android::hardware::tv::tuner::V1_0::DvrSettings; |
shubang | 74bfd48 | 2019-10-29 19:10:22 -0700 | [diff] [blame] | 77 | using ::android::hardware::tv::tuner::V1_0::FrontendAnalogSettings; |
| 78 | using ::android::hardware::tv::tuner::V1_0::FrontendAnalogSifStandard; |
| 79 | using ::android::hardware::tv::tuner::V1_0::FrontendAnalogType; |
shubang | deb067c | 2020-01-27 13:21:55 -0800 | [diff] [blame] | 80 | using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3Bandwidth; |
| 81 | using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3CodeRate; |
| 82 | using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3DemodOutputFormat; |
| 83 | using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3Fec; |
| 84 | using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3Modulation; |
| 85 | using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3PlpSettings; |
| 86 | using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3Settings; |
| 87 | using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3TimeInterleaveMode; |
| 88 | using ::android::hardware::tv::tuner::V1_0::FrontendAtscSettings; |
| 89 | using ::android::hardware::tv::tuner::V1_0::FrontendAtscModulation; |
| 90 | using ::android::hardware::tv::tuner::V1_0::FrontendDvbcAnnex; |
| 91 | using ::android::hardware::tv::tuner::V1_0::FrontendDvbcModulation; |
| 92 | using ::android::hardware::tv::tuner::V1_0::FrontendDvbcOuterFec; |
| 93 | using ::android::hardware::tv::tuner::V1_0::FrontendDvbcSettings; |
| 94 | using ::android::hardware::tv::tuner::V1_0::FrontendDvbcSpectralInversion; |
| 95 | using ::android::hardware::tv::tuner::V1_0::FrontendDvbsCodeRate; |
| 96 | using ::android::hardware::tv::tuner::V1_0::FrontendDvbsModulation; |
| 97 | using ::android::hardware::tv::tuner::V1_0::FrontendDvbsPilot; |
| 98 | using ::android::hardware::tv::tuner::V1_0::FrontendDvbsRolloff; |
| 99 | using ::android::hardware::tv::tuner::V1_0::FrontendDvbsSettings; |
| 100 | using ::android::hardware::tv::tuner::V1_0::FrontendDvbsStandard; |
| 101 | using ::android::hardware::tv::tuner::V1_0::FrontendDvbsVcmMode; |
| 102 | using ::android::hardware::tv::tuner::V1_0::FrontendDvbtBandwidth; |
| 103 | using ::android::hardware::tv::tuner::V1_0::FrontendDvbtCoderate; |
| 104 | using ::android::hardware::tv::tuner::V1_0::FrontendDvbtConstellation; |
| 105 | using ::android::hardware::tv::tuner::V1_0::FrontendDvbtGuardInterval; |
| 106 | using ::android::hardware::tv::tuner::V1_0::FrontendDvbtHierarchy; |
| 107 | using ::android::hardware::tv::tuner::V1_0::FrontendDvbtPlpMode; |
| 108 | using ::android::hardware::tv::tuner::V1_0::FrontendDvbtSettings; |
| 109 | using ::android::hardware::tv::tuner::V1_0::FrontendDvbtStandard; |
| 110 | using ::android::hardware::tv::tuner::V1_0::FrontendDvbtTransmissionMode; |
| 111 | using ::android::hardware::tv::tuner::V1_0::FrontendInnerFec; |
| 112 | using ::android::hardware::tv::tuner::V1_0::FrontendIsdbs3Coderate; |
| 113 | using ::android::hardware::tv::tuner::V1_0::FrontendIsdbs3Modulation; |
| 114 | using ::android::hardware::tv::tuner::V1_0::FrontendIsdbs3Rolloff; |
| 115 | using ::android::hardware::tv::tuner::V1_0::FrontendIsdbs3Settings; |
| 116 | using ::android::hardware::tv::tuner::V1_0::FrontendIsdbsCoderate; |
| 117 | using ::android::hardware::tv::tuner::V1_0::FrontendIsdbsModulation; |
| 118 | using ::android::hardware::tv::tuner::V1_0::FrontendIsdbsRolloff; |
| 119 | using ::android::hardware::tv::tuner::V1_0::FrontendIsdbsSettings; |
| 120 | using ::android::hardware::tv::tuner::V1_0::FrontendIsdbsStreamIdType; |
| 121 | using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtBandwidth; |
| 122 | using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtCoderate; |
| 123 | using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtGuardInterval; |
| 124 | using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtMode; |
| 125 | using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtModulation; |
| 126 | using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtSettings; |
shubang | b83f823 | 2020-03-24 18:04:35 -0700 | [diff] [blame] | 127 | using ::android::hardware::tv::tuner::V1_0::FrontendModulationStatus; |
shubang | c8736b7 | 2020-02-11 18:27:53 -0800 | [diff] [blame] | 128 | using ::android::hardware::tv::tuner::V1_0::FrontendScanAtsc3PlpInfo; |
shubang | b83f823 | 2020-03-24 18:04:35 -0700 | [diff] [blame] | 129 | using ::android::hardware::tv::tuner::V1_0::FrontendStatus; |
| 130 | using ::android::hardware::tv::tuner::V1_0::FrontendStatusAtsc3PlpInfo; |
| 131 | using ::android::hardware::tv::tuner::V1_0::FrontendStatusType; |
shubang | deb067c | 2020-01-27 13:21:55 -0800 | [diff] [blame] | 132 | using ::android::hardware::tv::tuner::V1_0::FrontendType; |
shubang | 8ab43b1 | 2019-10-18 15:55:55 -0700 | [diff] [blame] | 133 | using ::android::hardware::tv::tuner::V1_0::ITuner; |
shubang | 1c1144e | 2020-03-03 18:00:17 -0800 | [diff] [blame] | 134 | using ::android::hardware::tv::tuner::V1_0::LnbPosition; |
| 135 | using ::android::hardware::tv::tuner::V1_0::LnbTone; |
| 136 | using ::android::hardware::tv::tuner::V1_0::LnbVoltage; |
shubang | 030afb5 | 2019-11-27 16:09:02 -0800 | [diff] [blame] | 137 | using ::android::hardware::tv::tuner::V1_0::PlaybackSettings; |
| 138 | using ::android::hardware::tv::tuner::V1_0::RecordSettings; |
shubang | 8ab43b1 | 2019-10-18 15:55:55 -0700 | [diff] [blame] | 139 | |
| 140 | struct fields_t { |
shubang | 13f15e0 | 2019-11-04 17:51:02 -0800 | [diff] [blame] | 141 | jfieldID tunerContext; |
shubang | 1c1144e | 2020-03-03 18:00:17 -0800 | [diff] [blame] | 142 | jfieldID lnbContext; |
shubang | cdf30de | 2019-11-06 17:28:38 -0800 | [diff] [blame] | 143 | jfieldID filterContext; |
shubang | f657da2 | 2020-02-05 16:27:06 -0800 | [diff] [blame] | 144 | jfieldID timeFilterContext; |
shubang | 13f15e0 | 2019-11-04 17:51:02 -0800 | [diff] [blame] | 145 | jfieldID descramblerContext; |
shubang | 5637a66 | 2020-02-27 18:06:21 -0800 | [diff] [blame] | 146 | jfieldID dvrRecorderContext; |
| 147 | jfieldID dvrPlaybackContext; |
shubang | 7e849b0 | 2019-10-18 19:36:25 -0700 | [diff] [blame] | 148 | jmethodID frontendInitID; |
shubang | 6f473d6 | 2019-11-01 15:42:21 -0700 | [diff] [blame] | 149 | jmethodID filterInitID; |
shubang | f657da2 | 2020-02-05 16:27:06 -0800 | [diff] [blame] | 150 | jmethodID timeFilterInitID; |
shubang | 5637a66 | 2020-02-27 18:06:21 -0800 | [diff] [blame] | 151 | jmethodID dvrRecorderInitID; |
| 152 | jmethodID dvrPlaybackInitID; |
shubang | 4b8c540 | 2019-10-24 17:49:53 -0700 | [diff] [blame] | 153 | jmethodID onFrontendEventID; |
shubang | cdf30de | 2019-11-06 17:28:38 -0800 | [diff] [blame] | 154 | jmethodID onFilterStatusID; |
shubang | 3e0c37b | 2020-02-19 19:09:10 -0800 | [diff] [blame] | 155 | jmethodID onFilterEventID; |
shubang | 760f031 | 2019-11-12 17:11:28 -0800 | [diff] [blame] | 156 | jmethodID lnbInitID; |
| 157 | jmethodID onLnbEventID; |
shubang | d295be0 | 2020-03-27 17:08:11 -0700 | [diff] [blame] | 158 | jmethodID onLnbDiseqcMessageID; |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 159 | jmethodID onDvrRecordStatusID; |
| 160 | jmethodID onDvrPlaybackStatusID; |
shubang | 13f15e0 | 2019-11-04 17:51:02 -0800 | [diff] [blame] | 161 | jmethodID descramblerInitID; |
shubang | d49681e | 2020-02-17 21:32:30 -0800 | [diff] [blame] | 162 | jmethodID linearBlockInitID; |
| 163 | jmethodID linearBlockSetInternalStateID; |
shubang | 8ab43b1 | 2019-10-18 15:55:55 -0700 | [diff] [blame] | 164 | }; |
| 165 | |
| 166 | static fields_t gFields; |
| 167 | |
shubang | d49681e | 2020-02-17 21:32:30 -0800 | [diff] [blame] | 168 | |
shubang | 87788c3 | 2020-02-04 13:55:23 -0800 | [diff] [blame] | 169 | static int IP_V4_LENGTH = 4; |
| 170 | static int IP_V6_LENGTH = 16; |
| 171 | |
shubang | 8ab43b1 | 2019-10-18 15:55:55 -0700 | [diff] [blame] | 172 | namespace android { |
shubang | 760f031 | 2019-11-12 17:11:28 -0800 | [diff] [blame] | 173 | /////////////// LnbCallback /////////////////////// |
shubang | d295be0 | 2020-03-27 17:08:11 -0700 | [diff] [blame] | 174 | LnbCallback::LnbCallback(jobject lnbObj, LnbId id) : mId(id) { |
| 175 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 176 | mLnb = env->NewWeakGlobalRef(lnbObj); |
| 177 | } |
shubang | 760f031 | 2019-11-12 17:11:28 -0800 | [diff] [blame] | 178 | |
| 179 | Return<void> LnbCallback::onEvent(LnbEventType lnbEventType) { |
| 180 | ALOGD("LnbCallback::onEvent, type=%d", lnbEventType); |
| 181 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 182 | env->CallVoidMethod( |
shubang | d295be0 | 2020-03-27 17:08:11 -0700 | [diff] [blame] | 183 | mLnb, |
shubang | 760f031 | 2019-11-12 17:11:28 -0800 | [diff] [blame] | 184 | gFields.onLnbEventID, |
| 185 | (jint)lnbEventType); |
| 186 | return Void(); |
| 187 | } |
shubang | d295be0 | 2020-03-27 17:08:11 -0700 | [diff] [blame] | 188 | Return<void> LnbCallback::onDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage) { |
shubang | 760f031 | 2019-11-12 17:11:28 -0800 | [diff] [blame] | 189 | ALOGD("LnbCallback::onDiseqcMessage"); |
shubang | d295be0 | 2020-03-27 17:08:11 -0700 | [diff] [blame] | 190 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 191 | jbyteArray array = env->NewByteArray(diseqcMessage.size()); |
| 192 | env->SetByteArrayRegion( |
| 193 | array, 0, diseqcMessage.size(), reinterpret_cast<jbyte*>(diseqcMessage[0])); |
| 194 | |
| 195 | env->CallVoidMethod( |
| 196 | mLnb, |
| 197 | gFields.onLnbDiseqcMessageID, |
| 198 | array); |
shubang | 760f031 | 2019-11-12 17:11:28 -0800 | [diff] [blame] | 199 | return Void(); |
| 200 | } |
| 201 | |
shubang | 1c1144e | 2020-03-03 18:00:17 -0800 | [diff] [blame] | 202 | /////////////// Lnb /////////////////////// |
| 203 | |
| 204 | Lnb::Lnb(sp<ILnb> sp, jobject obj) : mLnbSp(sp) { |
| 205 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 206 | mLnbObj = env->NewWeakGlobalRef(obj); |
| 207 | } |
| 208 | |
| 209 | Lnb::~Lnb() { |
| 210 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 211 | env->DeleteWeakGlobalRef(mLnbObj); |
| 212 | mLnbObj = NULL; |
| 213 | } |
| 214 | |
| 215 | sp<ILnb> Lnb::getILnb() { |
| 216 | return mLnbSp; |
| 217 | } |
| 218 | |
shubang | 4a0eddf | 2019-11-08 17:10:18 -0800 | [diff] [blame] | 219 | /////////////// DvrCallback /////////////////////// |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 220 | Return<void> DvrCallback::onRecordStatus(RecordStatus status) { |
shubang | 4a0eddf | 2019-11-08 17:10:18 -0800 | [diff] [blame] | 221 | ALOGD("DvrCallback::onRecordStatus"); |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 222 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 223 | env->CallVoidMethod( |
| 224 | mDvr, |
| 225 | gFields.onDvrRecordStatusID, |
| 226 | (jint) status); |
shubang | 4a0eddf | 2019-11-08 17:10:18 -0800 | [diff] [blame] | 227 | return Void(); |
| 228 | } |
| 229 | |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 230 | Return<void> DvrCallback::onPlaybackStatus(PlaybackStatus status) { |
shubang | 4a0eddf | 2019-11-08 17:10:18 -0800 | [diff] [blame] | 231 | ALOGD("DvrCallback::onPlaybackStatus"); |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 232 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 233 | env->CallVoidMethod( |
| 234 | mDvr, |
| 235 | gFields.onDvrPlaybackStatusID, |
| 236 | (jint) status); |
shubang | 4a0eddf | 2019-11-08 17:10:18 -0800 | [diff] [blame] | 237 | return Void(); |
| 238 | } |
| 239 | |
| 240 | void DvrCallback::setDvr(const jobject dvr) { |
shubang | ba21a7f | 2019-12-05 16:58:55 -0800 | [diff] [blame] | 241 | ALOGD("DvrCallback::setDvr"); |
shubang | 4a0eddf | 2019-11-08 17:10:18 -0800 | [diff] [blame] | 242 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 243 | mDvr = env->NewWeakGlobalRef(dvr); |
| 244 | } |
| 245 | |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 246 | DvrCallback::~DvrCallback() { |
| 247 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 248 | if (mDvr != NULL) { |
| 249 | env->DeleteWeakGlobalRef(mDvr); |
| 250 | mDvr = NULL; |
| 251 | } |
shubang | ba21a7f | 2019-12-05 16:58:55 -0800 | [diff] [blame] | 252 | } |
| 253 | |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 254 | /////////////// Dvr /////////////////////// |
| 255 | |
| 256 | Dvr::Dvr(sp<IDvr> sp, jobject obj) : mDvrSp(sp), mDvrMQEventFlag(nullptr) { |
| 257 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 258 | mDvrObj = env->NewWeakGlobalRef(obj); |
| 259 | } |
| 260 | |
| 261 | Dvr::~Dvr() { |
| 262 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 263 | env->DeleteWeakGlobalRef(mDvrObj); |
| 264 | mDvrObj = NULL; |
| 265 | } |
| 266 | |
| 267 | jint Dvr::close() { |
shubang | ba21a7f | 2019-12-05 16:58:55 -0800 | [diff] [blame] | 268 | Result r = mDvrSp->close(); |
| 269 | if (r == Result::SUCCESS) { |
| 270 | EventFlag::deleteEventFlag(&mDvrMQEventFlag); |
| 271 | } |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 272 | return (jint) r; |
shubang | ba21a7f | 2019-12-05 16:58:55 -0800 | [diff] [blame] | 273 | } |
| 274 | |
shubang | 9e700ff | 2019-12-04 16:26:51 -0800 | [diff] [blame] | 275 | sp<IDvr> Dvr::getIDvr() { |
| 276 | return mDvrSp; |
| 277 | } |
| 278 | |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 279 | MQ& Dvr::getDvrMQ() { |
shubang | 5f4ea35 | 2019-12-09 15:12:10 -0800 | [diff] [blame] | 280 | return *mDvrMQ; |
| 281 | } |
| 282 | |
shubang | 6f473d6 | 2019-11-01 15:42:21 -0700 | [diff] [blame] | 283 | /////////////// FilterCallback /////////////////////// |
| 284 | //TODO: implement filter callback |
shubang | d49681e | 2020-02-17 21:32:30 -0800 | [diff] [blame] | 285 | jobject FilterCallback::handleToLinearBlock(const native_handle_t* handle, uint32_t size) { |
| 286 | ALOGD("FilterCallback::handleToLinearBlock"); |
| 287 | C2HandleIon* ion = new C2HandleIon(handle->data[0], size); |
| 288 | std::shared_ptr<C2LinearBlock> block = _C2BlockFactory::CreateLinearBlock(ion); |
| 289 | |
| 290 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 291 | std::unique_ptr<JMediaCodecLinearBlock> context{new JMediaCodecLinearBlock}; |
| 292 | context->mBlock = block; |
| 293 | |
| 294 | jobject linearBlock = |
| 295 | env->NewObject( |
| 296 | env->FindClass("android/media/MediaCodec$LinearBlock"), |
| 297 | gFields.linearBlockInitID); |
| 298 | env->CallVoidMethod( |
| 299 | linearBlock, |
| 300 | gFields.linearBlockSetInternalStateID, |
| 301 | (jlong)context.release(), |
| 302 | true); |
| 303 | return linearBlock; |
| 304 | } |
| 305 | |
shubang | 3e0c37b | 2020-02-19 19:09:10 -0800 | [diff] [blame] | 306 | jobjectArray FilterCallback::getSectionEvent( |
| 307 | jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) { |
shubang | d49681e | 2020-02-17 21:32:30 -0800 | [diff] [blame] | 308 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
shubang | 3e0c37b | 2020-02-19 19:09:10 -0800 | [diff] [blame] | 309 | jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/SectionEvent"); |
| 310 | jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(IIII)V"); |
| 311 | |
| 312 | for (int i = 0; i < events.size(); i++) { |
| 313 | auto event = events[i]; |
| 314 | DemuxFilterSectionEvent sectionEvent = event.section(); |
| 315 | |
| 316 | jint tableId = static_cast<jint>(sectionEvent.tableId); |
| 317 | jint version = static_cast<jint>(sectionEvent.version); |
| 318 | jint sectionNum = static_cast<jint>(sectionEvent.sectionNum); |
| 319 | jint dataLength = static_cast<jint>(sectionEvent.dataLength); |
| 320 | |
| 321 | jobject obj = |
| 322 | env->NewObject(eventClazz, eventInit, tableId, version, sectionNum, dataLength); |
| 323 | env->SetObjectArrayElement(arr, i, obj); |
| 324 | } |
| 325 | return arr; |
| 326 | } |
| 327 | |
| 328 | jobjectArray FilterCallback::getMediaEvent( |
| 329 | jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) { |
| 330 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 331 | jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/MediaEvent"); |
| 332 | jmethodID eventInit = env->GetMethodID(eventClazz, |
shubang | d49681e | 2020-02-17 21:32:30 -0800 | [diff] [blame] | 333 | "<init>", |
| 334 | "(IZJJJLandroid/media/MediaCodec$LinearBlock;" |
| 335 | "ZJIZLandroid/media/tv/tuner/filter/AudioDescriptor;)V"); |
| 336 | |
shubang | 3e0c37b | 2020-02-19 19:09:10 -0800 | [diff] [blame] | 337 | for (int i = 0; i < events.size(); i++) { |
| 338 | auto event = events[i]; |
| 339 | DemuxFilterMediaEvent mediaEvent = event.media(); |
shubang | d49681e | 2020-02-17 21:32:30 -0800 | [diff] [blame] | 340 | |
shubang | 3e0c37b | 2020-02-19 19:09:10 -0800 | [diff] [blame] | 341 | jobject audioDescriptor = NULL; |
| 342 | if (mediaEvent.extraMetaData.getDiscriminator() |
| 343 | == DemuxFilterMediaEvent::ExtraMetaData::hidl_discriminator::audio) { |
| 344 | jclass adClazz = env->FindClass("android/media/tv/tuner/filter/AudioDescriptor"); |
| 345 | jmethodID adInit = env->GetMethodID(adClazz, "<init>", "(BBCBBB)V"); |
| 346 | |
| 347 | AudioExtraMetaData ad = mediaEvent.extraMetaData.audio(); |
| 348 | jbyte adFade = static_cast<jbyte>(ad.adFade); |
| 349 | jbyte adPan = static_cast<jbyte>(ad.adPan); |
| 350 | jchar versionTextTag = static_cast<jchar>(ad.versionTextTag); |
| 351 | jbyte adGainCenter = static_cast<jbyte>(ad.adGainCenter); |
| 352 | jbyte adGainFront = static_cast<jbyte>(ad.adGainFront); |
| 353 | jbyte adGainSurround = static_cast<jbyte>(ad.adGainSurround); |
| 354 | |
| 355 | audioDescriptor = |
| 356 | env->NewObject(adClazz, adInit, adFade, adPan, versionTextTag, adGainCenter, |
| 357 | adGainFront, adGainSurround); |
| 358 | } |
| 359 | |
| 360 | jlong dataLength = static_cast<jlong>(mediaEvent.dataLength); |
| 361 | const native_handle_t* h = NULL; |
| 362 | jobject block = NULL; |
| 363 | if (mediaEvent.avMemory != NULL) { |
| 364 | h = mediaEvent.avMemory.getNativeHandle(); |
| 365 | block = handleToLinearBlock(h, dataLength); |
| 366 | } |
| 367 | |
| 368 | jint streamId = static_cast<jint>(mediaEvent.streamId); |
| 369 | jboolean isPtsPresent = static_cast<jboolean>(mediaEvent.isPtsPresent); |
| 370 | jlong pts = static_cast<jlong>(mediaEvent.pts); |
| 371 | jlong offset = static_cast<jlong>(mediaEvent.offset); |
| 372 | jboolean isSecureMemory = static_cast<jboolean>(mediaEvent.isSecureMemory); |
| 373 | jlong avDataId = static_cast<jlong>(mediaEvent.avDataId); |
| 374 | jint mpuSequenceNumber = static_cast<jint>(mediaEvent.mpuSequenceNumber); |
| 375 | jboolean isPesPrivateData = static_cast<jboolean>(mediaEvent.isPesPrivateData); |
| 376 | |
| 377 | jobject obj = |
| 378 | env->NewObject(eventClazz, eventInit, streamId, isPtsPresent, pts, dataLength, |
| 379 | offset, block, isSecureMemory, avDataId, mpuSequenceNumber, isPesPrivateData, |
| 380 | audioDescriptor); |
| 381 | env->SetObjectArrayElement(arr, i, obj); |
| 382 | } |
| 383 | return arr; |
| 384 | } |
| 385 | |
| 386 | jobjectArray FilterCallback::getPesEvent( |
| 387 | jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) { |
| 388 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 389 | jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/PesEvent"); |
| 390 | jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(III)V"); |
| 391 | |
| 392 | for (int i = 0; i < events.size(); i++) { |
| 393 | auto event = events[i]; |
| 394 | DemuxFilterPesEvent pesEvent = event.pes(); |
| 395 | |
| 396 | jint streamId = static_cast<jint>(pesEvent.streamId); |
| 397 | jint dataLength = static_cast<jint>(pesEvent.dataLength); |
| 398 | jint mpuSequenceNumber = static_cast<jint>(pesEvent.mpuSequenceNumber); |
| 399 | |
| 400 | jobject obj = |
| 401 | env->NewObject(eventClazz, eventInit, streamId, dataLength, mpuSequenceNumber); |
| 402 | env->SetObjectArrayElement(arr, i, obj); |
| 403 | } |
| 404 | return arr; |
| 405 | } |
| 406 | |
| 407 | jobjectArray FilterCallback::getTsRecordEvent( |
| 408 | jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) { |
| 409 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 410 | jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/TsRecordEvent"); |
| 411 | jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(IIIJ)V"); |
| 412 | |
| 413 | for (int i = 0; i < events.size(); i++) { |
| 414 | auto event = events[i]; |
| 415 | DemuxFilterTsRecordEvent tsRecordEvent = event.tsRecord(); |
| 416 | DemuxPid pid = tsRecordEvent.pid; |
| 417 | |
| 418 | jint jpid = static_cast<jint>(Constant::INVALID_TS_PID); |
| 419 | |
| 420 | if (pid.getDiscriminator() == DemuxPid::hidl_discriminator::tPid) { |
| 421 | jpid = static_cast<jint>(pid.tPid()); |
| 422 | } else if (pid.getDiscriminator() == DemuxPid::hidl_discriminator::mmtpPid) { |
| 423 | jpid = static_cast<jint>(pid.mmtpPid()); |
| 424 | } |
| 425 | |
| 426 | jint sc = 0; |
| 427 | |
| 428 | if (tsRecordEvent.scIndexMask.getDiscriminator() |
| 429 | == DemuxFilterTsRecordEvent::ScIndexMask::hidl_discriminator::sc) { |
| 430 | sc = static_cast<jint>(tsRecordEvent.scIndexMask.sc()); |
| 431 | } else if (tsRecordEvent.scIndexMask.getDiscriminator() |
| 432 | == DemuxFilterTsRecordEvent::ScIndexMask::hidl_discriminator::scHevc) { |
| 433 | sc = static_cast<jint>(tsRecordEvent.scIndexMask.scHevc()); |
| 434 | } |
| 435 | |
| 436 | jint ts = static_cast<jint>(tsRecordEvent.tsIndexMask); |
| 437 | |
| 438 | jlong byteNumber = static_cast<jlong>(tsRecordEvent.byteNumber); |
| 439 | |
| 440 | jobject obj = |
| 441 | env->NewObject(eventClazz, eventInit, jpid, ts, sc, byteNumber); |
| 442 | env->SetObjectArrayElement(arr, i, obj); |
| 443 | } |
| 444 | return arr; |
| 445 | } |
| 446 | |
| 447 | jobjectArray FilterCallback::getMmtpRecordEvent( |
| 448 | jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) { |
| 449 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 450 | jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/MmtpRecordEvent"); |
| 451 | jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(IJ)V"); |
| 452 | |
| 453 | for (int i = 0; i < events.size(); i++) { |
| 454 | auto event = events[i]; |
| 455 | DemuxFilterMmtpRecordEvent mmtpRecordEvent = event.mmtpRecord(); |
| 456 | |
| 457 | jint scHevcIndexMask = static_cast<jint>(mmtpRecordEvent.scHevcIndexMask); |
| 458 | jlong byteNumber = static_cast<jlong>(mmtpRecordEvent.byteNumber); |
| 459 | |
| 460 | jobject obj = |
| 461 | env->NewObject(eventClazz, eventInit, scHevcIndexMask, byteNumber); |
| 462 | env->SetObjectArrayElement(arr, i, obj); |
| 463 | } |
| 464 | return arr; |
| 465 | } |
| 466 | |
| 467 | jobjectArray FilterCallback::getDownloadEvent( |
| 468 | jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) { |
| 469 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 470 | jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/DownloadEvent"); |
| 471 | jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(IIIII)V"); |
| 472 | |
| 473 | for (int i = 0; i < events.size(); i++) { |
| 474 | auto event = events[i]; |
| 475 | DemuxFilterDownloadEvent downloadEvent = event.download(); |
| 476 | |
| 477 | jint itemId = static_cast<jint>(downloadEvent.itemId); |
| 478 | jint mpuSequenceNumber = static_cast<jint>(downloadEvent.mpuSequenceNumber); |
| 479 | jint itemFragmentIndex = static_cast<jint>(downloadEvent.itemFragmentIndex); |
| 480 | jint lastItemFragmentIndex = static_cast<jint>(downloadEvent.lastItemFragmentIndex); |
| 481 | jint dataLength = static_cast<jint>(downloadEvent.dataLength); |
| 482 | |
| 483 | jobject obj = |
| 484 | env->NewObject(eventClazz, eventInit, itemId, mpuSequenceNumber, itemFragmentIndex, |
| 485 | lastItemFragmentIndex, dataLength); |
| 486 | env->SetObjectArrayElement(arr, i, obj); |
| 487 | } |
| 488 | return arr; |
| 489 | } |
| 490 | |
| 491 | jobjectArray FilterCallback::getIpPayloadEvent( |
| 492 | jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) { |
| 493 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 494 | jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/IpPayloadEvent"); |
| 495 | jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(I)V"); |
| 496 | |
| 497 | for (int i = 0; i < events.size(); i++) { |
| 498 | auto event = events[i]; |
| 499 | DemuxFilterIpPayloadEvent ipPayloadEvent = event.ipPayload(); |
| 500 | jint dataLength = static_cast<jint>(ipPayloadEvent.dataLength); |
| 501 | jobject obj = env->NewObject(eventClazz, eventInit, dataLength); |
| 502 | env->SetObjectArrayElement(arr, i, obj); |
| 503 | } |
| 504 | return arr; |
| 505 | } |
| 506 | |
| 507 | jobjectArray FilterCallback::getTemiEvent( |
| 508 | jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) { |
| 509 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 510 | jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/TemiEvent"); |
| 511 | jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(JB[B)V"); |
| 512 | |
| 513 | for (int i = 0; i < events.size(); i++) { |
| 514 | auto event = events[i]; |
| 515 | DemuxFilterTemiEvent temiEvent = event.temi(); |
| 516 | jlong pts = static_cast<jlong>(temiEvent.pts); |
| 517 | jbyte descrTag = static_cast<jbyte>(temiEvent.descrTag); |
| 518 | std::vector<uint8_t> descrData = temiEvent.descrData; |
| 519 | |
| 520 | jbyteArray array = env->NewByteArray(descrData.size()); |
| 521 | env->SetByteArrayRegion( |
| 522 | array, 0, descrData.size(), reinterpret_cast<jbyte*>(&descrData[0])); |
| 523 | |
| 524 | jobject obj = env->NewObject(eventClazz, eventInit, pts, descrTag, array); |
| 525 | env->SetObjectArrayElement(arr, i, obj); |
| 526 | } |
| 527 | return arr; |
shubang | d49681e | 2020-02-17 21:32:30 -0800 | [diff] [blame] | 528 | } |
| 529 | |
| 530 | Return<void> FilterCallback::onFilterEvent(const DemuxFilterEvent& filterEvent) { |
shubang | 6f473d6 | 2019-11-01 15:42:21 -0700 | [diff] [blame] | 531 | ALOGD("FilterCallback::onFilterEvent"); |
shubang | d49681e | 2020-02-17 21:32:30 -0800 | [diff] [blame] | 532 | |
| 533 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
shubang | d49681e | 2020-02-17 21:32:30 -0800 | [diff] [blame] | 534 | |
| 535 | std::vector<DemuxFilterEvent::Event> events = filterEvent.events; |
| 536 | jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/FilterEvent"); |
| 537 | jobjectArray array = env->NewObjectArray(events.size(), eventClazz, NULL); |
| 538 | |
shubang | 3e0c37b | 2020-02-19 19:09:10 -0800 | [diff] [blame] | 539 | if (!events.empty()) { |
| 540 | auto event = events[0]; |
| 541 | switch (event.getDiscriminator()) { |
| 542 | case DemuxFilterEvent::Event::hidl_discriminator::media: { |
| 543 | array = getMediaEvent(array, events); |
| 544 | break; |
| 545 | } |
| 546 | case DemuxFilterEvent::Event::hidl_discriminator::section: { |
| 547 | array = getSectionEvent(array, events); |
| 548 | break; |
| 549 | } |
| 550 | case DemuxFilterEvent::Event::hidl_discriminator::pes: { |
| 551 | array = getPesEvent(array, events); |
| 552 | break; |
| 553 | } |
| 554 | case DemuxFilterEvent::Event::hidl_discriminator::tsRecord: { |
| 555 | array = getTsRecordEvent(array, events); |
| 556 | break; |
| 557 | } |
| 558 | case DemuxFilterEvent::Event::hidl_discriminator::mmtpRecord: { |
| 559 | array = getMmtpRecordEvent(array, events); |
| 560 | break; |
| 561 | } |
| 562 | case DemuxFilterEvent::Event::hidl_discriminator::download: { |
| 563 | array = getDownloadEvent(array, events); |
| 564 | break; |
| 565 | } |
| 566 | case DemuxFilterEvent::Event::hidl_discriminator::ipPayload: { |
| 567 | array = getIpPayloadEvent(array, events); |
| 568 | break; |
| 569 | } |
| 570 | case DemuxFilterEvent::Event::hidl_discriminator::temi: { |
| 571 | array = getTemiEvent(array, events); |
| 572 | break; |
| 573 | } |
| 574 | default: { |
| 575 | break; |
| 576 | } |
shubang | d49681e | 2020-02-17 21:32:30 -0800 | [diff] [blame] | 577 | } |
| 578 | } |
| 579 | env->CallVoidMethod( |
| 580 | mFilter, |
shubang | 3e0c37b | 2020-02-19 19:09:10 -0800 | [diff] [blame] | 581 | gFields.onFilterEventID, |
shubang | d49681e | 2020-02-17 21:32:30 -0800 | [diff] [blame] | 582 | array); |
shubang | 6f473d6 | 2019-11-01 15:42:21 -0700 | [diff] [blame] | 583 | return Void(); |
| 584 | } |
shubang | cdf30de | 2019-11-06 17:28:38 -0800 | [diff] [blame] | 585 | |
shubang | 3e0c37b | 2020-02-19 19:09:10 -0800 | [diff] [blame] | 586 | |
shubang | cdf30de | 2019-11-06 17:28:38 -0800 | [diff] [blame] | 587 | Return<void> FilterCallback::onFilterStatus(const DemuxFilterStatus status) { |
| 588 | ALOGD("FilterCallback::onFilterStatus"); |
| 589 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 590 | env->CallVoidMethod( |
| 591 | mFilter, |
| 592 | gFields.onFilterStatusID, |
| 593 | (jint)status); |
shubang | 6f473d6 | 2019-11-01 15:42:21 -0700 | [diff] [blame] | 594 | return Void(); |
| 595 | } |
shubang | 8ab43b1 | 2019-10-18 15:55:55 -0700 | [diff] [blame] | 596 | |
shubang | cdf30de | 2019-11-06 17:28:38 -0800 | [diff] [blame] | 597 | void FilterCallback::setFilter(const jobject filter) { |
| 598 | ALOGD("FilterCallback::setFilter"); |
| 599 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 600 | mFilter = env->NewWeakGlobalRef(filter); |
| 601 | } |
| 602 | |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 603 | FilterCallback::~FilterCallback() { |
| 604 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 605 | if (mFilter != NULL) { |
| 606 | env->DeleteWeakGlobalRef(mFilter); |
| 607 | mFilter = NULL; |
| 608 | } |
| 609 | } |
| 610 | |
shubang | 7648a3c | 2019-11-25 18:16:45 -0800 | [diff] [blame] | 611 | /////////////// Filter /////////////////////// |
| 612 | |
shubang | 3e0c37b | 2020-02-19 19:09:10 -0800 | [diff] [blame] | 613 | Filter::Filter(sp<IFilter> sp, jobject obj) : mFilterSp(sp) { |
| 614 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 615 | mFilterObj = env->NewWeakGlobalRef(obj); |
| 616 | } |
shubang | 7648a3c | 2019-11-25 18:16:45 -0800 | [diff] [blame] | 617 | |
shubang | 964e613 | 2019-11-26 15:05:22 -0800 | [diff] [blame] | 618 | Filter::~Filter() { |
shubang | 3e0c37b | 2020-02-19 19:09:10 -0800 | [diff] [blame] | 619 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 620 | |
| 621 | env->DeleteWeakGlobalRef(mFilterObj); |
| 622 | mFilterObj = NULL; |
shubang | 964e613 | 2019-11-26 15:05:22 -0800 | [diff] [blame] | 623 | EventFlag::deleteEventFlag(&mFilterMQEventFlag); |
| 624 | } |
| 625 | |
| 626 | int Filter::close() { |
| 627 | Result r = mFilterSp->close(); |
| 628 | if (r == Result::SUCCESS) { |
| 629 | EventFlag::deleteEventFlag(&mFilterMQEventFlag); |
| 630 | } |
| 631 | return (int)r; |
| 632 | } |
| 633 | |
shubang | 7648a3c | 2019-11-25 18:16:45 -0800 | [diff] [blame] | 634 | sp<IFilter> Filter::getIFilter() { |
| 635 | return mFilterSp; |
| 636 | } |
| 637 | |
shubang | f657da2 | 2020-02-05 16:27:06 -0800 | [diff] [blame] | 638 | /////////////// TimeFilter /////////////////////// |
| 639 | |
| 640 | TimeFilter::TimeFilter(sp<ITimeFilter> sp, jobject obj) : mTimeFilterSp(sp) { |
| 641 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 642 | mTimeFilterObj = env->NewWeakGlobalRef(obj); |
| 643 | } |
| 644 | |
| 645 | TimeFilter::~TimeFilter() { |
| 646 | ALOGD("~TimeFilter"); |
| 647 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 648 | |
| 649 | env->DeleteWeakGlobalRef(mTimeFilterObj); |
| 650 | mTimeFilterObj = NULL; |
| 651 | } |
| 652 | |
| 653 | sp<ITimeFilter> TimeFilter::getITimeFilter() { |
| 654 | return mTimeFilterSp; |
| 655 | } |
| 656 | |
shubang | 4b8c540 | 2019-10-24 17:49:53 -0700 | [diff] [blame] | 657 | /////////////// FrontendCallback /////////////////////// |
| 658 | |
| 659 | FrontendCallback::FrontendCallback(jweak tunerObj, FrontendId id) : mObject(tunerObj), mId(id) {} |
| 660 | |
| 661 | Return<void> FrontendCallback::onEvent(FrontendEventType frontendEventType) { |
| 662 | ALOGD("FrontendCallback::onEvent, type=%d", frontendEventType); |
| 663 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 664 | env->CallVoidMethod( |
| 665 | mObject, |
| 666 | gFields.onFrontendEventID, |
| 667 | (jint)frontendEventType); |
| 668 | return Void(); |
| 669 | } |
shubang | 4b8c540 | 2019-10-24 17:49:53 -0700 | [diff] [blame] | 670 | |
shubang | c8736b7 | 2020-02-11 18:27:53 -0800 | [diff] [blame] | 671 | Return<void> FrontendCallback::onScanMessage(FrontendScanMessageType type, const FrontendScanMessage& message) { |
shubang | 4b8c540 | 2019-10-24 17:49:53 -0700 | [diff] [blame] | 672 | ALOGD("FrontendCallback::onScanMessage, type=%d", type); |
shubang | c8736b7 | 2020-02-11 18:27:53 -0800 | [diff] [blame] | 673 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 674 | jclass clazz = env->FindClass("android/media/tv/tuner/Tuner"); |
| 675 | switch(type) { |
| 676 | case FrontendScanMessageType::LOCKED: { |
| 677 | if (message.isLocked()) { |
| 678 | env->CallVoidMethod( |
| 679 | mObject, |
| 680 | env->GetMethodID(clazz, "onLocked", "()V")); |
| 681 | } |
| 682 | break; |
| 683 | } |
| 684 | case FrontendScanMessageType::END: { |
| 685 | if (message.isEnd()) { |
| 686 | env->CallVoidMethod( |
| 687 | mObject, |
| 688 | env->GetMethodID(clazz, "onScanStopped", "()V")); |
| 689 | } |
| 690 | break; |
| 691 | } |
| 692 | case FrontendScanMessageType::PROGRESS_PERCENT: { |
| 693 | env->CallVoidMethod( |
| 694 | mObject, |
| 695 | env->GetMethodID(clazz, "onProgress", "(I)V"), |
| 696 | (jint) message.progressPercent()); |
| 697 | break; |
| 698 | } |
| 699 | case FrontendScanMessageType::FREQUENCY: { |
| 700 | std::vector<uint32_t> v = message.frequencies(); |
| 701 | jintArray freqs = env->NewIntArray(v.size()); |
| 702 | env->SetIntArrayRegion(freqs, 0, v.size(), reinterpret_cast<jint*>(&v[0])); |
| 703 | |
| 704 | env->CallVoidMethod( |
| 705 | mObject, |
| 706 | env->GetMethodID(clazz, "onFrequenciesReport", "([I)V"), |
| 707 | freqs); |
| 708 | break; |
| 709 | } |
| 710 | case FrontendScanMessageType::SYMBOL_RATE: { |
| 711 | std::vector<uint32_t> v = message.symbolRates(); |
| 712 | jintArray symbolRates = env->NewIntArray(v.size()); |
| 713 | env->SetIntArrayRegion(symbolRates, 0, v.size(), reinterpret_cast<jint*>(&v[0])); |
| 714 | |
| 715 | env->CallVoidMethod( |
| 716 | mObject, |
| 717 | env->GetMethodID(clazz, "onSymbolRates", "([I)V"), |
| 718 | symbolRates); |
| 719 | break; |
| 720 | } |
| 721 | case FrontendScanMessageType::HIERARCHY: { |
| 722 | env->CallVoidMethod( |
| 723 | mObject, |
| 724 | env->GetMethodID(clazz, "onHierarchy", "(I)V"), |
| 725 | (jint) message.hierarchy()); |
| 726 | break; |
| 727 | } |
| 728 | case FrontendScanMessageType::ANALOG_TYPE: { |
| 729 | env->CallVoidMethod( |
| 730 | mObject, |
| 731 | env->GetMethodID(clazz, "onSignalType", "(I)V"), |
| 732 | (jint) message.analogType()); |
| 733 | break; |
| 734 | } |
| 735 | case FrontendScanMessageType::PLP_IDS: { |
| 736 | std::vector<uint8_t> v = message.plpIds(); |
| 737 | std::vector<jint> jintV(v.begin(), v.end()); |
| 738 | jintArray plpIds = env->NewIntArray(v.size()); |
| 739 | env->SetIntArrayRegion(plpIds, 0, jintV.size(), &jintV[0]); |
| 740 | |
| 741 | env->CallVoidMethod( |
| 742 | mObject, |
| 743 | env->GetMethodID(clazz, "onPlpIds", "([I)V"), |
| 744 | plpIds); |
| 745 | break; |
| 746 | } |
| 747 | case FrontendScanMessageType::GROUP_IDS: { |
| 748 | std::vector<uint8_t> v = message.groupIds(); |
| 749 | std::vector<jint> jintV(v.begin(), v.end()); |
| 750 | jintArray groupIds = env->NewIntArray(v.size()); |
| 751 | env->SetIntArrayRegion(groupIds, 0, jintV.size(), &jintV[0]); |
| 752 | |
| 753 | env->CallVoidMethod( |
| 754 | mObject, |
| 755 | env->GetMethodID(clazz, "onGroupIds", "([I)V"), |
| 756 | groupIds); |
| 757 | break; |
| 758 | } |
| 759 | case FrontendScanMessageType::INPUT_STREAM_IDS: { |
| 760 | std::vector<uint16_t> v = message.inputStreamIds(); |
| 761 | std::vector<jint> jintV(v.begin(), v.end()); |
| 762 | jintArray streamIds = env->NewIntArray(v.size()); |
| 763 | env->SetIntArrayRegion(streamIds, 0, jintV.size(), &jintV[0]); |
| 764 | |
| 765 | env->CallVoidMethod( |
| 766 | mObject, |
| 767 | env->GetMethodID(clazz, "onInputStreamIds", "([I)V"), |
| 768 | streamIds); |
| 769 | break; |
| 770 | } |
| 771 | case FrontendScanMessageType::STANDARD: { |
| 772 | FrontendScanMessage::Standard std = message.std(); |
| 773 | jint standard; |
| 774 | if (std.getDiscriminator() == FrontendScanMessage::Standard::hidl_discriminator::sStd) { |
| 775 | standard = (jint) std.sStd(); |
| 776 | env->CallVoidMethod( |
| 777 | mObject, |
| 778 | env->GetMethodID(clazz, "onDvbsStandard", "(I)V"), |
| 779 | standard); |
| 780 | } else if (std.getDiscriminator() == FrontendScanMessage::Standard::hidl_discriminator::tStd) { |
| 781 | standard = (jint) std.tStd(); |
| 782 | env->CallVoidMethod( |
| 783 | mObject, |
| 784 | env->GetMethodID(clazz, "onDvbtStandard", "(I)V"), |
| 785 | standard); |
| 786 | } else if (std.getDiscriminator() == FrontendScanMessage::Standard::hidl_discriminator::sifStd) { |
| 787 | standard = (jint) std.sifStd(); |
| 788 | env->CallVoidMethod( |
| 789 | mObject, |
| 790 | env->GetMethodID(clazz, "onAnalogSifStandard", "(I)V"), |
| 791 | standard); |
| 792 | } |
| 793 | break; |
| 794 | } |
| 795 | case FrontendScanMessageType::ATSC3_PLP_INFO: { |
| 796 | jclass plpClazz = env->FindClass("android/media/tv/tuner/frontend/Atsc3PlpInfo"); |
| 797 | jmethodID init = env->GetMethodID(plpClazz, "<init>", "(IZ)V"); |
| 798 | std::vector<FrontendScanAtsc3PlpInfo> plpInfos = message.atsc3PlpInfos(); |
| 799 | jobjectArray array = env->NewObjectArray(plpInfos.size(), plpClazz, NULL); |
| 800 | |
| 801 | for (int i = 0; i < plpInfos.size(); i++) { |
| 802 | auto info = plpInfos[i]; |
| 803 | jint plpId = (jint) info.plpId; |
| 804 | jboolean lls = (jboolean) info.bLlsFlag; |
| 805 | |
| 806 | jobject obj = env->NewObject(plpClazz, init, plpId, lls); |
| 807 | env->SetObjectArrayElement(array, i, obj); |
| 808 | } |
| 809 | env->CallVoidMethod( |
| 810 | mObject, |
| 811 | env->GetMethodID(clazz, "onAtsc3PlpInfos", "([Landroid/media/tv/tuner/frontend/Atsc3PlpInfo;)V"), |
| 812 | array); |
| 813 | break; |
| 814 | } |
| 815 | } |
shubang | 4b8c540 | 2019-10-24 17:49:53 -0700 | [diff] [blame] | 816 | return Void(); |
| 817 | } |
| 818 | |
shubang | 6f473d6 | 2019-11-01 15:42:21 -0700 | [diff] [blame] | 819 | /////////////// Tuner /////////////////////// |
shubang | 4b8c540 | 2019-10-24 17:49:53 -0700 | [diff] [blame] | 820 | |
shubang | 8ab43b1 | 2019-10-18 15:55:55 -0700 | [diff] [blame] | 821 | sp<ITuner> JTuner::mTuner; |
| 822 | |
| 823 | JTuner::JTuner(JNIEnv *env, jobject thiz) |
| 824 | : mClass(NULL) { |
| 825 | jclass clazz = env->GetObjectClass(thiz); |
| 826 | CHECK(clazz != NULL); |
| 827 | |
| 828 | mClass = (jclass)env->NewGlobalRef(clazz); |
| 829 | mObject = env->NewWeakGlobalRef(thiz); |
| 830 | if (mTuner == NULL) { |
| 831 | mTuner = getTunerService(); |
| 832 | } |
| 833 | } |
| 834 | |
| 835 | JTuner::~JTuner() { |
shubang | 2f9cab3 | 2020-04-10 18:00:56 -0700 | [diff] [blame] | 836 | if (mFe != NULL) { |
| 837 | mFe->close(); |
| 838 | } |
| 839 | if (mDemux != NULL) { |
| 840 | mDemux->close(); |
| 841 | } |
shubang | 8ab43b1 | 2019-10-18 15:55:55 -0700 | [diff] [blame] | 842 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 843 | |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 844 | env->DeleteWeakGlobalRef(mObject); |
shubang | 8ab43b1 | 2019-10-18 15:55:55 -0700 | [diff] [blame] | 845 | env->DeleteGlobalRef(mClass); |
| 846 | mTuner = NULL; |
| 847 | mClass = NULL; |
| 848 | mObject = NULL; |
| 849 | } |
| 850 | |
| 851 | sp<ITuner> JTuner::getTunerService() { |
| 852 | if (mTuner == nullptr) { |
| 853 | mTuner = ITuner::getService(); |
| 854 | |
| 855 | if (mTuner == nullptr) { |
| 856 | ALOGW("Failed to get tuner service."); |
| 857 | } |
| 858 | } |
| 859 | return mTuner; |
| 860 | } |
| 861 | |
shubang | 7e849b0 | 2019-10-18 19:36:25 -0700 | [diff] [blame] | 862 | jobject JTuner::getFrontendIds() { |
| 863 | ALOGD("JTuner::getFrontendIds()"); |
shubang | 7e849b0 | 2019-10-18 19:36:25 -0700 | [diff] [blame] | 864 | mTuner->getFrontendIds([&](Result, const hidl_vec<FrontendId>& frontendIds) { |
shubang | 4b8c540 | 2019-10-24 17:49:53 -0700 | [diff] [blame] | 865 | mFeIds = frontendIds; |
shubang | 7e849b0 | 2019-10-18 19:36:25 -0700 | [diff] [blame] | 866 | }); |
shubang | 4b8c540 | 2019-10-24 17:49:53 -0700 | [diff] [blame] | 867 | if (mFeIds.size() == 0) { |
shubang | 7e849b0 | 2019-10-18 19:36:25 -0700 | [diff] [blame] | 868 | ALOGW("Frontend isn't available"); |
| 869 | return NULL; |
| 870 | } |
| 871 | |
| 872 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 873 | jclass arrayListClazz = env->FindClass("java/util/ArrayList"); |
| 874 | jmethodID arrayListAdd = env->GetMethodID(arrayListClazz, "add", "(Ljava/lang/Object;)Z"); |
| 875 | jobject obj = env->NewObject(arrayListClazz, env->GetMethodID(arrayListClazz, "<init>", "()V")); |
| 876 | |
| 877 | jclass integerClazz = env->FindClass("java/lang/Integer"); |
| 878 | jmethodID intInit = env->GetMethodID(integerClazz, "<init>", "(I)V"); |
| 879 | |
shubang | 4b8c540 | 2019-10-24 17:49:53 -0700 | [diff] [blame] | 880 | for (int i=0; i < mFeIds.size(); i++) { |
| 881 | jobject idObj = env->NewObject(integerClazz, intInit, mFeIds[i]); |
shubang | 7e849b0 | 2019-10-18 19:36:25 -0700 | [diff] [blame] | 882 | env->CallBooleanMethod(obj, arrayListAdd, idObj); |
| 883 | } |
| 884 | return obj; |
| 885 | } |
| 886 | |
| 887 | jobject JTuner::openFrontendById(int id) { |
shubang | 4b8c540 | 2019-10-24 17:49:53 -0700 | [diff] [blame] | 888 | sp<IFrontend> fe; |
shubang | 66cc3aa | 2020-04-06 17:10:01 -0700 | [diff] [blame] | 889 | Result res; |
| 890 | mTuner->openFrontendById(id, [&](Result r, const sp<IFrontend>& frontend) { |
shubang | 4b8c540 | 2019-10-24 17:49:53 -0700 | [diff] [blame] | 891 | fe = frontend; |
shubang | 66cc3aa | 2020-04-06 17:10:01 -0700 | [diff] [blame] | 892 | res = r; |
shubang | 7e849b0 | 2019-10-18 19:36:25 -0700 | [diff] [blame] | 893 | }); |
shubang | 66cc3aa | 2020-04-06 17:10:01 -0700 | [diff] [blame] | 894 | if (res != Result::SUCCESS || fe == nullptr) { |
shubang | 7e849b0 | 2019-10-18 19:36:25 -0700 | [diff] [blame] | 895 | ALOGE("Failed to open frontend"); |
| 896 | return NULL; |
| 897 | } |
shubang | 4b8c540 | 2019-10-24 17:49:53 -0700 | [diff] [blame] | 898 | mFe = fe; |
shubang | d295be0 | 2020-03-27 17:08:11 -0700 | [diff] [blame] | 899 | mFeId = id; |
| 900 | if (mDemux != NULL) { |
| 901 | mDemux->setFrontendDataSource(mFeId); |
| 902 | } |
shubang | 4b8c540 | 2019-10-24 17:49:53 -0700 | [diff] [blame] | 903 | sp<FrontendCallback> feCb = new FrontendCallback(mObject, id); |
| 904 | fe->setCallback(feCb); |
shubang | 7e849b0 | 2019-10-18 19:36:25 -0700 | [diff] [blame] | 905 | |
| 906 | jint jId = (jint) id; |
shubang | 964e613 | 2019-11-26 15:05:22 -0800 | [diff] [blame] | 907 | |
shubang | 7e849b0 | 2019-10-18 19:36:25 -0700 | [diff] [blame] | 908 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 909 | // TODO: add more fields to frontend |
| 910 | return env->NewObject( |
| 911 | env->FindClass("android/media/tv/tuner/Tuner$Frontend"), |
| 912 | gFields.frontendInitID, |
shubang | 4b8c540 | 2019-10-24 17:49:53 -0700 | [diff] [blame] | 913 | mObject, |
shubang | 7e849b0 | 2019-10-18 19:36:25 -0700 | [diff] [blame] | 914 | (jint) jId); |
| 915 | } |
| 916 | |
shubang | 2f9cab3 | 2020-04-10 18:00:56 -0700 | [diff] [blame] | 917 | jint JTuner::closeFrontendById(int id) { |
| 918 | if (mFe != NULL && mFeId == id) { |
| 919 | Result r = mFe->close(); |
| 920 | return (jint) r; |
| 921 | } |
| 922 | return (jint) Result::SUCCESS; |
| 923 | } |
| 924 | |
shubang | 66cc3aa | 2020-04-06 17:10:01 -0700 | [diff] [blame] | 925 | jobject JTuner::getAnalogFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) { |
shubang | 51cc62f | 2020-01-28 18:00:22 -0800 | [diff] [blame] | 926 | jclass clazz = env->FindClass("android/media/tv/tuner/frontend/AnalogFrontendCapabilities"); |
| 927 | jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(II)V"); |
| 928 | |
| 929 | jint typeCap = caps.analogCaps().typeCap; |
| 930 | jint sifStandardCap = caps.analogCaps().sifStandardCap; |
| 931 | return env->NewObject(clazz, capsInit, typeCap, sifStandardCap); |
| 932 | } |
| 933 | |
shubang | 66cc3aa | 2020-04-06 17:10:01 -0700 | [diff] [blame] | 934 | jobject JTuner::getAtsc3FrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) { |
shubang | 51cc62f | 2020-01-28 18:00:22 -0800 | [diff] [blame] | 935 | jclass clazz = env->FindClass("android/media/tv/tuner/frontend/Atsc3FrontendCapabilities"); |
| 936 | jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(IIIIII)V"); |
| 937 | |
| 938 | jint bandwidthCap = caps.atsc3Caps().bandwidthCap; |
| 939 | jint modulationCap = caps.atsc3Caps().modulationCap; |
| 940 | jint timeInterleaveModeCap = caps.atsc3Caps().timeInterleaveModeCap; |
| 941 | jint codeRateCap = caps.atsc3Caps().codeRateCap; |
| 942 | jint fecCap = caps.atsc3Caps().fecCap; |
| 943 | jint demodOutputFormatCap = caps.atsc3Caps().demodOutputFormatCap; |
| 944 | |
| 945 | return env->NewObject(clazz, capsInit, bandwidthCap, modulationCap, timeInterleaveModeCap, |
| 946 | codeRateCap, fecCap, demodOutputFormatCap); |
| 947 | } |
| 948 | |
shubang | 66cc3aa | 2020-04-06 17:10:01 -0700 | [diff] [blame] | 949 | jobject JTuner::getAtscFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) { |
shubang | 51cc62f | 2020-01-28 18:00:22 -0800 | [diff] [blame] | 950 | jclass clazz = env->FindClass("android/media/tv/tuner/frontend/AtscFrontendCapabilities"); |
| 951 | jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(I)V"); |
| 952 | |
| 953 | jint modulationCap = caps.atscCaps().modulationCap; |
| 954 | |
| 955 | return env->NewObject(clazz, capsInit, modulationCap); |
| 956 | } |
| 957 | |
shubang | 66cc3aa | 2020-04-06 17:10:01 -0700 | [diff] [blame] | 958 | jobject JTuner::getDvbcFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) { |
shubang | 51cc62f | 2020-01-28 18:00:22 -0800 | [diff] [blame] | 959 | jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbcFrontendCapabilities"); |
| 960 | jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(III)V"); |
| 961 | |
| 962 | jint modulationCap = caps.dvbcCaps().modulationCap; |
| 963 | jint fecCap = caps.dvbcCaps().fecCap; |
| 964 | jint annexCap = caps.dvbcCaps().annexCap; |
| 965 | |
| 966 | return env->NewObject(clazz, capsInit, modulationCap, fecCap, annexCap); |
| 967 | } |
| 968 | |
shubang | 66cc3aa | 2020-04-06 17:10:01 -0700 | [diff] [blame] | 969 | jobject JTuner::getDvbsFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) { |
shubang | 51cc62f | 2020-01-28 18:00:22 -0800 | [diff] [blame] | 970 | jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbsFrontendCapabilities"); |
| 971 | jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(IJI)V"); |
| 972 | |
| 973 | jint modulationCap = caps.dvbsCaps().modulationCap; |
| 974 | jlong innerfecCap = caps.dvbsCaps().innerfecCap; |
| 975 | jint standard = caps.dvbsCaps().standard; |
| 976 | |
| 977 | return env->NewObject(clazz, capsInit, modulationCap, innerfecCap, standard); |
| 978 | } |
| 979 | |
shubang | 66cc3aa | 2020-04-06 17:10:01 -0700 | [diff] [blame] | 980 | jobject JTuner::getDvbtFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) { |
shubang | 51cc62f | 2020-01-28 18:00:22 -0800 | [diff] [blame] | 981 | jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbtFrontendCapabilities"); |
| 982 | jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(IIIIIIZZ)V"); |
| 983 | |
| 984 | jint transmissionModeCap = caps.dvbtCaps().transmissionModeCap; |
| 985 | jint bandwidthCap = caps.dvbtCaps().bandwidthCap; |
| 986 | jint constellationCap = caps.dvbtCaps().constellationCap; |
| 987 | jint coderateCap = caps.dvbtCaps().coderateCap; |
| 988 | jint hierarchyCap = caps.dvbtCaps().hierarchyCap; |
| 989 | jint guardIntervalCap = caps.dvbtCaps().guardIntervalCap; |
| 990 | jboolean isT2Supported = caps.dvbtCaps().isT2Supported; |
| 991 | jboolean isMisoSupported = caps.dvbtCaps().isMisoSupported; |
| 992 | |
| 993 | return env->NewObject(clazz, capsInit, transmissionModeCap, bandwidthCap, constellationCap, |
| 994 | coderateCap, hierarchyCap, guardIntervalCap, isT2Supported, isMisoSupported); |
| 995 | } |
| 996 | |
shubang | 66cc3aa | 2020-04-06 17:10:01 -0700 | [diff] [blame] | 997 | jobject JTuner::getIsdbs3FrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) { |
shubang | 51cc62f | 2020-01-28 18:00:22 -0800 | [diff] [blame] | 998 | jclass clazz = env->FindClass("android/media/tv/tuner/frontend/Isdbs3FrontendCapabilities"); |
| 999 | jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(II)V"); |
| 1000 | |
| 1001 | jint modulationCap = caps.isdbs3Caps().modulationCap; |
| 1002 | jint coderateCap = caps.isdbs3Caps().coderateCap; |
| 1003 | |
| 1004 | return env->NewObject(clazz, capsInit, modulationCap, coderateCap); |
| 1005 | } |
| 1006 | |
shubang | 66cc3aa | 2020-04-06 17:10:01 -0700 | [diff] [blame] | 1007 | jobject JTuner::getIsdbsFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) { |
shubang | 51cc62f | 2020-01-28 18:00:22 -0800 | [diff] [blame] | 1008 | jclass clazz = env->FindClass("android/media/tv/tuner/frontend/IsdbsFrontendCapabilities"); |
| 1009 | jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(II)V"); |
| 1010 | |
| 1011 | jint modulationCap = caps.isdbsCaps().modulationCap; |
| 1012 | jint coderateCap = caps.isdbsCaps().coderateCap; |
| 1013 | |
| 1014 | return env->NewObject(clazz, capsInit, modulationCap, coderateCap); |
| 1015 | } |
| 1016 | |
shubang | 66cc3aa | 2020-04-06 17:10:01 -0700 | [diff] [blame] | 1017 | jobject JTuner::getIsdbtFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) { |
shubang | 51cc62f | 2020-01-28 18:00:22 -0800 | [diff] [blame] | 1018 | jclass clazz = env->FindClass("android/media/tv/tuner/frontend/IsdbtFrontendCapabilities"); |
| 1019 | jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(IIIII)V"); |
| 1020 | |
| 1021 | jint modeCap = caps.isdbtCaps().modeCap; |
| 1022 | jint bandwidthCap = caps.isdbtCaps().bandwidthCap; |
| 1023 | jint modulationCap = caps.isdbtCaps().modulationCap; |
| 1024 | jint coderateCap = caps.isdbtCaps().coderateCap; |
| 1025 | jint guardIntervalCap = caps.isdbtCaps().guardIntervalCap; |
| 1026 | |
| 1027 | return env->NewObject(clazz, capsInit, modeCap, bandwidthCap, modulationCap, coderateCap, |
| 1028 | guardIntervalCap); |
| 1029 | } |
| 1030 | |
| 1031 | jobject JTuner::getFrontendInfo(int id) { |
| 1032 | FrontendInfo feInfo; |
| 1033 | Result res; |
| 1034 | mTuner->getFrontendInfo(id, [&](Result r, const FrontendInfo& info) { |
| 1035 | feInfo = info; |
| 1036 | res = r; |
| 1037 | }); |
| 1038 | if (res != Result::SUCCESS) { |
| 1039 | return NULL; |
| 1040 | } |
| 1041 | |
| 1042 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 1043 | jclass clazz = env->FindClass("android/media/tv/tuner/frontend/FrontendInfo"); |
| 1044 | jmethodID infoInit = env->GetMethodID(clazz, "<init>", |
| 1045 | "(IIIIIIII[ILandroid/media/tv/tuner/frontend/FrontendCapabilities;)V"); |
| 1046 | |
| 1047 | jint type = (jint) feInfo.type; |
| 1048 | jint minFrequency = feInfo.minFrequency; |
| 1049 | jint maxFrequency = feInfo.maxFrequency; |
| 1050 | jint minSymbolRate = feInfo.minSymbolRate; |
| 1051 | jint maxSymbolRate = feInfo.maxSymbolRate; |
| 1052 | jint acquireRange = feInfo.acquireRange; |
| 1053 | jint exclusiveGroupId = feInfo.exclusiveGroupId; |
| 1054 | jintArray statusCaps = env->NewIntArray(feInfo.statusCaps.size()); |
| 1055 | env->SetIntArrayRegion( |
| 1056 | statusCaps, 0, feInfo.statusCaps.size(), |
| 1057 | reinterpret_cast<jint*>(&feInfo.statusCaps[0])); |
| 1058 | FrontendInfo::FrontendCapabilities caps = feInfo.frontendCaps; |
| 1059 | |
| 1060 | jobject jcaps = NULL; |
| 1061 | switch(feInfo.type) { |
| 1062 | case FrontendType::ANALOG: |
shubang | 66cc3aa | 2020-04-06 17:10:01 -0700 | [diff] [blame] | 1063 | if (FrontendInfo::FrontendCapabilities::hidl_discriminator::analogCaps |
| 1064 | == caps.getDiscriminator()) { |
| 1065 | jcaps = getAnalogFrontendCaps(env, caps); |
| 1066 | } |
shubang | 51cc62f | 2020-01-28 18:00:22 -0800 | [diff] [blame] | 1067 | break; |
| 1068 | case FrontendType::ATSC3: |
shubang | 66cc3aa | 2020-04-06 17:10:01 -0700 | [diff] [blame] | 1069 | if (FrontendInfo::FrontendCapabilities::hidl_discriminator::atsc3Caps |
| 1070 | == caps.getDiscriminator()) { |
| 1071 | jcaps = getAtsc3FrontendCaps(env, caps); |
| 1072 | } |
shubang | 51cc62f | 2020-01-28 18:00:22 -0800 | [diff] [blame] | 1073 | break; |
| 1074 | case FrontendType::ATSC: |
shubang | 66cc3aa | 2020-04-06 17:10:01 -0700 | [diff] [blame] | 1075 | if (FrontendInfo::FrontendCapabilities::hidl_discriminator::atscCaps |
| 1076 | == caps.getDiscriminator()) { |
| 1077 | jcaps = getAtscFrontendCaps(env, caps); |
| 1078 | } |
shubang | 51cc62f | 2020-01-28 18:00:22 -0800 | [diff] [blame] | 1079 | break; |
| 1080 | case FrontendType::DVBC: |
shubang | 66cc3aa | 2020-04-06 17:10:01 -0700 | [diff] [blame] | 1081 | if (FrontendInfo::FrontendCapabilities::hidl_discriminator::dvbcCaps |
| 1082 | == caps.getDiscriminator()) { |
| 1083 | jcaps = getDvbcFrontendCaps(env, caps); |
| 1084 | } |
shubang | 51cc62f | 2020-01-28 18:00:22 -0800 | [diff] [blame] | 1085 | break; |
| 1086 | case FrontendType::DVBS: |
shubang | 66cc3aa | 2020-04-06 17:10:01 -0700 | [diff] [blame] | 1087 | if (FrontendInfo::FrontendCapabilities::hidl_discriminator::dvbsCaps |
| 1088 | == caps.getDiscriminator()) { |
| 1089 | jcaps = getDvbsFrontendCaps(env, caps); |
| 1090 | } |
shubang | 51cc62f | 2020-01-28 18:00:22 -0800 | [diff] [blame] | 1091 | break; |
| 1092 | case FrontendType::DVBT: |
shubang | 66cc3aa | 2020-04-06 17:10:01 -0700 | [diff] [blame] | 1093 | if (FrontendInfo::FrontendCapabilities::hidl_discriminator::dvbtCaps |
| 1094 | == caps.getDiscriminator()) { |
| 1095 | jcaps = getDvbtFrontendCaps(env, caps); |
| 1096 | } |
shubang | 51cc62f | 2020-01-28 18:00:22 -0800 | [diff] [blame] | 1097 | break; |
| 1098 | case FrontendType::ISDBS: |
shubang | 66cc3aa | 2020-04-06 17:10:01 -0700 | [diff] [blame] | 1099 | if (FrontendInfo::FrontendCapabilities::hidl_discriminator::isdbsCaps |
| 1100 | == caps.getDiscriminator()) { |
| 1101 | jcaps = getIsdbsFrontendCaps(env, caps); |
| 1102 | } |
shubang | 51cc62f | 2020-01-28 18:00:22 -0800 | [diff] [blame] | 1103 | break; |
| 1104 | case FrontendType::ISDBS3: |
shubang | 66cc3aa | 2020-04-06 17:10:01 -0700 | [diff] [blame] | 1105 | if (FrontendInfo::FrontendCapabilities::hidl_discriminator::isdbs3Caps |
| 1106 | == caps.getDiscriminator()) { |
| 1107 | jcaps = getIsdbs3FrontendCaps(env, caps); |
| 1108 | } |
shubang | 51cc62f | 2020-01-28 18:00:22 -0800 | [diff] [blame] | 1109 | break; |
| 1110 | case FrontendType::ISDBT: |
shubang | 66cc3aa | 2020-04-06 17:10:01 -0700 | [diff] [blame] | 1111 | if (FrontendInfo::FrontendCapabilities::hidl_discriminator::isdbtCaps |
| 1112 | == caps.getDiscriminator()) { |
| 1113 | jcaps = getIsdbtFrontendCaps(env, caps); |
| 1114 | } |
shubang | 51cc62f | 2020-01-28 18:00:22 -0800 | [diff] [blame] | 1115 | break; |
| 1116 | default: |
| 1117 | break; |
| 1118 | } |
| 1119 | |
| 1120 | return env->NewObject( |
| 1121 | clazz, infoInit, (jint) id, type, minFrequency, maxFrequency, minSymbolRate, |
| 1122 | maxSymbolRate, acquireRange, exclusiveGroupId, statusCaps, jcaps); |
| 1123 | } |
| 1124 | |
shubang | 0dc8394 | 2020-04-02 17:19:31 -0700 | [diff] [blame] | 1125 | jintArray JTuner::getLnbIds() { |
shubang | 760f031 | 2019-11-12 17:11:28 -0800 | [diff] [blame] | 1126 | ALOGD("JTuner::getLnbIds()"); |
shubang | 0dc8394 | 2020-04-02 17:19:31 -0700 | [diff] [blame] | 1127 | Result res; |
| 1128 | hidl_vec<LnbId> lnbIds; |
| 1129 | mTuner->getLnbIds([&](Result r, const hidl_vec<LnbId>& ids) { |
| 1130 | lnbIds = ids; |
| 1131 | res = r; |
shubang | 760f031 | 2019-11-12 17:11:28 -0800 | [diff] [blame] | 1132 | }); |
shubang | b3bfffe | 2020-03-26 17:44:31 -0700 | [diff] [blame^] | 1133 | if (res != Result::SUCCESS || lnbIds.size() == 0) { |
shubang | 760f031 | 2019-11-12 17:11:28 -0800 | [diff] [blame] | 1134 | ALOGW("Lnb isn't available"); |
| 1135 | return NULL; |
| 1136 | } |
| 1137 | |
shubang | 0dc8394 | 2020-04-02 17:19:31 -0700 | [diff] [blame] | 1138 | mLnbIds = lnbIds; |
shubang | 760f031 | 2019-11-12 17:11:28 -0800 | [diff] [blame] | 1139 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
shubang | 760f031 | 2019-11-12 17:11:28 -0800 | [diff] [blame] | 1140 | |
shubang | 0dc8394 | 2020-04-02 17:19:31 -0700 | [diff] [blame] | 1141 | jintArray ids = env->NewIntArray(mLnbIds.size()); |
| 1142 | env->SetIntArrayRegion(ids, 0, mLnbIds.size(), reinterpret_cast<jint*>(&mLnbIds[0])); |
shubang | 760f031 | 2019-11-12 17:11:28 -0800 | [diff] [blame] | 1143 | |
shubang | 0dc8394 | 2020-04-02 17:19:31 -0700 | [diff] [blame] | 1144 | return ids; |
shubang | 760f031 | 2019-11-12 17:11:28 -0800 | [diff] [blame] | 1145 | } |
| 1146 | |
| 1147 | jobject JTuner::openLnbById(int id) { |
shubang | 1c1144e | 2020-03-03 18:00:17 -0800 | [diff] [blame] | 1148 | sp<ILnb> iLnbSp; |
shubang | d295be0 | 2020-03-27 17:08:11 -0700 | [diff] [blame] | 1149 | Result r; |
| 1150 | mTuner->openLnbById(id, [&](Result res, const sp<ILnb>& lnb) { |
| 1151 | r = res; |
shubang | 1c1144e | 2020-03-03 18:00:17 -0800 | [diff] [blame] | 1152 | iLnbSp = lnb; |
shubang | 760f031 | 2019-11-12 17:11:28 -0800 | [diff] [blame] | 1153 | }); |
shubang | d295be0 | 2020-03-27 17:08:11 -0700 | [diff] [blame] | 1154 | if (r != Result::SUCCESS || iLnbSp == nullptr) { |
shubang | 760f031 | 2019-11-12 17:11:28 -0800 | [diff] [blame] | 1155 | ALOGE("Failed to open lnb"); |
| 1156 | return NULL; |
| 1157 | } |
shubang | 1c1144e | 2020-03-03 18:00:17 -0800 | [diff] [blame] | 1158 | mLnb = iLnbSp; |
shubang | 760f031 | 2019-11-12 17:11:28 -0800 | [diff] [blame] | 1159 | |
| 1160 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
shubang | 1c1144e | 2020-03-03 18:00:17 -0800 | [diff] [blame] | 1161 | jobject lnbObj = env->NewObject( |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 1162 | env->FindClass("android/media/tv/tuner/Lnb"), |
shubang | 760f031 | 2019-11-12 17:11:28 -0800 | [diff] [blame] | 1163 | gFields.lnbInitID, |
shubang | 1c1144e | 2020-03-03 18:00:17 -0800 | [diff] [blame] | 1164 | (jint) id); |
| 1165 | |
shubang | d295be0 | 2020-03-27 17:08:11 -0700 | [diff] [blame] | 1166 | sp<LnbCallback> lnbCb = new LnbCallback(lnbObj, id); |
| 1167 | mLnb->setCallback(lnbCb); |
| 1168 | |
shubang | 1c1144e | 2020-03-03 18:00:17 -0800 | [diff] [blame] | 1169 | sp<Lnb> lnbSp = new Lnb(iLnbSp, lnbObj); |
| 1170 | lnbSp->incStrong(lnbObj); |
| 1171 | env->SetLongField(lnbObj, gFields.lnbContext, (jlong) lnbSp.get()); |
| 1172 | |
| 1173 | return lnbObj; |
shubang | 760f031 | 2019-11-12 17:11:28 -0800 | [diff] [blame] | 1174 | } |
| 1175 | |
shubang | 757602f | 2020-03-06 15:23:41 -0800 | [diff] [blame] | 1176 | jobject JTuner::openLnbByName(jstring name) { |
| 1177 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 1178 | std::string lnbName(env->GetStringUTFChars(name, nullptr)); |
| 1179 | sp<ILnb> iLnbSp; |
| 1180 | Result res; |
| 1181 | LnbId id; |
| 1182 | mTuner->openLnbByName(lnbName, [&](Result r, LnbId lnbId, const sp<ILnb>& lnb) { |
| 1183 | res = r; |
| 1184 | iLnbSp = lnb; |
| 1185 | id = lnbId; |
| 1186 | }); |
| 1187 | if (res != Result::SUCCESS || iLnbSp == nullptr) { |
| 1188 | ALOGE("Failed to open lnb"); |
| 1189 | return NULL; |
| 1190 | } |
| 1191 | mLnb = iLnbSp; |
shubang | 757602f | 2020-03-06 15:23:41 -0800 | [diff] [blame] | 1192 | |
| 1193 | jobject lnbObj = env->NewObject( |
| 1194 | env->FindClass("android/media/tv/tuner/Lnb"), |
| 1195 | gFields.lnbInitID, |
| 1196 | id); |
| 1197 | |
shubang | d295be0 | 2020-03-27 17:08:11 -0700 | [diff] [blame] | 1198 | sp<LnbCallback> lnbCb = new LnbCallback(lnbObj, id); |
| 1199 | mLnb->setCallback(lnbCb); |
| 1200 | |
shubang | 757602f | 2020-03-06 15:23:41 -0800 | [diff] [blame] | 1201 | sp<Lnb> lnbSp = new Lnb(iLnbSp, lnbObj); |
| 1202 | lnbSp->incStrong(lnbObj); |
| 1203 | env->SetLongField(lnbObj, gFields.lnbContext, (jlong) lnbSp.get()); |
| 1204 | |
| 1205 | return lnbObj; |
| 1206 | } |
| 1207 | |
shubang | 74bfd48 | 2019-10-29 19:10:22 -0700 | [diff] [blame] | 1208 | int JTuner::tune(const FrontendSettings& settings) { |
| 1209 | if (mFe == NULL) { |
| 1210 | ALOGE("frontend is not initialized"); |
| 1211 | return (int)Result::INVALID_STATE; |
| 1212 | } |
| 1213 | Result result = mFe->tune(settings); |
| 1214 | return (int)result; |
| 1215 | } |
| 1216 | |
shubang | e32fb41 | 2020-01-28 14:53:05 -0800 | [diff] [blame] | 1217 | int JTuner::stopTune() { |
| 1218 | if (mFe == NULL) { |
| 1219 | ALOGE("frontend is not initialized"); |
| 1220 | return (int)Result::INVALID_STATE; |
| 1221 | } |
| 1222 | Result result = mFe->stopTune(); |
| 1223 | return (int)result; |
| 1224 | } |
| 1225 | |
shubang | d5b845f | 2019-12-11 15:29:09 -0800 | [diff] [blame] | 1226 | int JTuner::scan(const FrontendSettings& settings, FrontendScanType scanType) { |
| 1227 | if (mFe == NULL) { |
| 1228 | ALOGE("frontend is not initialized"); |
| 1229 | return (int)Result::INVALID_STATE; |
| 1230 | } |
| 1231 | Result result = mFe->scan(settings, scanType); |
| 1232 | return (int)result; |
| 1233 | } |
| 1234 | |
shubang | e32fb41 | 2020-01-28 14:53:05 -0800 | [diff] [blame] | 1235 | int JTuner::stopScan() { |
| 1236 | if (mFe == NULL) { |
| 1237 | ALOGE("frontend is not initialized"); |
| 1238 | return (int)Result::INVALID_STATE; |
| 1239 | } |
| 1240 | Result result = mFe->stopScan(); |
| 1241 | return (int)result; |
| 1242 | } |
| 1243 | |
| 1244 | int JTuner::setLnb(int id) { |
| 1245 | if (mFe == NULL) { |
| 1246 | ALOGE("frontend is not initialized"); |
| 1247 | return (int)Result::INVALID_STATE; |
| 1248 | } |
| 1249 | Result result = mFe->setLnb(id); |
| 1250 | return (int)result; |
| 1251 | } |
| 1252 | |
| 1253 | int JTuner::setLna(bool enable) { |
| 1254 | if (mFe == NULL) { |
| 1255 | ALOGE("frontend is not initialized"); |
| 1256 | return (int)Result::INVALID_STATE; |
| 1257 | } |
| 1258 | Result result = mFe->setLna(enable); |
| 1259 | return (int)result; |
| 1260 | } |
| 1261 | |
shubang | bee7346 | 2020-02-07 17:48:02 -0800 | [diff] [blame] | 1262 | Result JTuner::openDemux() { |
shubang | 6f473d6 | 2019-11-01 15:42:21 -0700 | [diff] [blame] | 1263 | if (mTuner == nullptr) { |
shubang | bee7346 | 2020-02-07 17:48:02 -0800 | [diff] [blame] | 1264 | return Result::NOT_INITIALIZED; |
shubang | 6f473d6 | 2019-11-01 15:42:21 -0700 | [diff] [blame] | 1265 | } |
| 1266 | if (mDemux != nullptr) { |
shubang | bee7346 | 2020-02-07 17:48:02 -0800 | [diff] [blame] | 1267 | return Result::SUCCESS; |
shubang | 6f473d6 | 2019-11-01 15:42:21 -0700 | [diff] [blame] | 1268 | } |
shubang | bee7346 | 2020-02-07 17:48:02 -0800 | [diff] [blame] | 1269 | Result res; |
shubang | d295be0 | 2020-03-27 17:08:11 -0700 | [diff] [blame] | 1270 | uint32_t id; |
| 1271 | sp<IDemux> demuxSp; |
shubang | bee7346 | 2020-02-07 17:48:02 -0800 | [diff] [blame] | 1272 | mTuner->openDemux([&](Result r, uint32_t demuxId, const sp<IDemux>& demux) { |
shubang | d295be0 | 2020-03-27 17:08:11 -0700 | [diff] [blame] | 1273 | demuxSp = demux; |
| 1274 | id = demuxId; |
shubang | bee7346 | 2020-02-07 17:48:02 -0800 | [diff] [blame] | 1275 | res = r; |
shubang | 6f473d6 | 2019-11-01 15:42:21 -0700 | [diff] [blame] | 1276 | ALOGD("open demux, id = %d", demuxId); |
| 1277 | }); |
shubang | d295be0 | 2020-03-27 17:08:11 -0700 | [diff] [blame] | 1278 | if (res == Result::SUCCESS) { |
| 1279 | mDemux = demuxSp; |
| 1280 | mDemuxId = id; |
| 1281 | if (mFe != NULL) { |
| 1282 | mDemux->setFrontendDataSource(mFeId); |
| 1283 | } |
| 1284 | } |
shubang | bee7346 | 2020-02-07 17:48:02 -0800 | [diff] [blame] | 1285 | return res; |
| 1286 | } |
| 1287 | |
shubang | 2f9cab3 | 2020-04-10 18:00:56 -0700 | [diff] [blame] | 1288 | jint JTuner::close() { |
| 1289 | Result res = Result::SUCCESS; |
| 1290 | if (mFe != NULL) { |
| 1291 | res = mFe->close(); |
| 1292 | if (res != Result::SUCCESS) { |
| 1293 | return (jint) res; |
| 1294 | } |
| 1295 | } |
| 1296 | if (mDemux != NULL) { |
| 1297 | res = mDemux->close(); |
| 1298 | if (res != Result::SUCCESS) { |
| 1299 | return (jint) res; |
| 1300 | } |
| 1301 | } |
| 1302 | return (jint) res; |
| 1303 | } |
| 1304 | |
shubang | bee7346 | 2020-02-07 17:48:02 -0800 | [diff] [blame] | 1305 | jobject JTuner::getAvSyncHwId(sp<Filter> filter) { |
| 1306 | if (mDemux == NULL) { |
| 1307 | return NULL; |
shubang | 6f473d6 | 2019-11-01 15:42:21 -0700 | [diff] [blame] | 1308 | } |
shubang | bee7346 | 2020-02-07 17:48:02 -0800 | [diff] [blame] | 1309 | |
| 1310 | uint32_t avSyncHwId; |
| 1311 | Result res; |
| 1312 | sp<IFilter> iFilterSp = filter->getIFilter(); |
| 1313 | mDemux->getAvSyncHwId(iFilterSp, |
| 1314 | [&](Result r, uint32_t id) { |
| 1315 | res = r; |
| 1316 | avSyncHwId = id; |
| 1317 | }); |
| 1318 | if (res == Result::SUCCESS) { |
| 1319 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 1320 | jclass integerClazz = env->FindClass("java/lang/Integer"); |
| 1321 | jmethodID intInit = env->GetMethodID(integerClazz, "<init>", "(I)V"); |
| 1322 | return env->NewObject(integerClazz, intInit, avSyncHwId); |
| 1323 | } |
| 1324 | return NULL; |
| 1325 | } |
| 1326 | |
| 1327 | jobject JTuner::getAvSyncTime(jint id) { |
| 1328 | if (mDemux == NULL) { |
| 1329 | return NULL; |
| 1330 | } |
| 1331 | uint64_t time; |
| 1332 | Result res; |
| 1333 | mDemux->getAvSyncTime(static_cast<uint32_t>(id), |
| 1334 | [&](Result r, uint64_t ts) { |
| 1335 | res = r; |
| 1336 | time = ts; |
| 1337 | }); |
| 1338 | if (res == Result::SUCCESS) { |
| 1339 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 1340 | jclass longClazz = env->FindClass("java/lang/Long"); |
| 1341 | jmethodID longInit = env->GetMethodID(longClazz, "<init>", "(J)V"); |
| 1342 | return env->NewObject(longClazz, longInit, static_cast<jlong>(time)); |
| 1343 | } |
| 1344 | return NULL; |
| 1345 | } |
| 1346 | |
| 1347 | int JTuner::connectCiCam(jint id) { |
| 1348 | if (mDemux == NULL) { |
| 1349 | Result r = openDemux(); |
| 1350 | if (r != Result::SUCCESS) { |
| 1351 | return (int) r; |
| 1352 | } |
| 1353 | } |
| 1354 | Result r = mDemux->connectCiCam(static_cast<uint32_t>(id)); |
| 1355 | return (int) r; |
| 1356 | } |
| 1357 | |
| 1358 | int JTuner::disconnectCiCam() { |
| 1359 | if (mDemux == NULL) { |
| 1360 | Result r = openDemux(); |
| 1361 | if (r != Result::SUCCESS) { |
| 1362 | return (int) r; |
| 1363 | } |
| 1364 | } |
| 1365 | Result r = mDemux->disconnectCiCam(); |
| 1366 | return (int) r; |
shubang | 6f473d6 | 2019-11-01 15:42:21 -0700 | [diff] [blame] | 1367 | } |
| 1368 | |
shubang | 13f15e0 | 2019-11-04 17:51:02 -0800 | [diff] [blame] | 1369 | jobject JTuner::openDescrambler() { |
| 1370 | ALOGD("JTuner::openDescrambler"); |
shubang | 40454db | 2020-03-30 16:52:29 -0700 | [diff] [blame] | 1371 | if (mTuner == nullptr || mDemux == nullptr) { |
shubang | 13f15e0 | 2019-11-04 17:51:02 -0800 | [diff] [blame] | 1372 | return NULL; |
| 1373 | } |
| 1374 | sp<IDescrambler> descramblerSp; |
shubang | 40454db | 2020-03-30 16:52:29 -0700 | [diff] [blame] | 1375 | Result res; |
| 1376 | mTuner->openDescrambler([&](Result r, const sp<IDescrambler>& descrambler) { |
| 1377 | res = r; |
shubang | 13f15e0 | 2019-11-04 17:51:02 -0800 | [diff] [blame] | 1378 | descramblerSp = descrambler; |
| 1379 | }); |
| 1380 | |
shubang | 40454db | 2020-03-30 16:52:29 -0700 | [diff] [blame] | 1381 | if (res != Result::SUCCESS || descramblerSp == NULL) { |
shubang | 13f15e0 | 2019-11-04 17:51:02 -0800 | [diff] [blame] | 1382 | return NULL; |
| 1383 | } |
| 1384 | |
shubang | 40454db | 2020-03-30 16:52:29 -0700 | [diff] [blame] | 1385 | descramblerSp->setDemuxSource(mDemuxId); |
| 1386 | |
shubang | 13f15e0 | 2019-11-04 17:51:02 -0800 | [diff] [blame] | 1387 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 1388 | jobject descramblerObj = |
| 1389 | env->NewObject( |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 1390 | env->FindClass("android/media/tv/tuner/Descrambler"), |
shubang | 40454db | 2020-03-30 16:52:29 -0700 | [diff] [blame] | 1391 | gFields.descramblerInitID); |
shubang | 13f15e0 | 2019-11-04 17:51:02 -0800 | [diff] [blame] | 1392 | |
| 1393 | descramblerSp->incStrong(descramblerObj); |
| 1394 | env->SetLongField(descramblerObj, gFields.descramblerContext, (jlong)descramblerSp.get()); |
| 1395 | |
| 1396 | return descramblerObj; |
| 1397 | } |
| 1398 | |
shubang | 6f473d6 | 2019-11-01 15:42:21 -0700 | [diff] [blame] | 1399 | jobject JTuner::openFilter(DemuxFilterType type, int bufferSize) { |
| 1400 | if (mDemux == NULL) { |
shubang | bee7346 | 2020-02-07 17:48:02 -0800 | [diff] [blame] | 1401 | if (openDemux() != Result::SUCCESS) { |
shubang | 6f473d6 | 2019-11-01 15:42:21 -0700 | [diff] [blame] | 1402 | return NULL; |
| 1403 | } |
| 1404 | } |
| 1405 | |
shubang | 7648a3c | 2019-11-25 18:16:45 -0800 | [diff] [blame] | 1406 | sp<IFilter> iFilterSp; |
shubang | cdf30de | 2019-11-06 17:28:38 -0800 | [diff] [blame] | 1407 | sp<FilterCallback> callback = new FilterCallback(); |
shubang | 40454db | 2020-03-30 16:52:29 -0700 | [diff] [blame] | 1408 | Result res; |
shubang | cdf30de | 2019-11-06 17:28:38 -0800 | [diff] [blame] | 1409 | mDemux->openFilter(type, bufferSize, callback, |
shubang | 40454db | 2020-03-30 16:52:29 -0700 | [diff] [blame] | 1410 | [&](Result r, const sp<IFilter>& filter) { |
shubang | 7648a3c | 2019-11-25 18:16:45 -0800 | [diff] [blame] | 1411 | iFilterSp = filter; |
shubang | 40454db | 2020-03-30 16:52:29 -0700 | [diff] [blame] | 1412 | res = r; |
shubang | 6f473d6 | 2019-11-01 15:42:21 -0700 | [diff] [blame] | 1413 | }); |
shubang | 40454db | 2020-03-30 16:52:29 -0700 | [diff] [blame] | 1414 | if (res != Result::SUCCESS || iFilterSp == NULL) { |
shubang | 6f473d6 | 2019-11-01 15:42:21 -0700 | [diff] [blame] | 1415 | ALOGD("Failed to open filter, type = %d", type.mainType); |
| 1416 | return NULL; |
| 1417 | } |
| 1418 | int fId; |
shubang | 7648a3c | 2019-11-25 18:16:45 -0800 | [diff] [blame] | 1419 | iFilterSp->getId([&](Result, uint32_t filterId) { |
shubang | 6f473d6 | 2019-11-01 15:42:21 -0700 | [diff] [blame] | 1420 | fId = filterId; |
| 1421 | }); |
shubang | 6f473d6 | 2019-11-01 15:42:21 -0700 | [diff] [blame] | 1422 | |
| 1423 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
shubang | cdf30de | 2019-11-06 17:28:38 -0800 | [diff] [blame] | 1424 | jobject filterObj = |
| 1425 | env->NewObject( |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 1426 | env->FindClass("android/media/tv/tuner/filter/Filter"), |
shubang | cdf30de | 2019-11-06 17:28:38 -0800 | [diff] [blame] | 1427 | gFields.filterInitID, |
shubang | cdf30de | 2019-11-06 17:28:38 -0800 | [diff] [blame] | 1428 | (jint) fId); |
| 1429 | |
shubang | 7648a3c | 2019-11-25 18:16:45 -0800 | [diff] [blame] | 1430 | sp<Filter> filterSp = new Filter(iFilterSp, filterObj); |
shubang | cdf30de | 2019-11-06 17:28:38 -0800 | [diff] [blame] | 1431 | filterSp->incStrong(filterObj); |
| 1432 | env->SetLongField(filterObj, gFields.filterContext, (jlong)filterSp.get()); |
| 1433 | |
| 1434 | callback->setFilter(filterObj); |
| 1435 | |
| 1436 | return filterObj; |
shubang | 6f473d6 | 2019-11-01 15:42:21 -0700 | [diff] [blame] | 1437 | } |
| 1438 | |
shubang | f657da2 | 2020-02-05 16:27:06 -0800 | [diff] [blame] | 1439 | jobject JTuner::openTimeFilter() { |
| 1440 | if (mDemux == NULL) { |
shubang | bee7346 | 2020-02-07 17:48:02 -0800 | [diff] [blame] | 1441 | if (openDemux() != Result::SUCCESS) { |
shubang | f657da2 | 2020-02-05 16:27:06 -0800 | [diff] [blame] | 1442 | return NULL; |
| 1443 | } |
| 1444 | } |
| 1445 | sp<ITimeFilter> iTimeFilterSp; |
| 1446 | Result res; |
| 1447 | mDemux->openTimeFilter( |
| 1448 | [&](Result r, const sp<ITimeFilter>& filter) { |
| 1449 | iTimeFilterSp = filter; |
| 1450 | res = r; |
| 1451 | }); |
| 1452 | |
| 1453 | if (res != Result::SUCCESS || iTimeFilterSp == NULL) { |
| 1454 | return NULL; |
| 1455 | } |
| 1456 | |
| 1457 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 1458 | jobject timeFilterObj = |
| 1459 | env->NewObject( |
| 1460 | env->FindClass("android/media/tv/tuner/filter/TimeFilter"), |
| 1461 | gFields.timeFilterInitID); |
| 1462 | sp<TimeFilter> timeFilterSp = new TimeFilter(iTimeFilterSp, timeFilterObj); |
| 1463 | timeFilterSp->incStrong(timeFilterObj); |
| 1464 | env->SetLongField(timeFilterObj, gFields.timeFilterContext, (jlong)timeFilterSp.get()); |
| 1465 | |
| 1466 | return timeFilterObj; |
| 1467 | } |
| 1468 | |
shubang | 5637a66 | 2020-02-27 18:06:21 -0800 | [diff] [blame] | 1469 | jobject JTuner::openDvr(DvrType type, jlong bufferSize) { |
shubang | 4a0eddf | 2019-11-08 17:10:18 -0800 | [diff] [blame] | 1470 | ALOGD("JTuner::openDvr"); |
| 1471 | if (mDemux == NULL) { |
shubang | bee7346 | 2020-02-07 17:48:02 -0800 | [diff] [blame] | 1472 | if (openDemux() != Result::SUCCESS) { |
shubang | 4a0eddf | 2019-11-08 17:10:18 -0800 | [diff] [blame] | 1473 | return NULL; |
| 1474 | } |
| 1475 | } |
shubang | 9e700ff | 2019-12-04 16:26:51 -0800 | [diff] [blame] | 1476 | sp<IDvr> iDvrSp; |
shubang | 4a0eddf | 2019-11-08 17:10:18 -0800 | [diff] [blame] | 1477 | sp<DvrCallback> callback = new DvrCallback(); |
shubang | 5637a66 | 2020-02-27 18:06:21 -0800 | [diff] [blame] | 1478 | Result res; |
| 1479 | mDemux->openDvr(type, (uint32_t) bufferSize, callback, |
| 1480 | [&](Result r, const sp<IDvr>& dvr) { |
| 1481 | res = r; |
shubang | 9e700ff | 2019-12-04 16:26:51 -0800 | [diff] [blame] | 1482 | iDvrSp = dvr; |
shubang | 4a0eddf | 2019-11-08 17:10:18 -0800 | [diff] [blame] | 1483 | }); |
| 1484 | |
shubang | 5637a66 | 2020-02-27 18:06:21 -0800 | [diff] [blame] | 1485 | if (res != Result::SUCCESS || iDvrSp == NULL) { |
shubang | 4a0eddf | 2019-11-08 17:10:18 -0800 | [diff] [blame] | 1486 | return NULL; |
| 1487 | } |
| 1488 | |
| 1489 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
shubang | 5637a66 | 2020-02-27 18:06:21 -0800 | [diff] [blame] | 1490 | jobject dvrObj; |
| 1491 | if (type == DvrType::RECORD) { |
| 1492 | dvrObj = |
| 1493 | env->NewObject( |
| 1494 | env->FindClass("android/media/tv/tuner/dvr/DvrRecorder"), |
| 1495 | gFields.dvrRecorderInitID, |
| 1496 | mObject); |
| 1497 | sp<Dvr> dvrSp = new Dvr(iDvrSp, dvrObj); |
| 1498 | dvrSp->incStrong(dvrObj); |
| 1499 | env->SetLongField(dvrObj, gFields.dvrRecorderContext, (jlong)dvrSp.get()); |
| 1500 | } else { |
| 1501 | dvrObj = |
| 1502 | env->NewObject( |
| 1503 | env->FindClass("android/media/tv/tuner/dvr/DvrPlayback"), |
| 1504 | gFields.dvrPlaybackInitID, |
| 1505 | mObject); |
| 1506 | sp<Dvr> dvrSp = new Dvr(iDvrSp, dvrObj); |
| 1507 | dvrSp->incStrong(dvrObj); |
| 1508 | env->SetLongField(dvrObj, gFields.dvrPlaybackContext, (jlong)dvrSp.get()); |
| 1509 | } |
shubang | 4a0eddf | 2019-11-08 17:10:18 -0800 | [diff] [blame] | 1510 | |
| 1511 | callback->setDvr(dvrObj); |
| 1512 | |
| 1513 | return dvrObj; |
| 1514 | } |
| 1515 | |
shubang | c4b4570 | 2020-03-23 18:48:12 -0700 | [diff] [blame] | 1516 | jobject JTuner::getDemuxCaps() { |
| 1517 | DemuxCapabilities caps; |
| 1518 | Result res; |
| 1519 | mTuner->getDemuxCaps([&](Result r, const DemuxCapabilities& demuxCaps) { |
| 1520 | caps = demuxCaps; |
| 1521 | res = r; |
| 1522 | }); |
| 1523 | if (res != Result::SUCCESS) { |
| 1524 | return NULL; |
| 1525 | } |
| 1526 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 1527 | jclass clazz = env->FindClass("android/media/tv/tuner/DemuxCapabilities"); |
| 1528 | jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(IIIIIIIIIJI[IZ)V"); |
| 1529 | |
| 1530 | jint numDemux = caps.numDemux; |
| 1531 | jint numRecord = caps.numRecord; |
| 1532 | jint numPlayback = caps.numPlayback; |
| 1533 | jint numTsFilter = caps.numTsFilter; |
| 1534 | jint numSectionFilter = caps.numSectionFilter; |
| 1535 | jint numAudioFilter = caps.numAudioFilter; |
| 1536 | jint numVideoFilter = caps.numVideoFilter; |
| 1537 | jint numPesFilter = caps.numPesFilter; |
| 1538 | jint numPcrFilter = caps.numPcrFilter; |
| 1539 | jlong numBytesInSectionFilter = caps.numBytesInSectionFilter; |
| 1540 | jint filterCaps = static_cast<jint>(caps.filterCaps); |
| 1541 | jboolean bTimeFilter = caps.bTimeFilter; |
| 1542 | |
| 1543 | jintArray linkCaps = env->NewIntArray(caps.linkCaps.size()); |
| 1544 | env->SetIntArrayRegion( |
| 1545 | linkCaps, 0, caps.linkCaps.size(), reinterpret_cast<jint*>(&caps.linkCaps[0])); |
| 1546 | |
| 1547 | return env->NewObject(clazz, capsInit, numDemux, numRecord, numPlayback, numTsFilter, |
| 1548 | numSectionFilter, numAudioFilter, numVideoFilter, numPesFilter, numPcrFilter, |
| 1549 | numBytesInSectionFilter, filterCaps, linkCaps, bTimeFilter); |
| 1550 | } |
| 1551 | |
shubang | b83f823 | 2020-03-24 18:04:35 -0700 | [diff] [blame] | 1552 | jobject JTuner::getFrontendStatus(jintArray types) { |
| 1553 | if (mFe == NULL) { |
| 1554 | return NULL; |
| 1555 | } |
| 1556 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 1557 | jsize size = env->GetArrayLength(types); |
| 1558 | std::vector<FrontendStatusType> v(size); |
| 1559 | env->GetIntArrayRegion(types, 0, size, reinterpret_cast<jint*>(&v[0])); |
| 1560 | |
| 1561 | Result res; |
| 1562 | hidl_vec<FrontendStatus> status; |
| 1563 | mFe->getStatus(v, |
| 1564 | [&](Result r, const hidl_vec<FrontendStatus>& s) { |
| 1565 | res = r; |
| 1566 | status = s; |
| 1567 | }); |
| 1568 | if (res != Result::SUCCESS) { |
| 1569 | return NULL; |
| 1570 | } |
| 1571 | |
| 1572 | jclass clazz = env->FindClass("android/media/tv/tuner/frontend/FrontendStatus"); |
| 1573 | jmethodID init = env->GetMethodID(clazz, "<init>", "()V"); |
| 1574 | jobject statusObj = env->NewObject(clazz, init); |
| 1575 | |
| 1576 | jclass intClazz = env->FindClass("java/lang/Integer"); |
| 1577 | jmethodID initInt = env->GetMethodID(intClazz, "<init>", "(I)V"); |
| 1578 | jclass booleanClazz = env->FindClass("java/lang/Boolean"); |
| 1579 | jmethodID initBoolean = env->GetMethodID(booleanClazz, "<init>", "(Z)V"); |
| 1580 | |
| 1581 | for (auto s : status) { |
| 1582 | switch(s.getDiscriminator()) { |
| 1583 | case FrontendStatus::hidl_discriminator::isDemodLocked: { |
| 1584 | jfieldID field = env->GetFieldID(clazz, "mIsDemodLocked", "Ljava/lang/Boolean;"); |
| 1585 | jobject newBooleanObj = env->NewObject( |
| 1586 | booleanClazz, initBoolean, static_cast<jboolean>(s.isDemodLocked())); |
| 1587 | env->SetObjectField(statusObj, field, newBooleanObj); |
| 1588 | break; |
| 1589 | } |
| 1590 | case FrontendStatus::hidl_discriminator::snr: { |
| 1591 | jfieldID field = env->GetFieldID(clazz, "mSnr", "Ljava/lang/Integer;"); |
| 1592 | jobject newIntegerObj = env->NewObject( |
| 1593 | intClazz, initInt, static_cast<jint>(s.snr())); |
| 1594 | env->SetObjectField(statusObj, field, newIntegerObj); |
| 1595 | break; |
| 1596 | } |
| 1597 | case FrontendStatus::hidl_discriminator::ber: { |
| 1598 | jfieldID field = env->GetFieldID(clazz, "mBer", "Ljava/lang/Integer;"); |
| 1599 | jobject newIntegerObj = env->NewObject( |
| 1600 | intClazz, initInt, static_cast<jint>(s.ber())); |
| 1601 | env->SetObjectField(statusObj, field, newIntegerObj); |
| 1602 | break; |
| 1603 | } |
| 1604 | case FrontendStatus::hidl_discriminator::per: { |
| 1605 | jfieldID field = env->GetFieldID(clazz, "mPer", "Ljava/lang/Integer;"); |
| 1606 | jobject newIntegerObj = env->NewObject( |
| 1607 | intClazz, initInt, static_cast<jint>(s.per())); |
| 1608 | env->SetObjectField(statusObj, field, newIntegerObj); |
| 1609 | break; |
| 1610 | } |
| 1611 | case FrontendStatus::hidl_discriminator::preBer: { |
| 1612 | jfieldID field = env->GetFieldID(clazz, "mPerBer", "Ljava/lang/Integer;"); |
| 1613 | jobject newIntegerObj = env->NewObject( |
| 1614 | intClazz, initInt, static_cast<jint>(s.preBer())); |
| 1615 | env->SetObjectField(statusObj, field, newIntegerObj); |
| 1616 | break; |
| 1617 | } |
| 1618 | case FrontendStatus::hidl_discriminator::signalQuality: { |
| 1619 | jfieldID field = env->GetFieldID(clazz, "mSignalQuality", "Ljava/lang/Integer;"); |
| 1620 | jobject newIntegerObj = env->NewObject( |
| 1621 | intClazz, initInt, static_cast<jint>(s.signalQuality())); |
| 1622 | env->SetObjectField(statusObj, field, newIntegerObj); |
| 1623 | break; |
| 1624 | } |
| 1625 | case FrontendStatus::hidl_discriminator::signalStrength: { |
| 1626 | jfieldID field = env->GetFieldID(clazz, "mSignalStrength", "Ljava/lang/Integer;"); |
| 1627 | jobject newIntegerObj = env->NewObject( |
| 1628 | intClazz, initInt, static_cast<jint>(s.signalStrength())); |
| 1629 | env->SetObjectField(statusObj, field, newIntegerObj); |
| 1630 | break; |
| 1631 | } |
| 1632 | case FrontendStatus::hidl_discriminator::symbolRate: { |
| 1633 | jfieldID field = env->GetFieldID(clazz, "mSymbolRate", "Ljava/lang/Integer;"); |
| 1634 | jobject newIntegerObj = env->NewObject( |
| 1635 | intClazz, initInt, static_cast<jint>(s.symbolRate())); |
| 1636 | env->SetObjectField(statusObj, field, newIntegerObj); |
| 1637 | break; |
| 1638 | } |
| 1639 | case FrontendStatus::hidl_discriminator::innerFec: { |
| 1640 | jfieldID field = env->GetFieldID(clazz, "mInnerFec", "Ljava/lang/Long;"); |
| 1641 | jclass longClazz = env->FindClass("java/lang/Long"); |
| 1642 | jmethodID initLong = env->GetMethodID(longClazz, "<init>", "(J)V"); |
| 1643 | jobject newLongObj = env->NewObject( |
| 1644 | longClazz, initLong, static_cast<jlong>(s.innerFec())); |
| 1645 | env->SetObjectField(statusObj, field, newLongObj); |
| 1646 | break; |
| 1647 | } |
| 1648 | case FrontendStatus::hidl_discriminator::modulation: { |
| 1649 | jfieldID field = env->GetFieldID(clazz, "mModulation", "Ljava/lang/Integer;"); |
| 1650 | FrontendModulationStatus modulation = s.modulation(); |
| 1651 | jint intModulation; |
| 1652 | bool valid = true; |
| 1653 | switch(modulation.getDiscriminator()) { |
| 1654 | case FrontendModulationStatus::hidl_discriminator::dvbc: { |
| 1655 | intModulation = static_cast<jint>(modulation.dvbc()); |
| 1656 | break; |
| 1657 | } |
| 1658 | case FrontendModulationStatus::hidl_discriminator::dvbs: { |
| 1659 | intModulation = static_cast<jint>(modulation.dvbs()); |
| 1660 | break; |
| 1661 | } |
| 1662 | case FrontendModulationStatus::hidl_discriminator::isdbs: { |
| 1663 | intModulation = static_cast<jint>(modulation.isdbs()); |
| 1664 | break; |
| 1665 | } |
| 1666 | case FrontendModulationStatus::hidl_discriminator::isdbs3: { |
| 1667 | intModulation = static_cast<jint>(modulation.isdbs3()); |
| 1668 | break; |
| 1669 | } |
| 1670 | case FrontendModulationStatus::hidl_discriminator::isdbt: { |
| 1671 | intModulation = static_cast<jint>(modulation.isdbt()); |
| 1672 | break; |
| 1673 | } |
| 1674 | default: { |
| 1675 | valid = false; |
| 1676 | break; |
| 1677 | } |
| 1678 | } |
| 1679 | if (valid) { |
| 1680 | jobject newIntegerObj = env->NewObject(intClazz, initInt, intModulation); |
| 1681 | env->SetObjectField(statusObj, field, newIntegerObj); |
| 1682 | } |
| 1683 | break; |
| 1684 | } |
| 1685 | case FrontendStatus::hidl_discriminator::inversion: { |
| 1686 | jfieldID field = env->GetFieldID(clazz, "mInversion", "Ljava/lang/Integer;"); |
| 1687 | jobject newIntegerObj = env->NewObject( |
| 1688 | intClazz, initInt, static_cast<jint>(s.inversion())); |
| 1689 | env->SetObjectField(statusObj, field, newIntegerObj); |
| 1690 | break; |
| 1691 | } |
| 1692 | case FrontendStatus::hidl_discriminator::lnbVoltage: { |
| 1693 | jfieldID field = env->GetFieldID(clazz, "mLnbVoltage", "Ljava/lang/Integer;"); |
| 1694 | jobject newIntegerObj = env->NewObject( |
| 1695 | intClazz, initInt, static_cast<jint>(s.lnbVoltage())); |
| 1696 | env->SetObjectField(statusObj, field, newIntegerObj); |
| 1697 | break; |
| 1698 | } |
| 1699 | case FrontendStatus::hidl_discriminator::plpId: { |
| 1700 | jfieldID field = env->GetFieldID(clazz, "mPlpId", "Ljava/lang/Integer;"); |
| 1701 | jobject newIntegerObj = env->NewObject( |
| 1702 | intClazz, initInt, static_cast<jint>(s.plpId())); |
| 1703 | env->SetObjectField(statusObj, field, newIntegerObj); |
| 1704 | break; |
| 1705 | } |
| 1706 | case FrontendStatus::hidl_discriminator::isEWBS: { |
| 1707 | jfieldID field = env->GetFieldID(clazz, "mIsEwbs", "Ljava/lang/Boolean;"); |
| 1708 | jobject newBooleanObj = env->NewObject( |
| 1709 | booleanClazz, initBoolean, static_cast<jboolean>(s.isEWBS())); |
| 1710 | env->SetObjectField(statusObj, field, newBooleanObj); |
| 1711 | break; |
| 1712 | } |
| 1713 | case FrontendStatus::hidl_discriminator::agc: { |
| 1714 | jfieldID field = env->GetFieldID(clazz, "mAgc", "Ljava/lang/Integer;"); |
| 1715 | jobject newIntegerObj = env->NewObject( |
| 1716 | intClazz, initInt, static_cast<jint>(s.agc())); |
| 1717 | env->SetObjectField(statusObj, field, newIntegerObj); |
| 1718 | break; |
| 1719 | } |
| 1720 | case FrontendStatus::hidl_discriminator::isLnaOn: { |
| 1721 | jfieldID field = env->GetFieldID(clazz, "mIsLnaOn", "Ljava/lang/Boolean;"); |
| 1722 | jobject newBooleanObj = env->NewObject( |
| 1723 | booleanClazz, initBoolean, static_cast<jboolean>(s.isLnaOn())); |
| 1724 | env->SetObjectField(statusObj, field, newBooleanObj); |
| 1725 | break; |
| 1726 | } |
| 1727 | case FrontendStatus::hidl_discriminator::isLayerError: { |
| 1728 | jfieldID field = env->GetFieldID(clazz, "mIsLayerErrors", "[Z"); |
| 1729 | hidl_vec<bool> layerErr = s.isLayerError(); |
| 1730 | |
| 1731 | jbooleanArray valObj = env->NewBooleanArray(layerErr.size()); |
| 1732 | |
| 1733 | for (size_t i = 0; i < layerErr.size(); i++) { |
| 1734 | jboolean x = layerErr[i]; |
| 1735 | env->SetBooleanArrayRegion(valObj, i, 1, &x); |
| 1736 | } |
| 1737 | env->SetObjectField(statusObj, field, valObj); |
| 1738 | break; |
| 1739 | } |
| 1740 | case FrontendStatus::hidl_discriminator::mer: { |
| 1741 | jfieldID field = env->GetFieldID(clazz, "mMer", "Ljava/lang/Integer;"); |
| 1742 | jobject newIntegerObj = env->NewObject( |
| 1743 | intClazz, initInt, static_cast<jint>(s.mer())); |
| 1744 | env->SetObjectField(statusObj, field, newIntegerObj); |
| 1745 | break; |
| 1746 | } |
| 1747 | case FrontendStatus::hidl_discriminator::freqOffset: { |
| 1748 | jfieldID field = env->GetFieldID(clazz, "mFreqOffset", "Ljava/lang/Integer;"); |
| 1749 | jobject newIntegerObj = env->NewObject( |
| 1750 | intClazz, initInt, static_cast<jint>(s.freqOffset())); |
| 1751 | env->SetObjectField(statusObj, field, newIntegerObj); |
| 1752 | break; |
| 1753 | } |
| 1754 | case FrontendStatus::hidl_discriminator::hierarchy: { |
| 1755 | jfieldID field = env->GetFieldID(clazz, "mHierarchy", "Ljava/lang/Integer;"); |
| 1756 | jobject newIntegerObj = env->NewObject( |
| 1757 | intClazz, initInt, static_cast<jint>(s.hierarchy())); |
| 1758 | env->SetObjectField(statusObj, field, newIntegerObj); |
| 1759 | break; |
| 1760 | } |
| 1761 | case FrontendStatus::hidl_discriminator::isRfLocked: { |
| 1762 | jfieldID field = env->GetFieldID(clazz, "mIsRfLocked", "Ljava/lang/Boolean;"); |
| 1763 | jobject newBooleanObj = env->NewObject( |
| 1764 | booleanClazz, initBoolean, static_cast<jboolean>(s.isRfLocked())); |
| 1765 | env->SetObjectField(statusObj, field, newBooleanObj); |
| 1766 | break; |
| 1767 | } |
| 1768 | case FrontendStatus::hidl_discriminator::plpInfo: { |
| 1769 | jfieldID field = env->GetFieldID(clazz, "mPlpInfo", |
| 1770 | "[Landroid/media/tv/tuner/frontend/FrontendStatus$Atsc3PlpTuningInfo;"); |
| 1771 | jclass plpClazz = env->FindClass( |
| 1772 | "android/media/tv/tuner/frontend/FrontendStatus$Atsc3PlpTuningInfo"); |
| 1773 | jmethodID initPlp = env->GetMethodID(plpClazz, "<init>", "(IZI)V"); |
| 1774 | |
| 1775 | hidl_vec<FrontendStatusAtsc3PlpInfo> plpInfos = s.plpInfo(); |
| 1776 | |
| 1777 | jobjectArray valObj = env->NewObjectArray(plpInfos.size(), plpClazz, NULL); |
| 1778 | for (int i = 0; i < plpInfos.size(); i++) { |
| 1779 | auto info = plpInfos[i]; |
| 1780 | jint plpId = (jint) info.plpId; |
| 1781 | jboolean isLocked = (jboolean) info.isLocked; |
| 1782 | jint uec = (jint) info.uec; |
| 1783 | |
| 1784 | jobject plpObj = env->NewObject(plpClazz, initPlp, plpId, isLocked, uec); |
| 1785 | env->SetObjectArrayElement(valObj, i, plpObj); |
| 1786 | } |
| 1787 | |
| 1788 | env->SetObjectField(statusObj, field, valObj); |
| 1789 | break; |
| 1790 | } |
| 1791 | default: { |
| 1792 | break; |
| 1793 | } |
| 1794 | } |
| 1795 | } |
| 1796 | |
| 1797 | return statusObj; |
| 1798 | } |
| 1799 | |
shubang | b3bfffe | 2020-03-26 17:44:31 -0700 | [diff] [blame^] | 1800 | jint JTuner::closeFrontend() { |
| 1801 | Result r = Result::SUCCESS; |
| 1802 | if (mFe != NULL) { |
| 1803 | r = mFe->close(); |
| 1804 | } |
| 1805 | return (jint) r; |
| 1806 | } |
| 1807 | |
| 1808 | jint JTuner::closeDemux() { |
| 1809 | Result r = Result::SUCCESS; |
| 1810 | if (mDemux != NULL) { |
| 1811 | r = mDemux->close(); |
| 1812 | } |
| 1813 | return (jint) r; |
| 1814 | } |
| 1815 | |
shubang | 8ab43b1 | 2019-10-18 15:55:55 -0700 | [diff] [blame] | 1816 | } // namespace android |
| 1817 | |
| 1818 | //////////////////////////////////////////////////////////////////////////////// |
| 1819 | |
| 1820 | using namespace android; |
| 1821 | |
| 1822 | static sp<JTuner> setTuner(JNIEnv *env, jobject thiz, const sp<JTuner> &tuner) { |
shubang | 13f15e0 | 2019-11-04 17:51:02 -0800 | [diff] [blame] | 1823 | sp<JTuner> old = (JTuner *)env->GetLongField(thiz, gFields.tunerContext); |
shubang | 8ab43b1 | 2019-10-18 15:55:55 -0700 | [diff] [blame] | 1824 | |
| 1825 | if (tuner != NULL) { |
| 1826 | tuner->incStrong(thiz); |
| 1827 | } |
| 1828 | if (old != NULL) { |
| 1829 | old->decStrong(thiz); |
| 1830 | } |
shubang | 13f15e0 | 2019-11-04 17:51:02 -0800 | [diff] [blame] | 1831 | env->SetLongField(thiz, gFields.tunerContext, (jlong)tuner.get()); |
shubang | 8ab43b1 | 2019-10-18 15:55:55 -0700 | [diff] [blame] | 1832 | |
| 1833 | return old; |
| 1834 | } |
| 1835 | |
| 1836 | static sp<JTuner> getTuner(JNIEnv *env, jobject thiz) { |
shubang | 13f15e0 | 2019-11-04 17:51:02 -0800 | [diff] [blame] | 1837 | return (JTuner *)env->GetLongField(thiz, gFields.tunerContext); |
| 1838 | } |
| 1839 | |
| 1840 | static sp<IDescrambler> getDescrambler(JNIEnv *env, jobject descrambler) { |
| 1841 | return (IDescrambler *)env->GetLongField(descrambler, gFields.descramblerContext); |
| 1842 | } |
| 1843 | |
shubang | c18cc10 | 2020-03-12 16:28:45 -0700 | [diff] [blame] | 1844 | static uint32_t getResourceIdFromHandle(jint handle) { |
| 1845 | return (handle & 0x00ff0000) >> 16; |
| 1846 | } |
| 1847 | |
shubang | 13f15e0 | 2019-11-04 17:51:02 -0800 | [diff] [blame] | 1848 | static DemuxPid getDemuxPid(int pidType, int pid) { |
| 1849 | DemuxPid demuxPid; |
| 1850 | if ((int)pidType == 1) { |
| 1851 | demuxPid.tPid(static_cast<DemuxTpid>(pid)); |
| 1852 | } else if ((int)pidType == 2) { |
| 1853 | demuxPid.mmtpPid(static_cast<DemuxMmtpPid>(pid)); |
| 1854 | } |
| 1855 | return demuxPid; |
shubang | 8ab43b1 | 2019-10-18 15:55:55 -0700 | [diff] [blame] | 1856 | } |
| 1857 | |
shubang | deb067c | 2020-01-27 13:21:55 -0800 | [diff] [blame] | 1858 | static uint32_t getFrontendSettingsFreq(JNIEnv *env, const jobject& settings) { |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 1859 | jclass clazz = env->FindClass("android/media/tv/tuner/frontend/FrontendSettings"); |
shubang | 964e613 | 2019-11-26 15:05:22 -0800 | [diff] [blame] | 1860 | jfieldID freqField = env->GetFieldID(clazz, "mFrequency", "I"); |
shubang | deb067c | 2020-01-27 13:21:55 -0800 | [diff] [blame] | 1861 | uint32_t freq = static_cast<uint32_t>(env->GetIntField(settings, freqField)); |
| 1862 | return freq; |
| 1863 | } |
shubang | 74bfd48 | 2019-10-29 19:10:22 -0700 | [diff] [blame] | 1864 | |
shubang | deb067c | 2020-01-27 13:21:55 -0800 | [diff] [blame] | 1865 | static FrontendSettings getAnalogFrontendSettings(JNIEnv *env, const jobject& settings) { |
| 1866 | FrontendSettings frontendSettings; |
| 1867 | uint32_t freq = getFrontendSettingsFreq(env, settings); |
| 1868 | jclass clazz = env->FindClass("android/media/tv/tuner/frontend/AnalogFrontendSettings"); |
| 1869 | FrontendAnalogType analogType = |
| 1870 | static_cast<FrontendAnalogType>( |
| 1871 | env->GetIntField(settings, env->GetFieldID(clazz, "mSignalType", "I"))); |
| 1872 | FrontendAnalogSifStandard sifStandard = |
| 1873 | static_cast<FrontendAnalogSifStandard>( |
| 1874 | env->GetIntField(settings, env->GetFieldID(clazz, "mSifStandard", "I"))); |
| 1875 | FrontendAnalogSettings frontendAnalogSettings { |
| 1876 | .frequency = freq, |
| 1877 | .type = analogType, |
| 1878 | .sifStandard = sifStandard, |
| 1879 | }; |
| 1880 | frontendSettings.analog(frontendAnalogSettings); |
shubang | 74bfd48 | 2019-10-29 19:10:22 -0700 | [diff] [blame] | 1881 | return frontendSettings; |
| 1882 | } |
| 1883 | |
shubang | deb067c | 2020-01-27 13:21:55 -0800 | [diff] [blame] | 1884 | static hidl_vec<FrontendAtsc3PlpSettings> getAtsc3PlpSettings( |
| 1885 | JNIEnv *env, const jobject& settings) { |
| 1886 | jclass clazz = env->FindClass("android/media/tv/tuner/frontend/Atsc3FrontendSettings"); |
| 1887 | jobjectArray plpSettings = |
| 1888 | reinterpret_cast<jobjectArray>( |
| 1889 | env->GetObjectField(settings, |
| 1890 | env->GetFieldID( |
| 1891 | clazz, |
| 1892 | "mPlpSettings", |
| 1893 | "[Landroid/media/tv/tuner/frontend/Atsc3PlpSettings;"))); |
| 1894 | int len = env->GetArrayLength(plpSettings); |
| 1895 | |
| 1896 | jclass plpClazz = env->FindClass("android/media/tv/tuner/frontend/Atsc3PlpSettings"); |
| 1897 | hidl_vec<FrontendAtsc3PlpSettings> plps = hidl_vec<FrontendAtsc3PlpSettings>(len); |
| 1898 | // parse PLP settings |
| 1899 | for (int i = 0; i < len; i++) { |
| 1900 | jobject plp = env->GetObjectArrayElement(plpSettings, i); |
| 1901 | uint8_t plpId = |
| 1902 | static_cast<uint8_t>( |
| 1903 | env->GetIntField(plp, env->GetFieldID(plpClazz, "mPlpId", "I"))); |
| 1904 | FrontendAtsc3Modulation modulation = |
| 1905 | static_cast<FrontendAtsc3Modulation>( |
| 1906 | env->GetIntField(plp, env->GetFieldID(plpClazz, "mModulation", "I"))); |
| 1907 | FrontendAtsc3TimeInterleaveMode interleaveMode = |
| 1908 | static_cast<FrontendAtsc3TimeInterleaveMode>( |
| 1909 | env->GetIntField( |
| 1910 | plp, env->GetFieldID(plpClazz, "mInterleaveMode", "I"))); |
| 1911 | FrontendAtsc3CodeRate codeRate = |
| 1912 | static_cast<FrontendAtsc3CodeRate>( |
| 1913 | env->GetIntField(plp, env->GetFieldID(plpClazz, "mCodeRate", "I"))); |
| 1914 | FrontendAtsc3Fec fec = |
| 1915 | static_cast<FrontendAtsc3Fec>( |
| 1916 | env->GetIntField(plp, env->GetFieldID(plpClazz, "mFec", "I"))); |
| 1917 | FrontendAtsc3PlpSettings frontendAtsc3PlpSettings { |
| 1918 | .plpId = plpId, |
| 1919 | .modulation = modulation, |
| 1920 | .interleaveMode = interleaveMode, |
| 1921 | .codeRate = codeRate, |
| 1922 | .fec = fec, |
| 1923 | }; |
| 1924 | plps[i] = frontendAtsc3PlpSettings; |
| 1925 | } |
| 1926 | return plps; |
| 1927 | } |
| 1928 | |
| 1929 | static FrontendSettings getAtsc3FrontendSettings(JNIEnv *env, const jobject& settings) { |
| 1930 | FrontendSettings frontendSettings; |
| 1931 | uint32_t freq = getFrontendSettingsFreq(env, settings); |
| 1932 | jclass clazz = env->FindClass("android/media/tv/tuner/frontend/Atsc3FrontendSettings"); |
| 1933 | |
| 1934 | FrontendAtsc3Bandwidth bandwidth = |
| 1935 | static_cast<FrontendAtsc3Bandwidth>( |
| 1936 | env->GetIntField(settings, env->GetFieldID(clazz, "mBandwidth", "I"))); |
| 1937 | FrontendAtsc3DemodOutputFormat demod = |
| 1938 | static_cast<FrontendAtsc3DemodOutputFormat>( |
| 1939 | env->GetIntField( |
| 1940 | settings, env->GetFieldID(clazz, "mDemodOutputFormat", "I"))); |
| 1941 | hidl_vec<FrontendAtsc3PlpSettings> plps = getAtsc3PlpSettings(env, settings); |
| 1942 | FrontendAtsc3Settings frontendAtsc3Settings { |
| 1943 | .frequency = freq, |
| 1944 | .bandwidth = bandwidth, |
| 1945 | .demodOutputFormat = demod, |
| 1946 | .plpSettings = plps, |
| 1947 | }; |
| 1948 | frontendSettings.atsc3(frontendAtsc3Settings); |
| 1949 | return frontendSettings; |
| 1950 | } |
| 1951 | |
| 1952 | static FrontendSettings getAtscFrontendSettings(JNIEnv *env, const jobject& settings) { |
| 1953 | FrontendSettings frontendSettings; |
| 1954 | uint32_t freq = getFrontendSettingsFreq(env, settings); |
| 1955 | jclass clazz = env->FindClass("android/media/tv/tuner/frontend/AtscFrontendSettings"); |
| 1956 | FrontendAtscModulation modulation = |
| 1957 | static_cast<FrontendAtscModulation>( |
| 1958 | env->GetIntField(settings, env->GetFieldID(clazz, "mModulation", "I"))); |
| 1959 | FrontendAtscSettings frontendAtscSettings { |
| 1960 | .frequency = freq, |
| 1961 | .modulation = modulation, |
| 1962 | }; |
| 1963 | frontendSettings.atsc(frontendAtscSettings); |
| 1964 | return frontendSettings; |
| 1965 | } |
| 1966 | |
| 1967 | static FrontendSettings getDvbcFrontendSettings(JNIEnv *env, const jobject& settings) { |
| 1968 | FrontendSettings frontendSettings; |
| 1969 | uint32_t freq = getFrontendSettingsFreq(env, settings); |
| 1970 | jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbcFrontendSettings"); |
| 1971 | FrontendDvbcModulation modulation = |
| 1972 | static_cast<FrontendDvbcModulation>( |
| 1973 | env->GetIntField(settings, env->GetFieldID(clazz, "mModulation", "I"))); |
| 1974 | FrontendInnerFec innerFec = |
| 1975 | static_cast<FrontendInnerFec>( |
| 1976 | env->GetLongField(settings, env->GetFieldID(clazz, "mFec", "J"))); |
| 1977 | uint32_t symbolRate = |
| 1978 | static_cast<uint32_t>( |
| 1979 | env->GetIntField(settings, env->GetFieldID(clazz, "mSymbolRate", "I"))); |
| 1980 | FrontendDvbcOuterFec outerFec = |
| 1981 | static_cast<FrontendDvbcOuterFec>( |
| 1982 | env->GetIntField(settings, env->GetFieldID(clazz, "mOuterFec", "I"))); |
| 1983 | FrontendDvbcAnnex annex = |
| 1984 | static_cast<FrontendDvbcAnnex>( |
| 1985 | env->GetByteField(settings, env->GetFieldID(clazz, "mAnnex", "B"))); |
| 1986 | FrontendDvbcSpectralInversion spectralInversion = |
| 1987 | static_cast<FrontendDvbcSpectralInversion>( |
| 1988 | env->GetIntField( |
| 1989 | settings, env->GetFieldID(clazz, "mSpectralInversion", "I"))); |
| 1990 | FrontendDvbcSettings frontendDvbcSettings { |
| 1991 | .frequency = freq, |
| 1992 | .modulation = modulation, |
| 1993 | .fec = innerFec, |
| 1994 | .symbolRate = symbolRate, |
| 1995 | .outerFec = outerFec, |
| 1996 | .annex = annex, |
| 1997 | .spectralInversion = spectralInversion, |
| 1998 | }; |
| 1999 | frontendSettings.dvbc(frontendDvbcSettings); |
| 2000 | return frontendSettings; |
| 2001 | } |
| 2002 | |
| 2003 | static FrontendDvbsCodeRate getDvbsCodeRate(JNIEnv *env, const jobject& settings) { |
| 2004 | jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbsFrontendSettings"); |
| 2005 | jobject jcodeRate = |
| 2006 | env->GetObjectField(settings, |
| 2007 | env->GetFieldID( |
| 2008 | clazz, |
| 2009 | "mCodeRate", |
| 2010 | "Landroid/media/tv/tuner/frontend/DvbsCodeRate;")); |
| 2011 | |
| 2012 | jclass codeRateClazz = env->FindClass("android/media/tv/tuner/frontend/DvbsCodeRate"); |
| 2013 | FrontendInnerFec innerFec = |
| 2014 | static_cast<FrontendInnerFec>( |
| 2015 | env->GetLongField( |
| 2016 | jcodeRate, env->GetFieldID(codeRateClazz, "mInnerFec", "J"))); |
| 2017 | bool isLinear = |
| 2018 | static_cast<bool>( |
| 2019 | env->GetBooleanField( |
| 2020 | jcodeRate, env->GetFieldID(codeRateClazz, "mIsLinear", "Z"))); |
| 2021 | bool isShortFrames = |
| 2022 | static_cast<bool>( |
| 2023 | env->GetBooleanField( |
| 2024 | jcodeRate, env->GetFieldID(codeRateClazz, "mIsShortFrames", "Z"))); |
| 2025 | uint32_t bitsPer1000Symbol = |
| 2026 | static_cast<uint32_t>( |
| 2027 | env->GetIntField( |
| 2028 | jcodeRate, env->GetFieldID( |
| 2029 | codeRateClazz, "mBitsPer1000Symbol", "I"))); |
| 2030 | FrontendDvbsCodeRate coderate { |
| 2031 | .fec = innerFec, |
| 2032 | .isLinear = isLinear, |
| 2033 | .isShortFrames = isShortFrames, |
| 2034 | .bitsPer1000Symbol = bitsPer1000Symbol, |
| 2035 | }; |
| 2036 | return coderate; |
| 2037 | } |
| 2038 | |
| 2039 | static FrontendSettings getDvbsFrontendSettings(JNIEnv *env, const jobject& settings) { |
| 2040 | FrontendSettings frontendSettings; |
| 2041 | uint32_t freq = getFrontendSettingsFreq(env, settings); |
| 2042 | jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbsFrontendSettings"); |
| 2043 | |
| 2044 | |
| 2045 | FrontendDvbsModulation modulation = |
| 2046 | static_cast<FrontendDvbsModulation>( |
| 2047 | env->GetIntField(settings, env->GetFieldID(clazz, "mModulation", "I"))); |
| 2048 | uint32_t symbolRate = |
| 2049 | static_cast<uint32_t>( |
| 2050 | env->GetIntField(settings, env->GetFieldID(clazz, "mSymbolRate", "I"))); |
| 2051 | FrontendDvbsRolloff rolloff = |
| 2052 | static_cast<FrontendDvbsRolloff>( |
| 2053 | env->GetIntField(settings, env->GetFieldID(clazz, "mRolloff", "I"))); |
| 2054 | FrontendDvbsPilot pilot = |
| 2055 | static_cast<FrontendDvbsPilot>( |
| 2056 | env->GetIntField(settings, env->GetFieldID(clazz, "mPilot", "I"))); |
| 2057 | uint32_t inputStreamId = |
| 2058 | static_cast<uint32_t>( |
| 2059 | env->GetIntField(settings, env->GetFieldID(clazz, "mInputStreamId", "I"))); |
| 2060 | FrontendDvbsStandard standard = |
| 2061 | static_cast<FrontendDvbsStandard>( |
| 2062 | env->GetIntField(settings, env->GetFieldID(clazz, "mStandard", "I"))); |
| 2063 | FrontendDvbsVcmMode vcmMode = |
| 2064 | static_cast<FrontendDvbsVcmMode>( |
| 2065 | env->GetIntField(settings, env->GetFieldID(clazz, "mVcmMode", "I"))); |
| 2066 | FrontendDvbsCodeRate coderate = getDvbsCodeRate(env, settings); |
| 2067 | |
| 2068 | FrontendDvbsSettings frontendDvbsSettings { |
| 2069 | .frequency = freq, |
| 2070 | .modulation = modulation, |
| 2071 | .coderate = coderate, |
| 2072 | .symbolRate = symbolRate, |
| 2073 | .rolloff = rolloff, |
| 2074 | .pilot = pilot, |
| 2075 | .inputStreamId = inputStreamId, |
| 2076 | .standard = standard, |
| 2077 | .vcmMode = vcmMode, |
| 2078 | }; |
| 2079 | frontendSettings.dvbs(frontendDvbsSettings); |
| 2080 | return frontendSettings; |
| 2081 | } |
| 2082 | |
| 2083 | static FrontendSettings getDvbtFrontendSettings(JNIEnv *env, const jobject& settings) { |
| 2084 | FrontendSettings frontendSettings; |
| 2085 | uint32_t freq = getFrontendSettingsFreq(env, settings); |
| 2086 | jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbtFrontendSettings"); |
| 2087 | FrontendDvbtTransmissionMode transmissionMode = |
| 2088 | static_cast<FrontendDvbtTransmissionMode>( |
| 2089 | env->GetIntField( |
| 2090 | settings, env->GetFieldID(clazz, "mTransmissionMode", "I"))); |
| 2091 | FrontendDvbtBandwidth bandwidth = |
| 2092 | static_cast<FrontendDvbtBandwidth>( |
| 2093 | env->GetIntField(settings, env->GetFieldID(clazz, "mBandwidth", "I"))); |
| 2094 | FrontendDvbtConstellation constellation = |
| 2095 | static_cast<FrontendDvbtConstellation>( |
| 2096 | env->GetIntField(settings, env->GetFieldID(clazz, "mConstellation", "I"))); |
| 2097 | FrontendDvbtHierarchy hierarchy = |
| 2098 | static_cast<FrontendDvbtHierarchy>( |
| 2099 | env->GetIntField(settings, env->GetFieldID(clazz, "mHierarchy", "I"))); |
| 2100 | FrontendDvbtCoderate hpCoderate = |
| 2101 | static_cast<FrontendDvbtCoderate>( |
| 2102 | env->GetIntField(settings, env->GetFieldID(clazz, "mHpCodeRate", "I"))); |
| 2103 | FrontendDvbtCoderate lpCoderate = |
| 2104 | static_cast<FrontendDvbtCoderate>( |
| 2105 | env->GetIntField(settings, env->GetFieldID(clazz, "mLpCodeRate", "I"))); |
| 2106 | FrontendDvbtGuardInterval guardInterval = |
| 2107 | static_cast<FrontendDvbtGuardInterval>( |
| 2108 | env->GetIntField(settings, env->GetFieldID(clazz, "mGuardInterval", "I"))); |
| 2109 | bool isHighPriority = |
| 2110 | static_cast<bool>( |
| 2111 | env->GetBooleanField( |
| 2112 | settings, env->GetFieldID(clazz, "mIsHighPriority", "Z"))); |
| 2113 | FrontendDvbtStandard standard = |
| 2114 | static_cast<FrontendDvbtStandard>( |
| 2115 | env->GetIntField(settings, env->GetFieldID(clazz, "mStandard", "I"))); |
| 2116 | bool isMiso = |
| 2117 | static_cast<bool>( |
| 2118 | env->GetBooleanField(settings, env->GetFieldID(clazz, "mIsMiso", "Z"))); |
| 2119 | FrontendDvbtPlpMode plpMode = |
| 2120 | static_cast<FrontendDvbtPlpMode>( |
| 2121 | env->GetIntField(settings, env->GetFieldID(clazz, "mPlpMode", "I"))); |
| 2122 | uint8_t plpId = |
| 2123 | static_cast<uint8_t>( |
| 2124 | env->GetIntField(settings, env->GetFieldID(clazz, "mPlpId", "I"))); |
| 2125 | uint8_t plpGroupId = |
| 2126 | static_cast<uint8_t>( |
| 2127 | env->GetIntField(settings, env->GetFieldID(clazz, "mPlpGroupId", "I"))); |
| 2128 | |
| 2129 | FrontendDvbtSettings frontendDvbtSettings { |
| 2130 | .frequency = freq, |
| 2131 | .transmissionMode = transmissionMode, |
| 2132 | .bandwidth = bandwidth, |
| 2133 | .constellation = constellation, |
| 2134 | .hierarchy = hierarchy, |
| 2135 | .hpCoderate = hpCoderate, |
| 2136 | .lpCoderate = lpCoderate, |
| 2137 | .guardInterval = guardInterval, |
| 2138 | .isHighPriority = isHighPriority, |
| 2139 | .standard = standard, |
| 2140 | .isMiso = isMiso, |
| 2141 | .plpMode = plpMode, |
| 2142 | .plpId = plpId, |
| 2143 | .plpGroupId = plpGroupId, |
| 2144 | }; |
| 2145 | frontendSettings.dvbt(frontendDvbtSettings); |
| 2146 | return frontendSettings; |
| 2147 | } |
| 2148 | |
| 2149 | static FrontendSettings getIsdbsFrontendSettings(JNIEnv *env, const jobject& settings) { |
| 2150 | FrontendSettings frontendSettings; |
| 2151 | uint32_t freq = getFrontendSettingsFreq(env, settings); |
| 2152 | jclass clazz = env->FindClass("android/media/tv/tuner/frontend/IsdbsFrontendSettings"); |
| 2153 | uint16_t streamId = |
| 2154 | static_cast<uint16_t>( |
| 2155 | env->GetIntField(settings, env->GetFieldID(clazz, "mStreamId", "I"))); |
| 2156 | FrontendIsdbsStreamIdType streamIdType = |
| 2157 | static_cast<FrontendIsdbsStreamIdType>( |
| 2158 | env->GetIntField(settings, env->GetFieldID(clazz, "mStreamIdType", "I"))); |
| 2159 | FrontendIsdbsModulation modulation = |
| 2160 | static_cast<FrontendIsdbsModulation>( |
| 2161 | env->GetIntField(settings, env->GetFieldID(clazz, "mModulation", "I"))); |
| 2162 | FrontendIsdbsCoderate coderate = |
| 2163 | static_cast<FrontendIsdbsCoderate>( |
| 2164 | env->GetIntField(settings, env->GetFieldID(clazz, "mCodeRate", "I"))); |
| 2165 | uint32_t symbolRate = |
| 2166 | static_cast<uint32_t>( |
| 2167 | env->GetIntField(settings, env->GetFieldID(clazz, "mSymbolRate", "I"))); |
| 2168 | FrontendIsdbsRolloff rolloff = |
| 2169 | static_cast<FrontendIsdbsRolloff>( |
| 2170 | env->GetIntField(settings, env->GetFieldID(clazz, "mRolloff", "I"))); |
| 2171 | |
| 2172 | FrontendIsdbsSettings frontendIsdbsSettings { |
| 2173 | .frequency = freq, |
| 2174 | .streamId = streamId, |
| 2175 | .streamIdType = streamIdType, |
| 2176 | .modulation = modulation, |
| 2177 | .coderate = coderate, |
| 2178 | .symbolRate = symbolRate, |
| 2179 | .rolloff = rolloff, |
| 2180 | }; |
| 2181 | frontendSettings.isdbs(frontendIsdbsSettings); |
| 2182 | return frontendSettings; |
| 2183 | } |
| 2184 | |
| 2185 | static FrontendSettings getIsdbs3FrontendSettings(JNIEnv *env, const jobject& settings) { |
| 2186 | FrontendSettings frontendSettings; |
| 2187 | uint32_t freq = getFrontendSettingsFreq(env, settings); |
| 2188 | jclass clazz = env->FindClass("android/media/tv/tuner/frontend/Isdbs3FrontendSettings"); |
| 2189 | uint16_t streamId = |
| 2190 | static_cast<uint16_t>( |
| 2191 | env->GetIntField(settings, env->GetFieldID(clazz, "mStreamId", "I"))); |
| 2192 | FrontendIsdbsStreamIdType streamIdType = |
| 2193 | static_cast<FrontendIsdbsStreamIdType>( |
| 2194 | env->GetIntField(settings, env->GetFieldID(clazz, "mStreamIdType", "I"))); |
| 2195 | FrontendIsdbs3Modulation modulation = |
| 2196 | static_cast<FrontendIsdbs3Modulation>( |
| 2197 | env->GetIntField(settings, env->GetFieldID(clazz, "mModulation", "I"))); |
| 2198 | FrontendIsdbs3Coderate coderate = |
| 2199 | static_cast<FrontendIsdbs3Coderate>( |
| 2200 | env->GetIntField(settings, env->GetFieldID(clazz, "mCodeRate", "I"))); |
| 2201 | uint32_t symbolRate = |
| 2202 | static_cast<uint32_t>( |
| 2203 | env->GetIntField(settings, env->GetFieldID(clazz, "mSymbolRate", "I"))); |
| 2204 | FrontendIsdbs3Rolloff rolloff = |
| 2205 | static_cast<FrontendIsdbs3Rolloff>( |
| 2206 | env->GetIntField(settings, env->GetFieldID(clazz, "mRolloff", "I"))); |
| 2207 | |
| 2208 | FrontendIsdbs3Settings frontendIsdbs3Settings { |
| 2209 | .frequency = freq, |
| 2210 | .streamId = streamId, |
| 2211 | .streamIdType = streamIdType, |
| 2212 | .modulation = modulation, |
| 2213 | .coderate = coderate, |
| 2214 | .symbolRate = symbolRate, |
| 2215 | .rolloff = rolloff, |
| 2216 | }; |
| 2217 | frontendSettings.isdbs3(frontendIsdbs3Settings); |
| 2218 | return frontendSettings; |
| 2219 | } |
| 2220 | |
| 2221 | static FrontendSettings getIsdbtFrontendSettings(JNIEnv *env, const jobject& settings) { |
| 2222 | FrontendSettings frontendSettings; |
| 2223 | uint32_t freq = getFrontendSettingsFreq(env, settings); |
| 2224 | jclass clazz = env->FindClass("android/media/tv/tuner/frontend/IsdbtFrontendSettings"); |
| 2225 | FrontendIsdbtModulation modulation = |
| 2226 | static_cast<FrontendIsdbtModulation>( |
| 2227 | env->GetIntField(settings, env->GetFieldID(clazz, "mModulation", "I"))); |
| 2228 | FrontendIsdbtBandwidth bandwidth = |
| 2229 | static_cast<FrontendIsdbtBandwidth>( |
| 2230 | env->GetIntField(settings, env->GetFieldID(clazz, "mBandwidth", "I"))); |
| 2231 | FrontendIsdbtMode mode = |
| 2232 | static_cast<FrontendIsdbtMode>( |
| 2233 | env->GetIntField(settings, env->GetFieldID(clazz, "mMode", "I"))); |
| 2234 | FrontendIsdbtCoderate coderate = |
| 2235 | static_cast<FrontendIsdbtCoderate>( |
| 2236 | env->GetIntField(settings, env->GetFieldID(clazz, "mCodeRate", "I"))); |
| 2237 | FrontendIsdbtGuardInterval guardInterval = |
| 2238 | static_cast<FrontendIsdbtGuardInterval>( |
| 2239 | env->GetIntField(settings, env->GetFieldID(clazz, "mGuardInterval", "I"))); |
| 2240 | uint32_t serviceAreaId = |
| 2241 | static_cast<uint32_t>( |
| 2242 | env->GetIntField(settings, env->GetFieldID(clazz, "mServiceAreaId", "I"))); |
| 2243 | |
| 2244 | FrontendIsdbtSettings frontendIsdbtSettings { |
| 2245 | .frequency = freq, |
| 2246 | .modulation = modulation, |
| 2247 | .bandwidth = bandwidth, |
| 2248 | .mode = mode, |
| 2249 | .coderate = coderate, |
| 2250 | .guardInterval = guardInterval, |
| 2251 | .serviceAreaId = serviceAreaId, |
| 2252 | }; |
| 2253 | frontendSettings.isdbt(frontendIsdbtSettings); |
| 2254 | return frontendSettings; |
| 2255 | } |
| 2256 | |
| 2257 | static FrontendSettings getFrontendSettings(JNIEnv *env, int type, jobject settings) { |
| 2258 | ALOGD("getFrontendSettings %d", type); |
| 2259 | |
| 2260 | FrontendType feType = static_cast<FrontendType>(type); |
| 2261 | switch(feType) { |
| 2262 | case FrontendType::ANALOG: |
| 2263 | return getAnalogFrontendSettings(env, settings); |
| 2264 | case FrontendType::ATSC3: |
| 2265 | return getAtsc3FrontendSettings(env, settings); |
| 2266 | case FrontendType::ATSC: |
| 2267 | return getAtscFrontendSettings(env, settings); |
| 2268 | case FrontendType::DVBC: |
| 2269 | return getDvbcFrontendSettings(env, settings); |
| 2270 | case FrontendType::DVBS: |
| 2271 | return getDvbsFrontendSettings(env, settings); |
| 2272 | case FrontendType::DVBT: |
| 2273 | return getDvbtFrontendSettings(env, settings); |
| 2274 | case FrontendType::ISDBS: |
| 2275 | return getIsdbsFrontendSettings(env, settings); |
| 2276 | case FrontendType::ISDBS3: |
| 2277 | return getIsdbs3FrontendSettings(env, settings); |
| 2278 | case FrontendType::ISDBT: |
| 2279 | return getIsdbtFrontendSettings(env, settings); |
| 2280 | default: |
| 2281 | // should never happen because a type is associated with a subclass of |
| 2282 | // FrontendSettings and not set by users |
| 2283 | jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", |
| 2284 | "Unsupported frontend type %d", type); |
| 2285 | return FrontendSettings(); |
| 2286 | } |
| 2287 | } |
| 2288 | |
shubang | 7648a3c | 2019-11-25 18:16:45 -0800 | [diff] [blame] | 2289 | static sp<Filter> getFilter(JNIEnv *env, jobject filter) { |
| 2290 | return (Filter *)env->GetLongField(filter, gFields.filterContext); |
shubang | cdf30de | 2019-11-06 17:28:38 -0800 | [diff] [blame] | 2291 | } |
| 2292 | |
shubang | 030afb5 | 2019-11-27 16:09:02 -0800 | [diff] [blame] | 2293 | static DvrSettings getDvrSettings(JNIEnv *env, jobject settings) { |
| 2294 | DvrSettings dvrSettings; |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 2295 | jclass clazz = env->FindClass("android/media/tv/tuner/dvr/DvrSettings"); |
shubang | 030afb5 | 2019-11-27 16:09:02 -0800 | [diff] [blame] | 2296 | uint32_t statusMask = |
| 2297 | static_cast<uint32_t>(env->GetIntField( |
| 2298 | settings, env->GetFieldID(clazz, "mStatusMask", "I"))); |
| 2299 | uint32_t lowThreshold = |
| 2300 | static_cast<uint32_t>(env->GetIntField( |
| 2301 | settings, env->GetFieldID(clazz, "mLowThreshold", "I"))); |
| 2302 | uint32_t highThreshold = |
| 2303 | static_cast<uint32_t>(env->GetIntField( |
| 2304 | settings, env->GetFieldID(clazz, "mHighThreshold", "I"))); |
| 2305 | uint8_t packetSize = |
| 2306 | static_cast<uint8_t>(env->GetIntField( |
| 2307 | settings, env->GetFieldID(clazz, "mPacketSize", "I"))); |
| 2308 | DataFormat dataFormat = |
| 2309 | static_cast<DataFormat>(env->GetIntField( |
| 2310 | settings, env->GetFieldID(clazz, "mDataFormat", "I"))); |
| 2311 | DvrType type = |
| 2312 | static_cast<DvrType>(env->GetIntField( |
| 2313 | settings, env->GetFieldID(clazz, "mType", "I"))); |
| 2314 | if (type == DvrType::RECORD) { |
| 2315 | RecordSettings recordSettings { |
| 2316 | .statusMask = static_cast<unsigned char>(statusMask), |
| 2317 | .lowThreshold = lowThreshold, |
| 2318 | .highThreshold = highThreshold, |
| 2319 | .dataFormat = dataFormat, |
| 2320 | .packetSize = packetSize, |
| 2321 | }; |
| 2322 | dvrSettings.record(recordSettings); |
| 2323 | } else if (type == DvrType::PLAYBACK) { |
| 2324 | PlaybackSettings PlaybackSettings { |
| 2325 | .statusMask = statusMask, |
| 2326 | .lowThreshold = lowThreshold, |
| 2327 | .highThreshold = highThreshold, |
| 2328 | .dataFormat = dataFormat, |
| 2329 | .packetSize = packetSize, |
| 2330 | }; |
| 2331 | dvrSettings.playback(PlaybackSettings); |
| 2332 | } |
| 2333 | return dvrSettings; |
| 2334 | } |
| 2335 | |
shubang | 9e700ff | 2019-12-04 16:26:51 -0800 | [diff] [blame] | 2336 | static sp<Dvr> getDvr(JNIEnv *env, jobject dvr) { |
shubang | 5637a66 | 2020-02-27 18:06:21 -0800 | [diff] [blame] | 2337 | bool isRecorder = |
| 2338 | env->IsInstanceOf(dvr, env->FindClass("android/media/tv/tuner/dvr/DvrRecorder")); |
| 2339 | jfieldID fieldId = |
| 2340 | isRecorder ? gFields.dvrRecorderContext : gFields.dvrPlaybackContext; |
| 2341 | return (Dvr *)env->GetLongField(dvr, fieldId); |
shubang | 4a0eddf | 2019-11-08 17:10:18 -0800 | [diff] [blame] | 2342 | } |
| 2343 | |
shubang | 8ab43b1 | 2019-10-18 15:55:55 -0700 | [diff] [blame] | 2344 | static void android_media_tv_Tuner_native_init(JNIEnv *env) { |
| 2345 | jclass clazz = env->FindClass("android/media/tv/tuner/Tuner"); |
| 2346 | CHECK(clazz != NULL); |
| 2347 | |
shubang | 13f15e0 | 2019-11-04 17:51:02 -0800 | [diff] [blame] | 2348 | gFields.tunerContext = env->GetFieldID(clazz, "mNativeContext", "J"); |
| 2349 | CHECK(gFields.tunerContext != NULL); |
shubang | 7e849b0 | 2019-10-18 19:36:25 -0700 | [diff] [blame] | 2350 | |
shubang | 4b8c540 | 2019-10-24 17:49:53 -0700 | [diff] [blame] | 2351 | gFields.onFrontendEventID = env->GetMethodID(clazz, "onFrontendEvent", "(I)V"); |
| 2352 | |
shubang | 7e849b0 | 2019-10-18 19:36:25 -0700 | [diff] [blame] | 2353 | jclass frontendClazz = env->FindClass("android/media/tv/tuner/Tuner$Frontend"); |
shubang | 4b8c540 | 2019-10-24 17:49:53 -0700 | [diff] [blame] | 2354 | gFields.frontendInitID = |
| 2355 | env->GetMethodID(frontendClazz, "<init>", "(Landroid/media/tv/tuner/Tuner;I)V"); |
shubang | 6f473d6 | 2019-11-01 15:42:21 -0700 | [diff] [blame] | 2356 | |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 2357 | jclass lnbClazz = env->FindClass("android/media/tv/tuner/Lnb"); |
shubang | 1c1144e | 2020-03-03 18:00:17 -0800 | [diff] [blame] | 2358 | gFields.lnbContext = env->GetFieldID(lnbClazz, "mNativeContext", "J"); |
shubang | 757602f | 2020-03-06 15:23:41 -0800 | [diff] [blame] | 2359 | gFields.lnbInitID = env->GetMethodID(lnbClazz, "<init>", "(I)V"); |
shubang | d295be0 | 2020-03-27 17:08:11 -0700 | [diff] [blame] | 2360 | gFields.onLnbEventID = env->GetMethodID(lnbClazz, "onEvent", "(I)V"); |
| 2361 | gFields.onLnbDiseqcMessageID = env->GetMethodID(lnbClazz, "onDiseqcMessage", "([B)V"); |
shubang | 760f031 | 2019-11-12 17:11:28 -0800 | [diff] [blame] | 2362 | |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 2363 | jclass filterClazz = env->FindClass("android/media/tv/tuner/filter/Filter"); |
shubang | cdf30de | 2019-11-06 17:28:38 -0800 | [diff] [blame] | 2364 | gFields.filterContext = env->GetFieldID(filterClazz, "mNativeContext", "J"); |
shubang | 6f473d6 | 2019-11-01 15:42:21 -0700 | [diff] [blame] | 2365 | gFields.filterInitID = |
shubang | deb067c | 2020-01-27 13:21:55 -0800 | [diff] [blame] | 2366 | env->GetMethodID(filterClazz, "<init>", "(I)V"); |
shubang | cdf30de | 2019-11-06 17:28:38 -0800 | [diff] [blame] | 2367 | gFields.onFilterStatusID = |
| 2368 | env->GetMethodID(filterClazz, "onFilterStatus", "(I)V"); |
shubang | 3e0c37b | 2020-02-19 19:09:10 -0800 | [diff] [blame] | 2369 | gFields.onFilterEventID = |
| 2370 | env->GetMethodID(filterClazz, "onFilterEvent", |
| 2371 | "([Landroid/media/tv/tuner/filter/FilterEvent;)V"); |
shubang | 13f15e0 | 2019-11-04 17:51:02 -0800 | [diff] [blame] | 2372 | |
shubang | f657da2 | 2020-02-05 16:27:06 -0800 | [diff] [blame] | 2373 | jclass timeFilterClazz = env->FindClass("android/media/tv/tuner/filter/TimeFilter"); |
| 2374 | gFields.timeFilterContext = env->GetFieldID(timeFilterClazz, "mNativeContext", "J"); |
| 2375 | gFields.timeFilterInitID = env->GetMethodID(timeFilterClazz, "<init>", "()V"); |
| 2376 | |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 2377 | jclass descramblerClazz = env->FindClass("android/media/tv/tuner/Descrambler"); |
shubang | 13f15e0 | 2019-11-04 17:51:02 -0800 | [diff] [blame] | 2378 | gFields.descramblerContext = env->GetFieldID(descramblerClazz, "mNativeContext", "J"); |
shubang | 40454db | 2020-03-30 16:52:29 -0700 | [diff] [blame] | 2379 | gFields.descramblerInitID = env->GetMethodID(descramblerClazz, "<init>", "()V"); |
shubang | 4a0eddf | 2019-11-08 17:10:18 -0800 | [diff] [blame] | 2380 | |
shubang | 5637a66 | 2020-02-27 18:06:21 -0800 | [diff] [blame] | 2381 | jclass dvrRecorderClazz = env->FindClass("android/media/tv/tuner/dvr/DvrRecorder"); |
| 2382 | gFields.dvrRecorderContext = env->GetFieldID(dvrRecorderClazz, "mNativeContext", "J"); |
| 2383 | gFields.dvrRecorderInitID = env->GetMethodID(dvrRecorderClazz, "<init>", "()V"); |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 2384 | gFields.onDvrRecordStatusID = |
| 2385 | env->GetMethodID(dvrRecorderClazz, "onRecordStatusChanged", "(I)V"); |
shubang | 5637a66 | 2020-02-27 18:06:21 -0800 | [diff] [blame] | 2386 | |
| 2387 | jclass dvrPlaybackClazz = env->FindClass("android/media/tv/tuner/dvr/DvrPlayback"); |
| 2388 | gFields.dvrPlaybackContext = env->GetFieldID(dvrPlaybackClazz, "mNativeContext", "J"); |
| 2389 | gFields.dvrPlaybackInitID = env->GetMethodID(dvrPlaybackClazz, "<init>", "()V"); |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 2390 | gFields.onDvrPlaybackStatusID = |
shubang | 66cc3aa | 2020-04-06 17:10:01 -0700 | [diff] [blame] | 2391 | env->GetMethodID(dvrPlaybackClazz, "onPlaybackStatusChanged", "(I)V"); |
shubang | d49681e | 2020-02-17 21:32:30 -0800 | [diff] [blame] | 2392 | |
| 2393 | jclass linearBlockClazz = env->FindClass("android/media/MediaCodec$LinearBlock"); |
| 2394 | gFields.linearBlockInitID = env->GetMethodID(linearBlockClazz, "<init>", "()V"); |
| 2395 | gFields.linearBlockSetInternalStateID = |
| 2396 | env->GetMethodID(linearBlockClazz, "setInternalStateLocked", "(JZ)V"); |
shubang | 8ab43b1 | 2019-10-18 15:55:55 -0700 | [diff] [blame] | 2397 | } |
| 2398 | |
| 2399 | static void android_media_tv_Tuner_native_setup(JNIEnv *env, jobject thiz) { |
| 2400 | sp<JTuner> tuner = new JTuner(env, thiz); |
| 2401 | setTuner(env,thiz, tuner); |
| 2402 | } |
| 2403 | |
shubang | 7e849b0 | 2019-10-18 19:36:25 -0700 | [diff] [blame] | 2404 | static jobject android_media_tv_Tuner_get_frontend_ids(JNIEnv *env, jobject thiz) { |
| 2405 | sp<JTuner> tuner = getTuner(env, thiz); |
| 2406 | return tuner->getFrontendIds(); |
| 2407 | } |
| 2408 | |
shubang | c18cc10 | 2020-03-12 16:28:45 -0700 | [diff] [blame] | 2409 | static jobject android_media_tv_Tuner_open_frontend_by_handle( |
| 2410 | JNIEnv *env, jobject thiz, jint handle) { |
shubang | 7e849b0 | 2019-10-18 19:36:25 -0700 | [diff] [blame] | 2411 | sp<JTuner> tuner = getTuner(env, thiz); |
shubang | c18cc10 | 2020-03-12 16:28:45 -0700 | [diff] [blame] | 2412 | uint32_t id = getResourceIdFromHandle(handle); |
shubang | 7e849b0 | 2019-10-18 19:36:25 -0700 | [diff] [blame] | 2413 | return tuner->openFrontendById(id); |
| 2414 | } |
| 2415 | |
shubang | 2f9cab3 | 2020-04-10 18:00:56 -0700 | [diff] [blame] | 2416 | static jint android_media_tv_Tuner_close_frontend_by_handle( |
| 2417 | JNIEnv *env, jobject thiz, jint handle) { |
| 2418 | sp<JTuner> tuner = getTuner(env, thiz); |
| 2419 | uint32_t id = getResourceIdFromHandle(handle); |
| 2420 | return tuner->closeFrontendById(id); |
| 2421 | } |
| 2422 | |
shubang | 74bfd48 | 2019-10-29 19:10:22 -0700 | [diff] [blame] | 2423 | static int android_media_tv_Tuner_tune(JNIEnv *env, jobject thiz, jint type, jobject settings) { |
| 2424 | sp<JTuner> tuner = getTuner(env, thiz); |
| 2425 | return tuner->tune(getFrontendSettings(env, type, settings)); |
| 2426 | } |
| 2427 | |
shubang | e32fb41 | 2020-01-28 14:53:05 -0800 | [diff] [blame] | 2428 | static int android_media_tv_Tuner_stop_tune(JNIEnv *env, jobject thiz) { |
| 2429 | sp<JTuner> tuner = getTuner(env, thiz); |
| 2430 | return tuner->stopTune(); |
shubang | e65b686 | 2019-12-17 15:43:35 -0800 | [diff] [blame] | 2431 | } |
| 2432 | |
shubang | d5b845f | 2019-12-11 15:29:09 -0800 | [diff] [blame] | 2433 | static int android_media_tv_Tuner_scan( |
| 2434 | JNIEnv *env, jobject thiz, jint settingsType, jobject settings, jint scanType) { |
| 2435 | sp<JTuner> tuner = getTuner(env, thiz); |
| 2436 | return tuner->scan(getFrontendSettings( |
| 2437 | env, settingsType, settings), static_cast<FrontendScanType>(scanType)); |
| 2438 | } |
| 2439 | |
shubang | e32fb41 | 2020-01-28 14:53:05 -0800 | [diff] [blame] | 2440 | static int android_media_tv_Tuner_stop_scan(JNIEnv *env, jobject thiz) { |
| 2441 | sp<JTuner> tuner = getTuner(env, thiz); |
| 2442 | return tuner->stopScan(); |
shubang | e65b686 | 2019-12-17 15:43:35 -0800 | [diff] [blame] | 2443 | } |
| 2444 | |
shubang | e32fb41 | 2020-01-28 14:53:05 -0800 | [diff] [blame] | 2445 | static int android_media_tv_Tuner_set_lnb(JNIEnv *env, jobject thiz, jint id) { |
| 2446 | sp<JTuner> tuner = getTuner(env, thiz); |
| 2447 | return tuner->setLnb(id); |
shubang | 793e570 | 2019-12-26 15:15:46 -0800 | [diff] [blame] | 2448 | } |
| 2449 | |
shubang | e32fb41 | 2020-01-28 14:53:05 -0800 | [diff] [blame] | 2450 | static int android_media_tv_Tuner_set_lna(JNIEnv *env, jobject thiz, jboolean enable) { |
| 2451 | sp<JTuner> tuner = getTuner(env, thiz); |
| 2452 | return tuner->setLna(enable); |
shubang | e65b686 | 2019-12-17 15:43:35 -0800 | [diff] [blame] | 2453 | } |
| 2454 | |
shubang | b83f823 | 2020-03-24 18:04:35 -0700 | [diff] [blame] | 2455 | static jobject android_media_tv_Tuner_get_frontend_status( |
| 2456 | JNIEnv* env, jobject thiz, jintArray types) { |
| 2457 | sp<JTuner> tuner = getTuner(env, thiz); |
| 2458 | return tuner->getFrontendStatus(types); |
shubang | 1512ec1 | 2019-12-23 18:22:42 -0800 | [diff] [blame] | 2459 | } |
| 2460 | |
shubang | bee7346 | 2020-02-07 17:48:02 -0800 | [diff] [blame] | 2461 | static jobject android_media_tv_Tuner_get_av_sync_hw_id( |
| 2462 | JNIEnv *env, jobject thiz, jobject filter) { |
| 2463 | sp<Filter> filterSp = getFilter(env, filter); |
| 2464 | if (filterSp == NULL) { |
| 2465 | ALOGD("Failed to get sync ID. Filter not found"); |
| 2466 | return NULL; |
| 2467 | } |
| 2468 | sp<JTuner> tuner = getTuner(env, thiz); |
| 2469 | return tuner->getAvSyncHwId(filterSp); |
shubang | 7343fee | 2019-12-27 12:02:08 -0800 | [diff] [blame] | 2470 | } |
| 2471 | |
shubang | bee7346 | 2020-02-07 17:48:02 -0800 | [diff] [blame] | 2472 | static jobject android_media_tv_Tuner_get_av_sync_time(JNIEnv *env, jobject thiz, jint id) { |
| 2473 | sp<JTuner> tuner = getTuner(env, thiz); |
| 2474 | return tuner->getAvSyncTime(id); |
shubang | 7343fee | 2019-12-27 12:02:08 -0800 | [diff] [blame] | 2475 | } |
| 2476 | |
shubang | bee7346 | 2020-02-07 17:48:02 -0800 | [diff] [blame] | 2477 | static int android_media_tv_Tuner_connect_cicam(JNIEnv *env, jobject thiz, jint id) { |
| 2478 | sp<JTuner> tuner = getTuner(env, thiz); |
| 2479 | return tuner->connectCiCam(id); |
shubang | 7343fee | 2019-12-27 12:02:08 -0800 | [diff] [blame] | 2480 | } |
| 2481 | |
shubang | bee7346 | 2020-02-07 17:48:02 -0800 | [diff] [blame] | 2482 | static int android_media_tv_Tuner_disconnect_cicam(JNIEnv *env, jobject thiz) { |
| 2483 | sp<JTuner> tuner = getTuner(env, thiz); |
| 2484 | return tuner->disconnectCiCam(); |
shubang | 7343fee | 2019-12-27 12:02:08 -0800 | [diff] [blame] | 2485 | } |
| 2486 | |
shubang | 51cc62f | 2020-01-28 18:00:22 -0800 | [diff] [blame] | 2487 | static jobject android_media_tv_Tuner_get_frontend_info(JNIEnv *env, jobject thiz, jint id) { |
| 2488 | sp<JTuner> tuner = getTuner(env, thiz); |
| 2489 | return tuner->getFrontendInfo(id); |
shubang | 95c1f75 | 2019-12-27 16:29:48 -0800 | [diff] [blame] | 2490 | } |
| 2491 | |
shubang | 0dc8394 | 2020-04-02 17:19:31 -0700 | [diff] [blame] | 2492 | static jintArray android_media_tv_Tuner_get_lnb_ids(JNIEnv *env, jobject thiz) { |
shubang | 760f031 | 2019-11-12 17:11:28 -0800 | [diff] [blame] | 2493 | sp<JTuner> tuner = getTuner(env, thiz); |
| 2494 | return tuner->getLnbIds(); |
| 2495 | } |
| 2496 | |
shubang | c18cc10 | 2020-03-12 16:28:45 -0700 | [diff] [blame] | 2497 | static jobject android_media_tv_Tuner_open_lnb_by_handle(JNIEnv *env, jobject thiz, jint handle) { |
shubang | 760f031 | 2019-11-12 17:11:28 -0800 | [diff] [blame] | 2498 | sp<JTuner> tuner = getTuner(env, thiz); |
shubang | c18cc10 | 2020-03-12 16:28:45 -0700 | [diff] [blame] | 2499 | uint32_t id = getResourceIdFromHandle(handle); |
shubang | 760f031 | 2019-11-12 17:11:28 -0800 | [diff] [blame] | 2500 | return tuner->openLnbById(id); |
| 2501 | } |
| 2502 | |
shubang | 757602f | 2020-03-06 15:23:41 -0800 | [diff] [blame] | 2503 | static jobject android_media_tv_Tuner_open_lnb_by_name(JNIEnv *env, jobject thiz, jstring name) { |
| 2504 | sp<JTuner> tuner = getTuner(env, thiz); |
| 2505 | return tuner->openLnbByName(name); |
| 2506 | } |
| 2507 | |
| 2508 | |
shubang | 6f473d6 | 2019-11-01 15:42:21 -0700 | [diff] [blame] | 2509 | static jobject android_media_tv_Tuner_open_filter( |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 2510 | JNIEnv *env, jobject thiz, jint type, jint subType, jlong bufferSize) { |
shubang | 6f473d6 | 2019-11-01 15:42:21 -0700 | [diff] [blame] | 2511 | sp<JTuner> tuner = getTuner(env, thiz); |
shubang | f657da2 | 2020-02-05 16:27:06 -0800 | [diff] [blame] | 2512 | DemuxFilterMainType mainType = static_cast<DemuxFilterMainType>(type); |
shubang | 6f473d6 | 2019-11-01 15:42:21 -0700 | [diff] [blame] | 2513 | DemuxFilterType filterType { |
shubang | f657da2 | 2020-02-05 16:27:06 -0800 | [diff] [blame] | 2514 | .mainType = mainType, |
shubang | 6f473d6 | 2019-11-01 15:42:21 -0700 | [diff] [blame] | 2515 | }; |
| 2516 | |
shubang | f657da2 | 2020-02-05 16:27:06 -0800 | [diff] [blame] | 2517 | switch(mainType) { |
| 2518 | case DemuxFilterMainType::TS: |
| 2519 | filterType.subType.tsFilterType(static_cast<DemuxTsFilterType>(subType)); |
| 2520 | break; |
| 2521 | case DemuxFilterMainType::MMTP: |
| 2522 | filterType.subType.mmtpFilterType(static_cast<DemuxMmtpFilterType>(subType)); |
| 2523 | break; |
| 2524 | case DemuxFilterMainType::IP: |
| 2525 | filterType.subType.ipFilterType(static_cast<DemuxIpFilterType>(subType)); |
| 2526 | break; |
| 2527 | case DemuxFilterMainType::TLV: |
| 2528 | filterType.subType.tlvFilterType(static_cast<DemuxTlvFilterType>(subType)); |
| 2529 | break; |
| 2530 | case DemuxFilterMainType::ALP: |
| 2531 | filterType.subType.alpFilterType(static_cast<DemuxAlpFilterType>(subType)); |
| 2532 | break; |
| 2533 | } |
shubang | 6f473d6 | 2019-11-01 15:42:21 -0700 | [diff] [blame] | 2534 | |
| 2535 | return tuner->openFilter(filterType, bufferSize); |
| 2536 | } |
| 2537 | |
shubang | f657da2 | 2020-02-05 16:27:06 -0800 | [diff] [blame] | 2538 | static jobject android_media_tv_Tuner_open_time_filter(JNIEnv *env, jobject thiz) { |
| 2539 | sp<JTuner> tuner = getTuner(env, thiz); |
| 2540 | return tuner->openTimeFilter(); |
shubang | 4347e2e | 2019-12-13 17:20:40 -0800 | [diff] [blame] | 2541 | } |
| 2542 | |
shubang | 44fa142 | 2020-01-30 11:42:59 -0800 | [diff] [blame] | 2543 | static DemuxFilterSectionBits getFilterSectionBits(JNIEnv *env, const jobject& settings) { |
| 2544 | jclass clazz = env->FindClass("android/media/tv/tuner/filter/SectionSettingsWithSectionBits"); |
| 2545 | jbyteArray jfilterBytes = static_cast<jbyteArray>( |
| 2546 | env->GetObjectField(settings, env->GetFieldID(clazz, "mFilter", "[B"))); |
| 2547 | jsize size = env->GetArrayLength(jfilterBytes); |
| 2548 | std::vector<uint8_t> filterBytes(size); |
| 2549 | env->GetByteArrayRegion( |
| 2550 | jfilterBytes, 0, size, reinterpret_cast<jbyte*>(&filterBytes[0])); |
| 2551 | |
| 2552 | jbyteArray jmask = static_cast<jbyteArray>( |
| 2553 | env->GetObjectField(settings, env->GetFieldID(clazz, "mMask", "[B"))); |
| 2554 | size = env->GetArrayLength(jmask); |
| 2555 | std::vector<uint8_t> mask(size); |
| 2556 | env->GetByteArrayRegion(jmask, 0, size, reinterpret_cast<jbyte*>(&mask[0])); |
| 2557 | |
| 2558 | jbyteArray jmode = static_cast<jbyteArray>( |
| 2559 | env->GetObjectField(settings, env->GetFieldID(clazz, "mMode", "[B"))); |
| 2560 | size = env->GetArrayLength(jmode); |
| 2561 | std::vector<uint8_t> mode(size); |
| 2562 | env->GetByteArrayRegion(jmode, 0, size, reinterpret_cast<jbyte*>(&mode[0])); |
| 2563 | |
| 2564 | DemuxFilterSectionBits filterSectionBits { |
| 2565 | .filter = filterBytes, |
| 2566 | .mask = mask, |
| 2567 | .mode = mode, |
| 2568 | }; |
| 2569 | return filterSectionBits; |
| 2570 | } |
| 2571 | |
| 2572 | static DemuxFilterSectionSettings::Condition::TableInfo getFilterTableInfo( |
| 2573 | JNIEnv *env, const jobject& settings) { |
| 2574 | jclass clazz = env->FindClass("android/media/tv/tuner/filter/SectionSettingsWithTableInfo"); |
| 2575 | uint16_t tableId = static_cast<uint16_t>( |
| 2576 | env->GetIntField(settings, env->GetFieldID(clazz, "mTableId", "I"))); |
| 2577 | uint16_t version = static_cast<uint16_t>( |
| 2578 | env->GetIntField(settings, env->GetFieldID(clazz, "mVersion", "I"))); |
| 2579 | DemuxFilterSectionSettings::Condition::TableInfo tableInfo { |
| 2580 | .tableId = tableId, |
| 2581 | .version = version, |
| 2582 | }; |
| 2583 | return tableInfo; |
| 2584 | } |
| 2585 | |
| 2586 | static DemuxFilterSectionSettings getFilterSectionSettings(JNIEnv *env, const jobject& settings) { |
| 2587 | jclass clazz = env->FindClass("android/media/tv/tuner/filter/SectionSettings"); |
| 2588 | bool isCheckCrc = static_cast<bool>( |
| 2589 | env->GetBooleanField(settings, env->GetFieldID(clazz, "mCrcEnabled", "Z"))); |
| 2590 | bool isRepeat = static_cast<bool>( |
| 2591 | env->GetBooleanField(settings, env->GetFieldID(clazz, "mIsRepeat", "Z"))); |
| 2592 | bool isRaw = static_cast<bool>( |
| 2593 | env->GetBooleanField(settings, env->GetFieldID(clazz, "mIsRaw", "Z"))); |
| 2594 | |
| 2595 | DemuxFilterSectionSettings filterSectionSettings { |
| 2596 | .isCheckCrc = isCheckCrc, |
| 2597 | .isRepeat = isRepeat, |
| 2598 | .isRaw = isRaw, |
| 2599 | }; |
| 2600 | if (env->IsInstanceOf( |
| 2601 | settings, |
| 2602 | env->FindClass("android/media/tv/tuner/filter/SectionSettingsWithSectionBits"))) { |
| 2603 | filterSectionSettings.condition.sectionBits(getFilterSectionBits(env, settings)); |
| 2604 | } else if (env->IsInstanceOf( |
| 2605 | settings, |
| 2606 | env->FindClass("android/media/tv/tuner/filter/SectionSettingsWithTableInfo"))) { |
| 2607 | filterSectionSettings.condition.tableInfo(getFilterTableInfo(env, settings)); |
| 2608 | } |
| 2609 | return filterSectionSettings; |
| 2610 | } |
| 2611 | |
| 2612 | static DemuxFilterAvSettings getFilterAvSettings(JNIEnv *env, const jobject& settings) { |
| 2613 | jclass clazz = env->FindClass("android/media/tv/tuner/filter/AvSettings"); |
| 2614 | bool isPassthrough = static_cast<bool>( |
| 2615 | env->GetBooleanField(settings, env->GetFieldID(clazz, "mIsPassthrough", "Z"))); |
| 2616 | DemuxFilterAvSettings filterAvSettings { |
| 2617 | .isPassthrough = isPassthrough, |
| 2618 | }; |
| 2619 | return filterAvSettings; |
| 2620 | } |
| 2621 | |
| 2622 | static DemuxFilterPesDataSettings getFilterPesDataSettings(JNIEnv *env, const jobject& settings) { |
| 2623 | jclass clazz = env->FindClass("android/media/tv/tuner/filter/PesSettings"); |
| 2624 | uint16_t streamId = static_cast<uint16_t>( |
| 2625 | env->GetIntField(settings, env->GetFieldID(clazz, "mStreamId", "I"))); |
| 2626 | bool isRaw = static_cast<bool>( |
| 2627 | env->GetBooleanField(settings, env->GetFieldID(clazz, "mIsRaw", "Z"))); |
| 2628 | DemuxFilterPesDataSettings filterPesDataSettings { |
| 2629 | .streamId = streamId, |
| 2630 | .isRaw = isRaw, |
| 2631 | }; |
| 2632 | return filterPesDataSettings; |
| 2633 | } |
| 2634 | |
| 2635 | static DemuxFilterRecordSettings getFilterRecordSettings(JNIEnv *env, const jobject& settings) { |
| 2636 | jclass clazz = env->FindClass("android/media/tv/tuner/filter/RecordSettings"); |
| 2637 | hidl_bitfield<DemuxTsIndex> tsIndexMask = static_cast<hidl_bitfield<DemuxTsIndex>>( |
| 2638 | env->GetIntField(settings, env->GetFieldID(clazz, "mTsIndexMask", "I"))); |
| 2639 | DemuxRecordScIndexType scIndexType = static_cast<DemuxRecordScIndexType>( |
| 2640 | env->GetIntField(settings, env->GetFieldID(clazz, "mScIndexType", "I"))); |
| 2641 | jint scIndexMask = env->GetIntField(settings, env->GetFieldID(clazz, "mScIndexMask", "I")); |
| 2642 | |
| 2643 | DemuxFilterRecordSettings filterRecordSettings { |
| 2644 | .tsIndexMask = tsIndexMask, |
| 2645 | .scIndexType = scIndexType, |
| 2646 | }; |
| 2647 | if (scIndexType == DemuxRecordScIndexType::SC) { |
| 2648 | filterRecordSettings.scIndexMask.sc(static_cast<hidl_bitfield<DemuxScIndex>>(scIndexMask)); |
| 2649 | } else if (scIndexType == DemuxRecordScIndexType::SC_HEVC) { |
| 2650 | filterRecordSettings.scIndexMask.scHevc( |
| 2651 | static_cast<hidl_bitfield<DemuxScHevcIndex>>(scIndexMask)); |
| 2652 | } |
| 2653 | return filterRecordSettings; |
| 2654 | } |
| 2655 | |
| 2656 | static DemuxFilterDownloadSettings getFilterDownloadSettings(JNIEnv *env, const jobject& settings) { |
| 2657 | jclass clazz = env->FindClass("android/media/tv/tuner/filter/DownloadSettings"); |
| 2658 | uint32_t downloadId = static_cast<uint32_t>( |
| 2659 | env->GetIntField(settings, env->GetFieldID(clazz, "mDownloadId", "I"))); |
| 2660 | |
| 2661 | DemuxFilterDownloadSettings filterDownloadSettings { |
| 2662 | .downloadId = downloadId, |
| 2663 | }; |
| 2664 | return filterDownloadSettings; |
| 2665 | } |
| 2666 | |
shubang | 87788c3 | 2020-02-04 13:55:23 -0800 | [diff] [blame] | 2667 | static DemuxIpAddress getDemuxIpAddress(JNIEnv *env, const jobject& config) { |
| 2668 | jclass clazz = env->FindClass("android/media/tv/tuner/filter/IpFilterConfiguration"); |
| 2669 | |
| 2670 | jbyteArray jsrcIpAddress = static_cast<jbyteArray>( |
| 2671 | env->GetObjectField(config, env->GetFieldID(clazz, "mSrcIpAddress", "[B"))); |
| 2672 | jsize srcSize = env->GetArrayLength(jsrcIpAddress); |
| 2673 | jbyteArray jdstIpAddress = static_cast<jbyteArray>( |
| 2674 | env->GetObjectField(config, env->GetFieldID(clazz, "mDstIpAddress", "[B"))); |
| 2675 | jsize dstSize = env->GetArrayLength(jdstIpAddress); |
| 2676 | |
| 2677 | DemuxIpAddress res; |
| 2678 | |
| 2679 | if (srcSize != dstSize) { |
| 2680 | // should never happen. Validated on Java size. |
| 2681 | jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", |
| 2682 | "IP address lengths don't match. srcLength=%d, dstLength=%d", srcSize, dstSize); |
| 2683 | return res; |
| 2684 | } |
| 2685 | |
| 2686 | if (srcSize == IP_V4_LENGTH) { |
| 2687 | uint8_t srcAddr[IP_V4_LENGTH]; |
| 2688 | uint8_t dstAddr[IP_V4_LENGTH]; |
| 2689 | env->GetByteArrayRegion( |
| 2690 | jsrcIpAddress, 0, srcSize, reinterpret_cast<jbyte*>(srcAddr)); |
| 2691 | env->GetByteArrayRegion( |
| 2692 | jdstIpAddress, 0, dstSize, reinterpret_cast<jbyte*>(dstAddr)); |
| 2693 | res.srcIpAddress.v4(srcAddr); |
| 2694 | res.dstIpAddress.v4(dstAddr); |
| 2695 | } else if (srcSize == IP_V6_LENGTH) { |
| 2696 | uint8_t srcAddr[IP_V6_LENGTH]; |
| 2697 | uint8_t dstAddr[IP_V6_LENGTH]; |
| 2698 | env->GetByteArrayRegion( |
| 2699 | jsrcIpAddress, 0, srcSize, reinterpret_cast<jbyte*>(srcAddr)); |
| 2700 | env->GetByteArrayRegion( |
| 2701 | jdstIpAddress, 0, dstSize, reinterpret_cast<jbyte*>(dstAddr)); |
| 2702 | res.srcIpAddress.v6(srcAddr); |
| 2703 | res.dstIpAddress.v6(dstAddr); |
| 2704 | } else { |
| 2705 | // should never happen. Validated on Java size. |
| 2706 | jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", |
| 2707 | "Invalid IP address length %d", srcSize); |
| 2708 | return res; |
| 2709 | } |
| 2710 | |
| 2711 | uint16_t srcPort = static_cast<uint16_t>( |
| 2712 | env->GetIntField(config, env->GetFieldID(clazz, "mSrcPort", "I"))); |
| 2713 | uint16_t dstPort = static_cast<uint16_t>( |
| 2714 | env->GetIntField(config, env->GetFieldID(clazz, "mDstPort", "I"))); |
| 2715 | |
| 2716 | res.srcPort = srcPort; |
| 2717 | res.dstPort = dstPort; |
| 2718 | |
| 2719 | return res; |
| 2720 | } |
| 2721 | |
shubang | 44fa142 | 2020-01-30 11:42:59 -0800 | [diff] [blame] | 2722 | static DemuxFilterSettings getFilterConfiguration( |
shubang | 87788c3 | 2020-02-04 13:55:23 -0800 | [diff] [blame] | 2723 | JNIEnv *env, int type, int subtype, jobject filterConfigObj) { |
shubang | 75c8708 | 2019-11-15 11:26:56 -0800 | [diff] [blame] | 2724 | DemuxFilterSettings filterSettings; |
shubang | 75c8708 | 2019-11-15 11:26:56 -0800 | [diff] [blame] | 2725 | jobject settingsObj = |
| 2726 | env->GetObjectField( |
shubang | 87788c3 | 2020-02-04 13:55:23 -0800 | [diff] [blame] | 2727 | filterConfigObj, |
shubang | 75c8708 | 2019-11-15 11:26:56 -0800 | [diff] [blame] | 2728 | env->GetFieldID( |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 2729 | env->FindClass("android/media/tv/tuner/filter/FilterConfiguration"), |
shubang | 75c8708 | 2019-11-15 11:26:56 -0800 | [diff] [blame] | 2730 | "mSettings", |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 2731 | "Landroid/media/tv/tuner/filter/Settings;")); |
shubang | 44fa142 | 2020-01-30 11:42:59 -0800 | [diff] [blame] | 2732 | DemuxFilterMainType mainType = static_cast<DemuxFilterMainType>(type); |
| 2733 | switch (mainType) { |
| 2734 | case DemuxFilterMainType::TS: { |
| 2735 | jclass clazz = env->FindClass("android/media/tv/tuner/filter/TsFilterConfiguration"); |
shubang | 87788c3 | 2020-02-04 13:55:23 -0800 | [diff] [blame] | 2736 | uint16_t tpid = static_cast<uint16_t>( |
| 2737 | env->GetIntField(filterConfigObj, env->GetFieldID(clazz, "mTpid", "I"))); |
shubang | 75c8708 | 2019-11-15 11:26:56 -0800 | [diff] [blame] | 2738 | DemuxTsFilterSettings tsFilterSettings { |
shubang | 87788c3 | 2020-02-04 13:55:23 -0800 | [diff] [blame] | 2739 | .tpid = tpid, |
shubang | 75c8708 | 2019-11-15 11:26:56 -0800 | [diff] [blame] | 2740 | }; |
shubang | 44fa142 | 2020-01-30 11:42:59 -0800 | [diff] [blame] | 2741 | |
| 2742 | DemuxTsFilterType tsType = static_cast<DemuxTsFilterType>(subtype); |
| 2743 | switch (tsType) { |
| 2744 | case DemuxTsFilterType::SECTION: |
| 2745 | tsFilterSettings.filterSettings.section( |
| 2746 | getFilterSectionSettings(env, settingsObj)); |
| 2747 | break; |
| 2748 | case DemuxTsFilterType::AUDIO: |
| 2749 | case DemuxTsFilterType::VIDEO: |
| 2750 | tsFilterSettings.filterSettings.av(getFilterAvSettings(env, settingsObj)); |
| 2751 | break; |
| 2752 | case DemuxTsFilterType::PES: |
| 2753 | tsFilterSettings.filterSettings.pesData( |
| 2754 | getFilterPesDataSettings(env, settingsObj)); |
| 2755 | break; |
| 2756 | case DemuxTsFilterType::RECORD: |
| 2757 | tsFilterSettings.filterSettings.record( |
| 2758 | getFilterRecordSettings(env, settingsObj)); |
| 2759 | break; |
| 2760 | default: |
| 2761 | break; |
| 2762 | } |
shubang | 75c8708 | 2019-11-15 11:26:56 -0800 | [diff] [blame] | 2763 | filterSettings.ts(tsFilterSettings); |
shubang | 44fa142 | 2020-01-30 11:42:59 -0800 | [diff] [blame] | 2764 | break; |
| 2765 | } |
| 2766 | case DemuxFilterMainType::MMTP: { |
shubang | 87788c3 | 2020-02-04 13:55:23 -0800 | [diff] [blame] | 2767 | jclass clazz = env->FindClass("android/media/tv/tuner/filter/MmtpFilterConfiguration"); |
| 2768 | uint16_t mmtpPid = static_cast<uint16_t>( |
| 2769 | env->GetIntField(filterConfigObj, env->GetFieldID(clazz, "mMmtpPid", "I"))); |
| 2770 | DemuxMmtpFilterSettings mmtpFilterSettings { |
| 2771 | .mmtpPid = mmtpPid, |
| 2772 | }; |
shubang | 44fa142 | 2020-01-30 11:42:59 -0800 | [diff] [blame] | 2773 | DemuxMmtpFilterType mmtpType = static_cast<DemuxMmtpFilterType>(subtype); |
| 2774 | switch (mmtpType) { |
| 2775 | case DemuxMmtpFilterType::SECTION: |
| 2776 | mmtpFilterSettings.filterSettings.section( |
| 2777 | getFilterSectionSettings(env, settingsObj)); |
| 2778 | break; |
| 2779 | case DemuxMmtpFilterType::AUDIO: |
| 2780 | case DemuxMmtpFilterType::VIDEO: |
| 2781 | mmtpFilterSettings.filterSettings.av(getFilterAvSettings(env, settingsObj)); |
| 2782 | break; |
| 2783 | case DemuxMmtpFilterType::PES: |
| 2784 | mmtpFilterSettings.filterSettings.pesData( |
| 2785 | getFilterPesDataSettings(env, settingsObj)); |
| 2786 | break; |
| 2787 | case DemuxMmtpFilterType::RECORD: |
| 2788 | mmtpFilterSettings.filterSettings.record( |
| 2789 | getFilterRecordSettings(env, settingsObj)); |
| 2790 | break; |
| 2791 | case DemuxMmtpFilterType::DOWNLOAD: |
| 2792 | mmtpFilterSettings.filterSettings.download( |
| 2793 | getFilterDownloadSettings(env, settingsObj)); |
| 2794 | break; |
| 2795 | default: |
| 2796 | break; |
| 2797 | } |
| 2798 | filterSettings.mmtp(mmtpFilterSettings); |
| 2799 | break; |
| 2800 | } |
| 2801 | case DemuxFilterMainType::IP: { |
shubang | 87788c3 | 2020-02-04 13:55:23 -0800 | [diff] [blame] | 2802 | DemuxIpAddress ipAddr = getDemuxIpAddress(env, filterConfigObj); |
| 2803 | |
| 2804 | DemuxIpFilterSettings ipFilterSettings { |
| 2805 | .ipAddr = ipAddr, |
| 2806 | }; |
shubang | 44fa142 | 2020-01-30 11:42:59 -0800 | [diff] [blame] | 2807 | DemuxIpFilterType ipType = static_cast<DemuxIpFilterType>(subtype); |
| 2808 | switch (ipType) { |
shubang | 87788c3 | 2020-02-04 13:55:23 -0800 | [diff] [blame] | 2809 | case DemuxIpFilterType::SECTION: { |
shubang | 44fa142 | 2020-01-30 11:42:59 -0800 | [diff] [blame] | 2810 | ipFilterSettings.filterSettings.section( |
| 2811 | getFilterSectionSettings(env, settingsObj)); |
| 2812 | break; |
shubang | 87788c3 | 2020-02-04 13:55:23 -0800 | [diff] [blame] | 2813 | } |
| 2814 | case DemuxIpFilterType::IP: { |
| 2815 | jclass clazz = env->FindClass( |
| 2816 | "android/media/tv/tuner/filter/IpFilterConfiguration"); |
| 2817 | bool bPassthrough = static_cast<bool>( |
| 2818 | env->GetBooleanField( |
| 2819 | filterConfigObj, env->GetFieldID( |
| 2820 | clazz, "mPassthrough", "Z"))); |
| 2821 | ipFilterSettings.filterSettings.bPassthrough(bPassthrough); |
shubang | 44fa142 | 2020-01-30 11:42:59 -0800 | [diff] [blame] | 2822 | break; |
shubang | 87788c3 | 2020-02-04 13:55:23 -0800 | [diff] [blame] | 2823 | } |
| 2824 | default: { |
shubang | 44fa142 | 2020-01-30 11:42:59 -0800 | [diff] [blame] | 2825 | break; |
shubang | 87788c3 | 2020-02-04 13:55:23 -0800 | [diff] [blame] | 2826 | } |
shubang | 44fa142 | 2020-01-30 11:42:59 -0800 | [diff] [blame] | 2827 | } |
| 2828 | filterSettings.ip(ipFilterSettings); |
| 2829 | break; |
| 2830 | } |
| 2831 | case DemuxFilterMainType::TLV: { |
shubang | 87788c3 | 2020-02-04 13:55:23 -0800 | [diff] [blame] | 2832 | jclass clazz = env->FindClass("android/media/tv/tuner/filter/TlvFilterConfiguration"); |
| 2833 | uint8_t packetType = static_cast<uint8_t>( |
| 2834 | env->GetIntField(filterConfigObj, env->GetFieldID(clazz, "mPacketType", "I"))); |
| 2835 | bool isCompressedIpPacket = static_cast<bool>( |
| 2836 | env->GetBooleanField( |
| 2837 | filterConfigObj, env->GetFieldID(clazz, "mIsCompressedIpPacket", "Z"))); |
| 2838 | |
| 2839 | DemuxTlvFilterSettings tlvFilterSettings { |
| 2840 | .packetType = packetType, |
| 2841 | .isCompressedIpPacket = isCompressedIpPacket, |
| 2842 | }; |
shubang | 44fa142 | 2020-01-30 11:42:59 -0800 | [diff] [blame] | 2843 | DemuxTlvFilterType tlvType = static_cast<DemuxTlvFilterType>(subtype); |
| 2844 | switch (tlvType) { |
shubang | 87788c3 | 2020-02-04 13:55:23 -0800 | [diff] [blame] | 2845 | case DemuxTlvFilterType::SECTION: { |
shubang | 44fa142 | 2020-01-30 11:42:59 -0800 | [diff] [blame] | 2846 | tlvFilterSettings.filterSettings.section( |
| 2847 | getFilterSectionSettings(env, settingsObj)); |
| 2848 | break; |
shubang | 87788c3 | 2020-02-04 13:55:23 -0800 | [diff] [blame] | 2849 | } |
| 2850 | case DemuxTlvFilterType::TLV: { |
| 2851 | bool bPassthrough = static_cast<bool>( |
| 2852 | env->GetBooleanField( |
| 2853 | filterConfigObj, env->GetFieldID( |
| 2854 | clazz, "mPassthrough", "Z"))); |
| 2855 | tlvFilterSettings.filterSettings.bPassthrough(bPassthrough); |
shubang | 44fa142 | 2020-01-30 11:42:59 -0800 | [diff] [blame] | 2856 | break; |
shubang | 87788c3 | 2020-02-04 13:55:23 -0800 | [diff] [blame] | 2857 | } |
| 2858 | default: { |
shubang | 44fa142 | 2020-01-30 11:42:59 -0800 | [diff] [blame] | 2859 | break; |
shubang | 87788c3 | 2020-02-04 13:55:23 -0800 | [diff] [blame] | 2860 | } |
shubang | 44fa142 | 2020-01-30 11:42:59 -0800 | [diff] [blame] | 2861 | } |
| 2862 | filterSettings.tlv(tlvFilterSettings); |
| 2863 | break; |
| 2864 | } |
| 2865 | case DemuxFilterMainType::ALP: { |
shubang | 87788c3 | 2020-02-04 13:55:23 -0800 | [diff] [blame] | 2866 | jclass clazz = env->FindClass("android/media/tv/tuner/filter/AlpFilterConfiguration"); |
| 2867 | uint8_t packetType = static_cast<uint8_t>( |
| 2868 | env->GetIntField(filterConfigObj, env->GetFieldID(clazz, "mPacketType", "I"))); |
| 2869 | DemuxAlpLengthType lengthType = static_cast<DemuxAlpLengthType>( |
| 2870 | env->GetIntField(filterConfigObj, env->GetFieldID(clazz, "mLengthType", "I"))); |
| 2871 | DemuxAlpFilterSettings alpFilterSettings { |
| 2872 | .packetType = packetType, |
| 2873 | .lengthType = lengthType, |
| 2874 | }; |
shubang | 44fa142 | 2020-01-30 11:42:59 -0800 | [diff] [blame] | 2875 | DemuxAlpFilterType alpType = static_cast<DemuxAlpFilterType>(subtype); |
| 2876 | switch (alpType) { |
| 2877 | case DemuxAlpFilterType::SECTION: |
| 2878 | alpFilterSettings.filterSettings.section( |
| 2879 | getFilterSectionSettings(env, settingsObj)); |
| 2880 | break; |
| 2881 | default: |
| 2882 | break; |
| 2883 | } |
| 2884 | filterSettings.alp(alpFilterSettings); |
| 2885 | break; |
| 2886 | } |
| 2887 | default: { |
| 2888 | break; |
shubang | 75c8708 | 2019-11-15 11:26:56 -0800 | [diff] [blame] | 2889 | } |
| 2890 | } |
| 2891 | return filterSettings; |
| 2892 | } |
| 2893 | |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 2894 | static jint copyData(JNIEnv *env, std::unique_ptr<MQ>& mq, EventFlag* flag, jbyteArray buffer, |
| 2895 | jlong offset, jlong size) { |
shubang | a06cfe5 | 2020-02-24 18:53:41 -0800 | [diff] [blame] | 2896 | ALOGD("copyData, size=%ld, offset=%ld", (long) size, (long) offset); |
shubang | 964e613 | 2019-11-26 15:05:22 -0800 | [diff] [blame] | 2897 | |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 2898 | jlong available = mq->availableToRead(); |
shubang | a06cfe5 | 2020-02-24 18:53:41 -0800 | [diff] [blame] | 2899 | ALOGD("copyData, available=%ld", (long) available); |
shubang | 964e613 | 2019-11-26 15:05:22 -0800 | [diff] [blame] | 2900 | size = std::min(size, available); |
| 2901 | |
| 2902 | jboolean isCopy; |
| 2903 | jbyte *dst = env->GetByteArrayElements(buffer, &isCopy); |
| 2904 | ALOGD("copyData, isCopy=%d", isCopy); |
| 2905 | if (dst == nullptr) { |
| 2906 | ALOGD("Failed to GetByteArrayElements"); |
| 2907 | return 0; |
| 2908 | } |
| 2909 | |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 2910 | if (mq->read(reinterpret_cast<unsigned char*>(dst) + offset, size)) { |
shubang | 964e613 | 2019-11-26 15:05:22 -0800 | [diff] [blame] | 2911 | env->ReleaseByteArrayElements(buffer, dst, 0); |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 2912 | flag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED)); |
shubang | 964e613 | 2019-11-26 15:05:22 -0800 | [diff] [blame] | 2913 | } else { |
| 2914 | ALOGD("Failed to read FMQ"); |
| 2915 | env->ReleaseByteArrayElements(buffer, dst, 0); |
| 2916 | return 0; |
| 2917 | } |
| 2918 | return size; |
| 2919 | } |
| 2920 | |
shubang | a06cfe5 | 2020-02-24 18:53:41 -0800 | [diff] [blame] | 2921 | static jint android_media_tv_Tuner_configure_filter( |
shubang | 75c8708 | 2019-11-15 11:26:56 -0800 | [diff] [blame] | 2922 | JNIEnv *env, jobject filter, int type, int subtype, jobject settings) { |
| 2923 | ALOGD("configure filter type=%d, subtype=%d", type, subtype); |
shubang | 964e613 | 2019-11-26 15:05:22 -0800 | [diff] [blame] | 2924 | sp<Filter> filterSp = getFilter(env, filter); |
| 2925 | sp<IFilter> iFilterSp = filterSp->getIFilter(); |
| 2926 | if (iFilterSp == NULL) { |
shubang | 75c8708 | 2019-11-15 11:26:56 -0800 | [diff] [blame] | 2927 | ALOGD("Failed to configure filter: filter not found"); |
shubang | 40454db | 2020-03-30 16:52:29 -0700 | [diff] [blame] | 2928 | return (jint) Result::NOT_INITIALIZED; |
shubang | 75c8708 | 2019-11-15 11:26:56 -0800 | [diff] [blame] | 2929 | } |
shubang | 44fa142 | 2020-01-30 11:42:59 -0800 | [diff] [blame] | 2930 | DemuxFilterSettings filterSettings = getFilterConfiguration(env, type, subtype, settings); |
shubang | 964e613 | 2019-11-26 15:05:22 -0800 | [diff] [blame] | 2931 | Result res = iFilterSp->configure(filterSettings); |
shubang | a06cfe5 | 2020-02-24 18:53:41 -0800 | [diff] [blame] | 2932 | |
| 2933 | if (res != Result::SUCCESS) { |
| 2934 | return (jint) res; |
| 2935 | } |
| 2936 | |
shubang | 964e613 | 2019-11-26 15:05:22 -0800 | [diff] [blame] | 2937 | MQDescriptorSync<uint8_t> filterMQDesc; |
shubang | a06cfe5 | 2020-02-24 18:53:41 -0800 | [diff] [blame] | 2938 | Result getQueueDescResult = Result::UNKNOWN_ERROR; |
| 2939 | if (filterSp->mFilterMQ == NULL) { |
shubang | 964e613 | 2019-11-26 15:05:22 -0800 | [diff] [blame] | 2940 | iFilterSp->getQueueDesc( |
| 2941 | [&](Result r, const MQDescriptorSync<uint8_t>& desc) { |
| 2942 | filterMQDesc = desc; |
| 2943 | getQueueDescResult = r; |
| 2944 | ALOGD("getFilterQueueDesc"); |
| 2945 | }); |
| 2946 | if (getQueueDescResult == Result::SUCCESS) { |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 2947 | filterSp->mFilterMQ = std::make_unique<MQ>(filterMQDesc, true); |
shubang | 964e613 | 2019-11-26 15:05:22 -0800 | [diff] [blame] | 2948 | EventFlag::createEventFlag( |
| 2949 | filterSp->mFilterMQ->getEventFlagWord(), &(filterSp->mFilterMQEventFlag)); |
| 2950 | } |
| 2951 | } |
shubang | a06cfe5 | 2020-02-24 18:53:41 -0800 | [diff] [blame] | 2952 | return (jint) getQueueDescResult; |
shubang | 75c8708 | 2019-11-15 11:26:56 -0800 | [diff] [blame] | 2953 | } |
| 2954 | |
shubang | a06cfe5 | 2020-02-24 18:53:41 -0800 | [diff] [blame] | 2955 | static jint android_media_tv_Tuner_get_filter_id(JNIEnv* env, jobject filter) { |
| 2956 | sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter(); |
| 2957 | if (iFilterSp == NULL) { |
| 2958 | ALOGD("Failed to get filter ID: filter not found"); |
shubang | 40454db | 2020-03-30 16:52:29 -0700 | [diff] [blame] | 2959 | return (int) Result::NOT_INITIALIZED; |
shubang | a06cfe5 | 2020-02-24 18:53:41 -0800 | [diff] [blame] | 2960 | } |
| 2961 | Result res; |
| 2962 | uint32_t id; |
| 2963 | iFilterSp->getId( |
| 2964 | [&](Result r, uint32_t filterId) { |
| 2965 | res = r; |
| 2966 | id = filterId; |
| 2967 | }); |
| 2968 | if (res != Result::SUCCESS) { |
| 2969 | return (jint) Constant::INVALID_FILTER_ID; |
| 2970 | } |
| 2971 | return (jint) id; |
shubang | 793e570 | 2019-12-26 15:15:46 -0800 | [diff] [blame] | 2972 | } |
| 2973 | |
shubang | a06cfe5 | 2020-02-24 18:53:41 -0800 | [diff] [blame] | 2974 | static jint android_media_tv_Tuner_set_filter_data_source( |
| 2975 | JNIEnv* env, jobject filter, jobject srcFilter) { |
| 2976 | sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter(); |
| 2977 | if (iFilterSp == NULL) { |
| 2978 | ALOGD("Failed to set filter data source: filter not found"); |
shubang | 40454db | 2020-03-30 16:52:29 -0700 | [diff] [blame] | 2979 | return (jint) Result::NOT_INITIALIZED; |
shubang | a06cfe5 | 2020-02-24 18:53:41 -0800 | [diff] [blame] | 2980 | } |
| 2981 | Result r; |
| 2982 | if (srcFilter == NULL) { |
| 2983 | r = iFilterSp->setDataSource(NULL); |
| 2984 | } else { |
| 2985 | sp<IFilter> srcSp = getFilter(env, srcFilter)->getIFilter(); |
| 2986 | if (iFilterSp == NULL) { |
| 2987 | ALOGD("Failed to set filter data source: src filter not found"); |
shubang | 40454db | 2020-03-30 16:52:29 -0700 | [diff] [blame] | 2988 | return (jint) Result::INVALID_ARGUMENT; |
shubang | a06cfe5 | 2020-02-24 18:53:41 -0800 | [diff] [blame] | 2989 | } |
| 2990 | r = iFilterSp->setDataSource(srcSp); |
| 2991 | } |
| 2992 | return (jint) r; |
shubang | 793e570 | 2019-12-26 15:15:46 -0800 | [diff] [blame] | 2993 | } |
| 2994 | |
shubang | a06cfe5 | 2020-02-24 18:53:41 -0800 | [diff] [blame] | 2995 | static jint android_media_tv_Tuner_start_filter(JNIEnv *env, jobject filter) { |
| 2996 | sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter(); |
| 2997 | if (iFilterSp == NULL) { |
shubang | d097790 | 2019-11-07 18:58:43 -0800 | [diff] [blame] | 2998 | ALOGD("Failed to start filter: filter not found"); |
shubang | 40454db | 2020-03-30 16:52:29 -0700 | [diff] [blame] | 2999 | return (jint) Result::NOT_INITIALIZED; |
shubang | d097790 | 2019-11-07 18:58:43 -0800 | [diff] [blame] | 3000 | } |
shubang | a06cfe5 | 2020-02-24 18:53:41 -0800 | [diff] [blame] | 3001 | Result r = iFilterSp->start(); |
| 3002 | return (jint) r; |
shubang | d097790 | 2019-11-07 18:58:43 -0800 | [diff] [blame] | 3003 | } |
| 3004 | |
shubang | a06cfe5 | 2020-02-24 18:53:41 -0800 | [diff] [blame] | 3005 | static jint android_media_tv_Tuner_stop_filter(JNIEnv *env, jobject filter) { |
| 3006 | sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter(); |
| 3007 | if (iFilterSp == NULL) { |
shubang | d097790 | 2019-11-07 18:58:43 -0800 | [diff] [blame] | 3008 | ALOGD("Failed to stop filter: filter not found"); |
shubang | 40454db | 2020-03-30 16:52:29 -0700 | [diff] [blame] | 3009 | return (jint) Result::NOT_INITIALIZED; |
shubang | d097790 | 2019-11-07 18:58:43 -0800 | [diff] [blame] | 3010 | } |
shubang | a06cfe5 | 2020-02-24 18:53:41 -0800 | [diff] [blame] | 3011 | Result r = iFilterSp->stop(); |
| 3012 | return (jint) r; |
shubang | d097790 | 2019-11-07 18:58:43 -0800 | [diff] [blame] | 3013 | } |
| 3014 | |
shubang | a06cfe5 | 2020-02-24 18:53:41 -0800 | [diff] [blame] | 3015 | static jint android_media_tv_Tuner_flush_filter(JNIEnv *env, jobject filter) { |
| 3016 | sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter(); |
| 3017 | if (iFilterSp == NULL) { |
shubang | d097790 | 2019-11-07 18:58:43 -0800 | [diff] [blame] | 3018 | ALOGD("Failed to flush filter: filter not found"); |
shubang | 40454db | 2020-03-30 16:52:29 -0700 | [diff] [blame] | 3019 | return (jint) Result::NOT_INITIALIZED; |
shubang | d097790 | 2019-11-07 18:58:43 -0800 | [diff] [blame] | 3020 | } |
shubang | a06cfe5 | 2020-02-24 18:53:41 -0800 | [diff] [blame] | 3021 | Result r = iFilterSp->flush(); |
| 3022 | return (jint) r; |
shubang | d097790 | 2019-11-07 18:58:43 -0800 | [diff] [blame] | 3023 | } |
| 3024 | |
shubang | a06cfe5 | 2020-02-24 18:53:41 -0800 | [diff] [blame] | 3025 | static jint android_media_tv_Tuner_read_filter_fmq( |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3026 | JNIEnv *env, jobject filter, jbyteArray buffer, jlong offset, jlong size) { |
shubang | 964e613 | 2019-11-26 15:05:22 -0800 | [diff] [blame] | 3027 | sp<Filter> filterSp = getFilter(env, filter); |
| 3028 | if (filterSp == NULL) { |
| 3029 | ALOGD("Failed to read filter FMQ: filter not found"); |
shubang | a06cfe5 | 2020-02-24 18:53:41 -0800 | [diff] [blame] | 3030 | return (jint) Result::INVALID_STATE; |
shubang | 964e613 | 2019-11-26 15:05:22 -0800 | [diff] [blame] | 3031 | } |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 3032 | return copyData(env, filterSp->mFilterMQ, filterSp->mFilterMQEventFlag, buffer, offset, size); |
shubang | 964e613 | 2019-11-26 15:05:22 -0800 | [diff] [blame] | 3033 | } |
| 3034 | |
shubang | a06cfe5 | 2020-02-24 18:53:41 -0800 | [diff] [blame] | 3035 | static jint android_media_tv_Tuner_close_filter(JNIEnv *env, jobject filter) { |
| 3036 | sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter(); |
| 3037 | if (iFilterSp == NULL) { |
| 3038 | ALOGD("Failed to close filter: filter not found"); |
shubang | 40454db | 2020-03-30 16:52:29 -0700 | [diff] [blame] | 3039 | return (jint) Result::NOT_INITIALIZED; |
shubang | a06cfe5 | 2020-02-24 18:53:41 -0800 | [diff] [blame] | 3040 | } |
| 3041 | Result r = iFilterSp->close(); |
| 3042 | return (jint) r; |
shubang | 793e570 | 2019-12-26 15:15:46 -0800 | [diff] [blame] | 3043 | } |
| 3044 | |
shubang | f657da2 | 2020-02-05 16:27:06 -0800 | [diff] [blame] | 3045 | static sp<TimeFilter> getTimeFilter(JNIEnv *env, jobject filter) { |
| 3046 | return (TimeFilter *)env->GetLongField(filter, gFields.timeFilterContext); |
| 3047 | } |
| 3048 | |
shubang | 4347e2e | 2019-12-13 17:20:40 -0800 | [diff] [blame] | 3049 | static int android_media_tv_Tuner_time_filter_set_timestamp( |
shubang | f657da2 | 2020-02-05 16:27:06 -0800 | [diff] [blame] | 3050 | JNIEnv *env, jobject filter, jlong timestamp) { |
| 3051 | sp<TimeFilter> filterSp = getTimeFilter(env, filter); |
| 3052 | if (filterSp == NULL) { |
| 3053 | ALOGD("Failed set timestamp: time filter not found"); |
| 3054 | return (int) Result::INVALID_STATE; |
| 3055 | } |
| 3056 | sp<ITimeFilter> iFilterSp = filterSp->getITimeFilter(); |
| 3057 | Result r = iFilterSp->setTimeStamp(static_cast<uint64_t>(timestamp)); |
| 3058 | return (int) r; |
shubang | 4347e2e | 2019-12-13 17:20:40 -0800 | [diff] [blame] | 3059 | } |
| 3060 | |
shubang | f657da2 | 2020-02-05 16:27:06 -0800 | [diff] [blame] | 3061 | static int android_media_tv_Tuner_time_filter_clear_timestamp(JNIEnv *env, jobject filter) { |
| 3062 | sp<TimeFilter> filterSp = getTimeFilter(env, filter); |
| 3063 | if (filterSp == NULL) { |
| 3064 | ALOGD("Failed clear timestamp: time filter not found"); |
| 3065 | return (int) Result::INVALID_STATE; |
| 3066 | } |
| 3067 | sp<ITimeFilter> iFilterSp = filterSp->getITimeFilter(); |
| 3068 | Result r = iFilterSp->clearTimeStamp(); |
| 3069 | return (int) r; |
shubang | 4347e2e | 2019-12-13 17:20:40 -0800 | [diff] [blame] | 3070 | } |
| 3071 | |
shubang | f657da2 | 2020-02-05 16:27:06 -0800 | [diff] [blame] | 3072 | static jobject android_media_tv_Tuner_time_filter_get_timestamp(JNIEnv *env, jobject filter) { |
| 3073 | sp<TimeFilter> filterSp = getTimeFilter(env, filter); |
| 3074 | if (filterSp == NULL) { |
| 3075 | ALOGD("Failed get timestamp: time filter not found"); |
| 3076 | return NULL; |
| 3077 | } |
| 3078 | |
| 3079 | sp<ITimeFilter> iFilterSp = filterSp->getITimeFilter(); |
| 3080 | Result res; |
| 3081 | uint64_t timestamp; |
| 3082 | iFilterSp->getTimeStamp( |
| 3083 | [&](Result r, uint64_t t) { |
| 3084 | res = r; |
| 3085 | timestamp = t; |
| 3086 | }); |
| 3087 | if (res != Result::SUCCESS) { |
| 3088 | return NULL; |
| 3089 | } |
| 3090 | |
| 3091 | jclass longClazz = env->FindClass("java/lang/Long"); |
| 3092 | jmethodID longInit = env->GetMethodID(longClazz, "<init>", "(J)V"); |
| 3093 | |
| 3094 | jobject longObj = env->NewObject(longClazz, longInit, static_cast<jlong>(timestamp)); |
| 3095 | return longObj; |
shubang | 4347e2e | 2019-12-13 17:20:40 -0800 | [diff] [blame] | 3096 | } |
| 3097 | |
shubang | f657da2 | 2020-02-05 16:27:06 -0800 | [diff] [blame] | 3098 | static jobject android_media_tv_Tuner_time_filter_get_source_time(JNIEnv *env, jobject filter) { |
| 3099 | sp<TimeFilter> filterSp = getTimeFilter(env, filter); |
| 3100 | if (filterSp == NULL) { |
| 3101 | ALOGD("Failed get source time: time filter not found"); |
| 3102 | return NULL; |
| 3103 | } |
| 3104 | |
| 3105 | sp<ITimeFilter> iFilterSp = filterSp->getITimeFilter(); |
| 3106 | Result res; |
| 3107 | uint64_t timestamp; |
| 3108 | iFilterSp->getSourceTime( |
| 3109 | [&](Result r, uint64_t t) { |
| 3110 | res = r; |
| 3111 | timestamp = t; |
| 3112 | }); |
| 3113 | if (res != Result::SUCCESS) { |
| 3114 | return NULL; |
| 3115 | } |
| 3116 | |
| 3117 | jclass longClazz = env->FindClass("java/lang/Long"); |
| 3118 | jmethodID longInit = env->GetMethodID(longClazz, "<init>", "(J)V"); |
| 3119 | |
| 3120 | jobject longObj = env->NewObject(longClazz, longInit, static_cast<jlong>(timestamp)); |
| 3121 | return longObj; |
shubang | 4347e2e | 2019-12-13 17:20:40 -0800 | [diff] [blame] | 3122 | } |
| 3123 | |
shubang | f657da2 | 2020-02-05 16:27:06 -0800 | [diff] [blame] | 3124 | static int android_media_tv_Tuner_time_filter_close(JNIEnv *env, jobject filter) { |
| 3125 | sp<TimeFilter> filterSp = getTimeFilter(env, filter); |
| 3126 | if (filterSp == NULL) { |
| 3127 | ALOGD("Failed close time filter: time filter not found"); |
| 3128 | return (int) Result::INVALID_STATE; |
| 3129 | } |
| 3130 | |
| 3131 | Result r = filterSp->getITimeFilter()->close(); |
| 3132 | if (r == Result::SUCCESS) { |
| 3133 | filterSp->decStrong(filter); |
| 3134 | env->SetLongField(filter, gFields.timeFilterContext, 0); |
| 3135 | } |
| 3136 | return (int) r; |
shubang | 4347e2e | 2019-12-13 17:20:40 -0800 | [diff] [blame] | 3137 | } |
| 3138 | |
shubang | f159a83 | 2020-03-18 21:57:49 -0700 | [diff] [blame] | 3139 | static jobject android_media_tv_Tuner_open_descrambler(JNIEnv *env, jobject thiz, jint) { |
shubang | 13f15e0 | 2019-11-04 17:51:02 -0800 | [diff] [blame] | 3140 | sp<JTuner> tuner = getTuner(env, thiz); |
| 3141 | return tuner->openDescrambler(); |
| 3142 | } |
| 3143 | |
shubang | 40454db | 2020-03-30 16:52:29 -0700 | [diff] [blame] | 3144 | static jint android_media_tv_Tuner_descrambler_add_pid( |
shubang | 13f15e0 | 2019-11-04 17:51:02 -0800 | [diff] [blame] | 3145 | JNIEnv *env, jobject descrambler, jint pidType, jint pid, jobject filter) { |
| 3146 | sp<IDescrambler> descramblerSp = getDescrambler(env, descrambler); |
| 3147 | if (descramblerSp == NULL) { |
shubang | 40454db | 2020-03-30 16:52:29 -0700 | [diff] [blame] | 3148 | return (jint) Result::NOT_INITIALIZED; |
shubang | 13f15e0 | 2019-11-04 17:51:02 -0800 | [diff] [blame] | 3149 | } |
shubang | a06cfe5 | 2020-02-24 18:53:41 -0800 | [diff] [blame] | 3150 | sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter(); |
| 3151 | Result result = descramblerSp->addPid(getDemuxPid((int)pidType, (int)pid), iFilterSp); |
shubang | 40454db | 2020-03-30 16:52:29 -0700 | [diff] [blame] | 3152 | return (jint) result; |
shubang | 13f15e0 | 2019-11-04 17:51:02 -0800 | [diff] [blame] | 3153 | } |
| 3154 | |
shubang | 40454db | 2020-03-30 16:52:29 -0700 | [diff] [blame] | 3155 | static jint android_media_tv_Tuner_descrambler_remove_pid( |
shubang | 13f15e0 | 2019-11-04 17:51:02 -0800 | [diff] [blame] | 3156 | JNIEnv *env, jobject descrambler, jint pidType, jint pid, jobject filter) { |
| 3157 | sp<IDescrambler> descramblerSp = getDescrambler(env, descrambler); |
| 3158 | if (descramblerSp == NULL) { |
shubang | 40454db | 2020-03-30 16:52:29 -0700 | [diff] [blame] | 3159 | return (jint) Result::NOT_INITIALIZED; |
shubang | 13f15e0 | 2019-11-04 17:51:02 -0800 | [diff] [blame] | 3160 | } |
shubang | a06cfe5 | 2020-02-24 18:53:41 -0800 | [diff] [blame] | 3161 | sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter(); |
| 3162 | Result result = descramblerSp->removePid(getDemuxPid((int)pidType, (int)pid), iFilterSp); |
shubang | 40454db | 2020-03-30 16:52:29 -0700 | [diff] [blame] | 3163 | return (jint) result; |
shubang | 99c8992 | 2019-12-17 17:33:15 -0800 | [diff] [blame] | 3164 | } |
| 3165 | |
shubang | 40454db | 2020-03-30 16:52:29 -0700 | [diff] [blame] | 3166 | static jint android_media_tv_Tuner_descrambler_set_key_token( |
| 3167 | JNIEnv* env, jobject descrambler, jbyteArray keyToken) { |
| 3168 | sp<IDescrambler> descramblerSp = getDescrambler(env, descrambler); |
| 3169 | if (descramblerSp == NULL) { |
| 3170 | return (jint) Result::NOT_INITIALIZED; |
| 3171 | } |
| 3172 | int size = env->GetArrayLength(keyToken); |
| 3173 | std::vector<uint8_t> v(size); |
| 3174 | env->GetByteArrayRegion(keyToken, 0, size, reinterpret_cast<jbyte*>(&v[0])); |
| 3175 | Result result = descramblerSp->setKeyToken(v); |
| 3176 | return (jint) result; |
shubang | 99c8992 | 2019-12-17 17:33:15 -0800 | [diff] [blame] | 3177 | } |
| 3178 | |
shubang | 40454db | 2020-03-30 16:52:29 -0700 | [diff] [blame] | 3179 | static jint android_media_tv_Tuner_close_descrambler(JNIEnv* env, jobject descrambler) { |
| 3180 | sp<IDescrambler> descramblerSp = getDescrambler(env, descrambler); |
| 3181 | if (descramblerSp == NULL) { |
| 3182 | return (jint) Result::NOT_INITIALIZED; |
| 3183 | } |
| 3184 | Result r = descramblerSp->close(); |
| 3185 | if (r == Result::SUCCESS) { |
| 3186 | descramblerSp->decStrong(descrambler); |
| 3187 | } |
| 3188 | return (jint) r; |
shubang | 13f15e0 | 2019-11-04 17:51:02 -0800 | [diff] [blame] | 3189 | } |
| 3190 | |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3191 | static jobject android_media_tv_Tuner_open_dvr_recorder( |
shubang | 5637a66 | 2020-02-27 18:06:21 -0800 | [diff] [blame] | 3192 | JNIEnv* env, jobject thiz, jlong bufferSize) { |
| 3193 | sp<JTuner> tuner = getTuner(env, thiz); |
| 3194 | return tuner->openDvr(DvrType::RECORD, bufferSize); |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3195 | } |
| 3196 | |
| 3197 | static jobject android_media_tv_Tuner_open_dvr_playback( |
shubang | 5637a66 | 2020-02-27 18:06:21 -0800 | [diff] [blame] | 3198 | JNIEnv* env, jobject thiz, jlong bufferSize) { |
| 3199 | sp<JTuner> tuner = getTuner(env, thiz); |
| 3200 | return tuner->openDvr(DvrType::PLAYBACK, bufferSize); |
shubang | 4a0eddf | 2019-11-08 17:10:18 -0800 | [diff] [blame] | 3201 | } |
| 3202 | |
shubang | c4b4570 | 2020-03-23 18:48:12 -0700 | [diff] [blame] | 3203 | static jobject android_media_tv_Tuner_get_demux_caps(JNIEnv* env, jobject thiz) { |
| 3204 | sp<JTuner> tuner = getTuner(env, thiz); |
| 3205 | return tuner->getDemuxCaps(); |
shubang | 3425893 | 2019-12-27 13:59:23 -0800 | [diff] [blame] | 3206 | } |
| 3207 | |
shubang | 66cc3aa | 2020-04-06 17:10:01 -0700 | [diff] [blame] | 3208 | static jint android_media_tv_Tuner_open_demux(JNIEnv* env, jobject thiz, jint /* handle */) { |
| 3209 | sp<JTuner> tuner = getTuner(env, thiz); |
| 3210 | return (jint) tuner->openDemux(); |
| 3211 | } |
| 3212 | |
shubang | 2f9cab3 | 2020-04-10 18:00:56 -0700 | [diff] [blame] | 3213 | static jint android_media_tv_Tuner_close_tuner(JNIEnv* env, jobject thiz) { |
| 3214 | sp<JTuner> tuner = getTuner(env, thiz); |
| 3215 | return (jint) tuner->close(); |
| 3216 | } |
| 3217 | |
shubang | b3bfffe | 2020-03-26 17:44:31 -0700 | [diff] [blame^] | 3218 | static jint android_media_tv_Tuner_close_demux(JNIEnv* env, jobject thiz, jint /* handle */) { |
| 3219 | sp<JTuner> tuner = getTuner(env, thiz); |
| 3220 | return tuner->closeDemux(); |
| 3221 | } |
| 3222 | |
| 3223 | static jint android_media_tv_Tuner_close_frontend(JNIEnv* env, jobject thiz, jint /* handle */) { |
| 3224 | sp<JTuner> tuner = getTuner(env, thiz); |
| 3225 | return tuner->closeFrontend(); |
| 3226 | } |
| 3227 | |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 3228 | static jint android_media_tv_Tuner_attach_filter(JNIEnv *env, jobject dvr, jobject filter) { |
shubang | ba21a7f | 2019-12-05 16:58:55 -0800 | [diff] [blame] | 3229 | sp<Dvr> dvrSp = getDvr(env, dvr); |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 3230 | if (dvrSp == NULL) { |
| 3231 | return (jint) Result::NOT_INITIALIZED; |
| 3232 | } |
| 3233 | sp<Filter> filterSp = getFilter(env, filter); |
| 3234 | if (filterSp == NULL) { |
| 3235 | return (jint) Result::INVALID_ARGUMENT; |
| 3236 | } |
shubang | ba21a7f | 2019-12-05 16:58:55 -0800 | [diff] [blame] | 3237 | sp<IDvr> iDvrSp = dvrSp->getIDvr(); |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 3238 | sp<IFilter> iFilterSp = filterSp->getIFilter(); |
| 3239 | Result result = iDvrSp->attachFilter(iFilterSp); |
| 3240 | return (jint) result; |
| 3241 | } |
| 3242 | |
| 3243 | static jint android_media_tv_Tuner_detach_filter(JNIEnv *env, jobject dvr, jobject filter) { |
| 3244 | sp<Dvr> dvrSp = getDvr(env, dvr); |
| 3245 | if (dvrSp == NULL) { |
| 3246 | return (jint) Result::NOT_INITIALIZED; |
| 3247 | } |
| 3248 | sp<Filter> filterSp = getFilter(env, filter); |
| 3249 | if (filterSp == NULL) { |
| 3250 | return (jint) Result::INVALID_ARGUMENT; |
| 3251 | } |
| 3252 | sp<IDvr> iDvrSp = dvrSp->getIDvr(); |
| 3253 | sp<IFilter> iFilterSp = filterSp->getIFilter(); |
| 3254 | Result result = iDvrSp->detachFilter(iFilterSp); |
| 3255 | return (jint) result; |
| 3256 | } |
| 3257 | |
| 3258 | static jint android_media_tv_Tuner_configure_dvr(JNIEnv *env, jobject dvr, jobject settings) { |
| 3259 | sp<Dvr> dvrSp = getDvr(env, dvr); |
shubang | 030afb5 | 2019-11-27 16:09:02 -0800 | [diff] [blame] | 3260 | if (dvrSp == NULL) { |
| 3261 | ALOGD("Failed to configure dvr: dvr not found"); |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 3262 | return (int)Result::NOT_INITIALIZED; |
shubang | 030afb5 | 2019-11-27 16:09:02 -0800 | [diff] [blame] | 3263 | } |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 3264 | sp<IDvr> iDvrSp = dvrSp->getIDvr(); |
shubang | ba21a7f | 2019-12-05 16:58:55 -0800 | [diff] [blame] | 3265 | Result result = iDvrSp->configure(getDvrSettings(env, settings)); |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 3266 | if (result != Result::SUCCESS) { |
| 3267 | return (jint) result; |
shubang | ba21a7f | 2019-12-05 16:58:55 -0800 | [diff] [blame] | 3268 | } |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 3269 | MQDescriptorSync<uint8_t> dvrMQDesc; |
| 3270 | Result getQueueDescResult = Result::UNKNOWN_ERROR; |
| 3271 | iDvrSp->getQueueDesc( |
| 3272 | [&](Result r, const MQDescriptorSync<uint8_t>& desc) { |
| 3273 | dvrMQDesc = desc; |
| 3274 | getQueueDescResult = r; |
| 3275 | ALOGD("getDvrQueueDesc"); |
| 3276 | }); |
| 3277 | if (getQueueDescResult == Result::SUCCESS) { |
| 3278 | dvrSp->mDvrMQ = std::make_unique<MQ>(dvrMQDesc, true); |
| 3279 | EventFlag::createEventFlag( |
| 3280 | dvrSp->mDvrMQ->getEventFlagWord(), &(dvrSp->mDvrMQEventFlag)); |
| 3281 | } |
| 3282 | return (jint) getQueueDescResult; |
shubang | 030afb5 | 2019-11-27 16:09:02 -0800 | [diff] [blame] | 3283 | } |
| 3284 | |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 3285 | static jint android_media_tv_Tuner_start_dvr(JNIEnv *env, jobject dvr) { |
| 3286 | sp<Dvr> dvrSp = getDvr(env, dvr); |
shubang | 4a0eddf | 2019-11-08 17:10:18 -0800 | [diff] [blame] | 3287 | if (dvrSp == NULL) { |
| 3288 | ALOGD("Failed to start dvr: dvr not found"); |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 3289 | return (jint) Result::NOT_INITIALIZED; |
shubang | 4a0eddf | 2019-11-08 17:10:18 -0800 | [diff] [blame] | 3290 | } |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 3291 | sp<IDvr> iDvrSp = dvrSp->getIDvr(); |
| 3292 | Result result = iDvrSp->start(); |
| 3293 | return (jint) result; |
shubang | 4a0eddf | 2019-11-08 17:10:18 -0800 | [diff] [blame] | 3294 | } |
| 3295 | |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 3296 | static jint android_media_tv_Tuner_stop_dvr(JNIEnv *env, jobject dvr) { |
| 3297 | sp<Dvr> dvrSp = getDvr(env, dvr); |
shubang | 4a0eddf | 2019-11-08 17:10:18 -0800 | [diff] [blame] | 3298 | if (dvrSp == NULL) { |
| 3299 | ALOGD("Failed to stop dvr: dvr not found"); |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 3300 | return (jint) Result::NOT_INITIALIZED; |
shubang | 4a0eddf | 2019-11-08 17:10:18 -0800 | [diff] [blame] | 3301 | } |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 3302 | sp<IDvr> iDvrSp = dvrSp->getIDvr(); |
| 3303 | Result result = iDvrSp->stop(); |
| 3304 | return (jint) result; |
shubang | 4a0eddf | 2019-11-08 17:10:18 -0800 | [diff] [blame] | 3305 | } |
| 3306 | |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 3307 | static jint android_media_tv_Tuner_flush_dvr(JNIEnv *env, jobject dvr) { |
| 3308 | sp<Dvr> dvrSp = getDvr(env, dvr); |
shubang | 4a0eddf | 2019-11-08 17:10:18 -0800 | [diff] [blame] | 3309 | if (dvrSp == NULL) { |
| 3310 | ALOGD("Failed to flush dvr: dvr not found"); |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 3311 | return (jint) Result::NOT_INITIALIZED; |
shubang | 4a0eddf | 2019-11-08 17:10:18 -0800 | [diff] [blame] | 3312 | } |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 3313 | sp<IDvr> iDvrSp = dvrSp->getIDvr(); |
| 3314 | Result result = iDvrSp->flush(); |
| 3315 | return (jint) result; |
shubang | 793e570 | 2019-12-26 15:15:46 -0800 | [diff] [blame] | 3316 | } |
| 3317 | |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 3318 | static jint android_media_tv_Tuner_close_dvr(JNIEnv* env, jobject dvr) { |
| 3319 | sp<Dvr> dvrSp = getDvr(env, dvr); |
| 3320 | if (dvrSp == NULL) { |
| 3321 | ALOGD("Failed to close dvr: dvr not found"); |
| 3322 | return (jint) Result::NOT_INITIALIZED; |
| 3323 | } |
| 3324 | return dvrSp->close(); |
shubang | 4a0eddf | 2019-11-08 17:10:18 -0800 | [diff] [blame] | 3325 | } |
| 3326 | |
shubang | 1c1144e | 2020-03-03 18:00:17 -0800 | [diff] [blame] | 3327 | static sp<Lnb> getLnb(JNIEnv *env, jobject lnb) { |
| 3328 | return (Lnb *)env->GetLongField(lnb, gFields.lnbContext); |
shubang | 847fc0a | 2019-12-26 16:54:10 -0800 | [diff] [blame] | 3329 | } |
| 3330 | |
shubang | 1c1144e | 2020-03-03 18:00:17 -0800 | [diff] [blame] | 3331 | static jint android_media_tv_Tuner_lnb_set_voltage(JNIEnv* env, jobject lnb, jint voltage) { |
| 3332 | sp<ILnb> iLnbSp = getLnb(env, lnb)->getILnb(); |
| 3333 | Result r = iLnbSp->setVoltage(static_cast<LnbVoltage>(voltage)); |
| 3334 | return (jint) r; |
shubang | 847fc0a | 2019-12-26 16:54:10 -0800 | [diff] [blame] | 3335 | } |
| 3336 | |
shubang | 1c1144e | 2020-03-03 18:00:17 -0800 | [diff] [blame] | 3337 | static int android_media_tv_Tuner_lnb_set_tone(JNIEnv* env, jobject lnb, jint tone) { |
| 3338 | sp<ILnb> iLnbSp = getLnb(env, lnb)->getILnb(); |
| 3339 | Result r = iLnbSp->setTone(static_cast<LnbTone>(tone)); |
| 3340 | return (jint) r; |
shubang | 847fc0a | 2019-12-26 16:54:10 -0800 | [diff] [blame] | 3341 | } |
| 3342 | |
shubang | 1c1144e | 2020-03-03 18:00:17 -0800 | [diff] [blame] | 3343 | static int android_media_tv_Tuner_lnb_set_position(JNIEnv* env, jobject lnb, jint position) { |
| 3344 | sp<ILnb> iLnbSp = getLnb(env, lnb)->getILnb(); |
| 3345 | Result r = iLnbSp->setSatellitePosition(static_cast<LnbPosition>(position)); |
| 3346 | return (jint) r; |
| 3347 | } |
| 3348 | |
| 3349 | static int android_media_tv_Tuner_lnb_send_diseqc_msg(JNIEnv* env, jobject lnb, jbyteArray msg) { |
| 3350 | sp<ILnb> iLnbSp = getLnb(env, lnb)->getILnb(); |
| 3351 | int size = env->GetArrayLength(msg); |
| 3352 | std::vector<uint8_t> v(size); |
| 3353 | env->GetByteArrayRegion(msg, 0, size, reinterpret_cast<jbyte*>(&v[0])); |
| 3354 | Result r = iLnbSp->sendDiseqcMessage(v); |
| 3355 | return (jint) r; |
shubang | 847fc0a | 2019-12-26 16:54:10 -0800 | [diff] [blame] | 3356 | } |
| 3357 | |
shubang | d295be0 | 2020-03-27 17:08:11 -0700 | [diff] [blame] | 3358 | static int android_media_tv_Tuner_close_lnb(JNIEnv* env, jobject lnb) { |
| 3359 | sp<Lnb> lnbSp = getLnb(env, lnb); |
| 3360 | Result r = lnbSp->getILnb()->close(); |
| 3361 | if (r == Result::SUCCESS) { |
| 3362 | lnbSp->decStrong(lnb); |
| 3363 | env->SetLongField(lnb, gFields.lnbContext, 0); |
| 3364 | } |
| 3365 | return (jint) r; |
shubang | 847fc0a | 2019-12-26 16:54:10 -0800 | [diff] [blame] | 3366 | } |
| 3367 | |
shubang | ba21a7f | 2019-12-05 16:58:55 -0800 | [diff] [blame] | 3368 | static void android_media_tv_Tuner_dvr_set_fd(JNIEnv *env, jobject dvr, jobject jfd) { |
| 3369 | sp<Dvr> dvrSp = getDvr(env, dvr); |
| 3370 | if (dvrSp == NULL) { |
| 3371 | ALOGD("Failed to set FD for dvr: dvr not found"); |
| 3372 | } |
| 3373 | dvrSp->mFd = jniGetFDFromFileDescriptor(env, jfd); |
| 3374 | ALOGD("set fd = %d", dvrSp->mFd); |
| 3375 | } |
| 3376 | |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3377 | static jlong android_media_tv_Tuner_read_dvr(JNIEnv *env, jobject dvr, jlong size) { |
shubang | ba21a7f | 2019-12-05 16:58:55 -0800 | [diff] [blame] | 3378 | sp<Dvr> dvrSp = getDvr(env, dvr); |
| 3379 | if (dvrSp == NULL) { |
| 3380 | ALOGD("Failed to read dvr: dvr not found"); |
| 3381 | } |
| 3382 | |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3383 | long available = dvrSp->mDvrMQ->availableToWrite(); |
| 3384 | long write = std::min((long) size, available); |
shubang | ba21a7f | 2019-12-05 16:58:55 -0800 | [diff] [blame] | 3385 | |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 3386 | MQ::MemTransaction tx; |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3387 | long ret = 0; |
shubang | ba21a7f | 2019-12-05 16:58:55 -0800 | [diff] [blame] | 3388 | if (dvrSp->mDvrMQ->beginWrite(write, &tx)) { |
| 3389 | auto first = tx.getFirstRegion(); |
| 3390 | auto data = first.getAddress(); |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3391 | long length = first.getLength(); |
| 3392 | long firstToWrite = std::min(length, write); |
shubang | ba21a7f | 2019-12-05 16:58:55 -0800 | [diff] [blame] | 3393 | ret = read(dvrSp->mFd, data, firstToWrite); |
| 3394 | if (ret < firstToWrite) { |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3395 | ALOGW("[DVR] file to MQ, first region: %ld bytes to write, but %ld bytes written", |
shubang | ba21a7f | 2019-12-05 16:58:55 -0800 | [diff] [blame] | 3396 | firstToWrite, ret); |
| 3397 | } else if (firstToWrite < write) { |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3398 | ALOGD("[DVR] write second region: %ld bytes written, %ld bytes in total", ret, write); |
shubang | ba21a7f | 2019-12-05 16:58:55 -0800 | [diff] [blame] | 3399 | auto second = tx.getSecondRegion(); |
| 3400 | data = second.getAddress(); |
| 3401 | length = second.getLength(); |
| 3402 | int secondToWrite = std::min(length, write - firstToWrite); |
| 3403 | ret += read(dvrSp->mFd, data, secondToWrite); |
| 3404 | } |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3405 | ALOGD("[DVR] file to MQ: %ld bytes need to be written, %ld bytes written", write, ret); |
shubang | ba21a7f | 2019-12-05 16:58:55 -0800 | [diff] [blame] | 3406 | if (!dvrSp->mDvrMQ->commitWrite(ret)) { |
| 3407 | ALOGE("[DVR] Error: failed to commit write!"); |
| 3408 | } |
| 3409 | |
| 3410 | } else { |
| 3411 | ALOGE("dvrMq.beginWrite failed"); |
| 3412 | } |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3413 | return (jlong) ret; |
shubang | ba21a7f | 2019-12-05 16:58:55 -0800 | [diff] [blame] | 3414 | } |
| 3415 | |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3416 | static jlong android_media_tv_Tuner_read_dvr_from_array( |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 3417 | JNIEnv* env, jobject dvr, jbyteArray buffer, jlong offset, jlong size) { |
| 3418 | sp<Dvr> dvrSp = getDvr(env, dvr); |
| 3419 | if (dvrSp == NULL) { |
| 3420 | ALOGW("Failed to read dvr: dvr not found"); |
| 3421 | return 0; |
| 3422 | } |
| 3423 | if (dvrSp->mDvrMQ == NULL) { |
| 3424 | ALOGW("Failed to read dvr: dvr not configured"); |
| 3425 | return 0; |
| 3426 | } |
| 3427 | |
| 3428 | jlong available = dvrSp->mDvrMQ->availableToWrite(); |
| 3429 | size = std::min(size, available); |
| 3430 | |
| 3431 | jboolean isCopy; |
| 3432 | jbyte *src = env->GetByteArrayElements(buffer, &isCopy); |
| 3433 | if (src == nullptr) { |
| 3434 | ALOGD("Failed to GetByteArrayElements"); |
| 3435 | return 0; |
| 3436 | } |
| 3437 | |
| 3438 | if (dvrSp->mDvrMQ->write(reinterpret_cast<unsigned char*>(src) + offset, size)) { |
| 3439 | env->ReleaseByteArrayElements(buffer, src, 0); |
| 3440 | dvrSp->mDvrMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED)); |
| 3441 | } else { |
| 3442 | ALOGD("Failed to write FMQ"); |
| 3443 | env->ReleaseByteArrayElements(buffer, src, 0); |
| 3444 | return 0; |
| 3445 | } |
| 3446 | return size; |
shubang | ba21a7f | 2019-12-05 16:58:55 -0800 | [diff] [blame] | 3447 | } |
| 3448 | |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3449 | static jlong android_media_tv_Tuner_write_dvr(JNIEnv *env, jobject dvr, jlong size) { |
shubang | 5f4ea35 | 2019-12-09 15:12:10 -0800 | [diff] [blame] | 3450 | sp<Dvr> dvrSp = getDvr(env, dvr); |
| 3451 | if (dvrSp == NULL) { |
| 3452 | ALOGW("Failed to write dvr: dvr not found"); |
| 3453 | return 0; |
| 3454 | } |
| 3455 | |
| 3456 | if (dvrSp->mDvrMQ == NULL) { |
| 3457 | ALOGW("Failed to write dvr: dvr not configured"); |
| 3458 | return 0; |
| 3459 | } |
| 3460 | |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 3461 | MQ& dvrMq = dvrSp->getDvrMQ(); |
shubang | 5f4ea35 | 2019-12-09 15:12:10 -0800 | [diff] [blame] | 3462 | |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3463 | long available = dvrMq.availableToRead(); |
| 3464 | long toRead = std::min((long) size, available); |
shubang | 5f4ea35 | 2019-12-09 15:12:10 -0800 | [diff] [blame] | 3465 | |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3466 | long ret = 0; |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 3467 | MQ::MemTransaction tx; |
shubang | 5f4ea35 | 2019-12-09 15:12:10 -0800 | [diff] [blame] | 3468 | if (dvrMq.beginRead(toRead, &tx)) { |
| 3469 | auto first = tx.getFirstRegion(); |
| 3470 | auto data = first.getAddress(); |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3471 | long length = first.getLength(); |
| 3472 | long firstToRead = std::min(length, toRead); |
shubang | 5f4ea35 | 2019-12-09 15:12:10 -0800 | [diff] [blame] | 3473 | ret = write(dvrSp->mFd, data, firstToRead); |
| 3474 | if (ret < firstToRead) { |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3475 | ALOGW("[DVR] MQ to file: %ld bytes read, but %ld bytes written", firstToRead, ret); |
shubang | 5f4ea35 | 2019-12-09 15:12:10 -0800 | [diff] [blame] | 3476 | } else if (firstToRead < toRead) { |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3477 | ALOGD("[DVR] read second region: %ld bytes read, %ld bytes in total", ret, toRead); |
shubang | 5f4ea35 | 2019-12-09 15:12:10 -0800 | [diff] [blame] | 3478 | auto second = tx.getSecondRegion(); |
| 3479 | data = second.getAddress(); |
| 3480 | length = second.getLength(); |
| 3481 | int secondToRead = toRead - firstToRead; |
| 3482 | ret += write(dvrSp->mFd, data, secondToRead); |
| 3483 | } |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3484 | ALOGD("[DVR] MQ to file: %ld bytes to be read, %ld bytes written", toRead, ret); |
shubang | 5f4ea35 | 2019-12-09 15:12:10 -0800 | [diff] [blame] | 3485 | if (!dvrMq.commitRead(ret)) { |
| 3486 | ALOGE("[DVR] Error: failed to commit read!"); |
| 3487 | } |
| 3488 | |
| 3489 | } else { |
| 3490 | ALOGE("dvrMq.beginRead failed"); |
| 3491 | } |
| 3492 | |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3493 | return (jlong) ret; |
shubang | 5f4ea35 | 2019-12-09 15:12:10 -0800 | [diff] [blame] | 3494 | } |
| 3495 | |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3496 | static jlong android_media_tv_Tuner_write_dvr_to_array( |
shubang | 431e561 | 2020-03-30 21:24:56 -0700 | [diff] [blame] | 3497 | JNIEnv *env, jobject dvr, jbyteArray buffer, jlong offset, jlong size) { |
| 3498 | sp<Dvr> dvrSp = getDvr(env, dvr); |
| 3499 | if (dvrSp == NULL) { |
| 3500 | ALOGW("Failed to write dvr: dvr not found"); |
| 3501 | return 0; |
| 3502 | } |
| 3503 | if (dvrSp->mDvrMQ == NULL) { |
| 3504 | ALOGW("Failed to write dvr: dvr not configured"); |
| 3505 | return 0; |
| 3506 | } |
| 3507 | return copyData(env, dvrSp->mDvrMQ, dvrSp->mDvrMQEventFlag, buffer, offset, size); |
shubang | 5f4ea35 | 2019-12-09 15:12:10 -0800 | [diff] [blame] | 3508 | } |
shubang | ba21a7f | 2019-12-05 16:58:55 -0800 | [diff] [blame] | 3509 | |
shubang | d097790 | 2019-11-07 18:58:43 -0800 | [diff] [blame] | 3510 | static const JNINativeMethod gTunerMethods[] = { |
shubang | 8ab43b1 | 2019-10-18 15:55:55 -0700 | [diff] [blame] | 3511 | { "nativeInit", "()V", (void *)android_media_tv_Tuner_native_init }, |
| 3512 | { "nativeSetup", "()V", (void *)android_media_tv_Tuner_native_setup }, |
shubang | 7e849b0 | 2019-10-18 19:36:25 -0700 | [diff] [blame] | 3513 | { "nativeGetFrontendIds", "()Ljava/util/List;", |
| 3514 | (void *)android_media_tv_Tuner_get_frontend_ids }, |
shubang | c18cc10 | 2020-03-12 16:28:45 -0700 | [diff] [blame] | 3515 | { "nativeOpenFrontendByHandle", "(I)Landroid/media/tv/tuner/Tuner$Frontend;", |
| 3516 | (void *)android_media_tv_Tuner_open_frontend_by_handle }, |
shubang | 2f9cab3 | 2020-04-10 18:00:56 -0700 | [diff] [blame] | 3517 | { "nativeCloseFrontendByHandle", "(I)I", |
| 3518 | (void *)android_media_tv_Tuner_close_frontend_by_handle }, |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3519 | { "nativeTune", "(ILandroid/media/tv/tuner/frontend/FrontendSettings;)I", |
shubang | 74bfd48 | 2019-10-29 19:10:22 -0700 | [diff] [blame] | 3520 | (void *)android_media_tv_Tuner_tune }, |
shubang | e65b686 | 2019-12-17 15:43:35 -0800 | [diff] [blame] | 3521 | { "nativeStopTune", "()I", (void *)android_media_tv_Tuner_stop_tune }, |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3522 | { "nativeScan", "(ILandroid/media/tv/tuner/frontend/FrontendSettings;I)I", |
shubang | d5b845f | 2019-12-11 15:29:09 -0800 | [diff] [blame] | 3523 | (void *)android_media_tv_Tuner_scan }, |
shubang | 793e570 | 2019-12-26 15:15:46 -0800 | [diff] [blame] | 3524 | { "nativeStopScan", "()I", (void *)android_media_tv_Tuner_stop_scan }, |
shubang | e65b686 | 2019-12-17 15:43:35 -0800 | [diff] [blame] | 3525 | { "nativeSetLnb", "(I)I", (void *)android_media_tv_Tuner_set_lnb }, |
| 3526 | { "nativeSetLna", "(Z)I", (void *)android_media_tv_Tuner_set_lna }, |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3527 | { "nativeGetFrontendStatus", "([I)Landroid/media/tv/tuner/frontend/FrontendStatus;", |
shubang | 1512ec1 | 2019-12-23 18:22:42 -0800 | [diff] [blame] | 3528 | (void *)android_media_tv_Tuner_get_frontend_status }, |
shubang | bee7346 | 2020-02-07 17:48:02 -0800 | [diff] [blame] | 3529 | { "nativeGetAvSyncHwId", "(Landroid/media/tv/tuner/filter/Filter;)Ljava/lang/Integer;", |
| 3530 | (void *)android_media_tv_Tuner_get_av_sync_hw_id }, |
| 3531 | { "nativeGetAvSyncTime", "(I)Ljava/lang/Long;", |
| 3532 | (void *)android_media_tv_Tuner_get_av_sync_time }, |
shubang | 7343fee | 2019-12-27 12:02:08 -0800 | [diff] [blame] | 3533 | { "nativeConnectCiCam", "(I)I", (void *)android_media_tv_Tuner_connect_cicam }, |
| 3534 | { "nativeDisconnectCiCam", "()I", (void *)android_media_tv_Tuner_disconnect_cicam }, |
shubang | deb067c | 2020-01-27 13:21:55 -0800 | [diff] [blame] | 3535 | { "nativeGetFrontendInfo", "(I)Landroid/media/tv/tuner/frontend/FrontendInfo;", |
shubang | 95c1f75 | 2019-12-27 16:29:48 -0800 | [diff] [blame] | 3536 | (void *)android_media_tv_Tuner_get_frontend_info }, |
shubang | deb067c | 2020-01-27 13:21:55 -0800 | [diff] [blame] | 3537 | { "nativeOpenFilter", "(IIJ)Landroid/media/tv/tuner/filter/Filter;", |
shubang | 6f473d6 | 2019-11-01 15:42:21 -0700 | [diff] [blame] | 3538 | (void *)android_media_tv_Tuner_open_filter }, |
shubang | deb067c | 2020-01-27 13:21:55 -0800 | [diff] [blame] | 3539 | { "nativeOpenTimeFilter", "()Landroid/media/tv/tuner/filter/TimeFilter;", |
shubang | 4347e2e | 2019-12-13 17:20:40 -0800 | [diff] [blame] | 3540 | (void *)android_media_tv_Tuner_open_time_filter }, |
shubang | 0dc8394 | 2020-04-02 17:19:31 -0700 | [diff] [blame] | 3541 | { "nativeGetLnbIds", "()[I", (void *)android_media_tv_Tuner_get_lnb_ids }, |
shubang | c18cc10 | 2020-03-12 16:28:45 -0700 | [diff] [blame] | 3542 | { "nativeOpenLnbByHandle", "(I)Landroid/media/tv/tuner/Lnb;", |
| 3543 | (void *)android_media_tv_Tuner_open_lnb_by_handle }, |
shubang | 757602f | 2020-03-06 15:23:41 -0800 | [diff] [blame] | 3544 | { "nativeOpenLnbByName", "(Ljava/lang/String;)Landroid/media/tv/tuner/Lnb;", |
| 3545 | (void *)android_media_tv_Tuner_open_lnb_by_name }, |
shubang | f159a83 | 2020-03-18 21:57:49 -0700 | [diff] [blame] | 3546 | { "nativeOpenDescramblerByHandle", "(I)Landroid/media/tv/tuner/Descrambler;", |
shubang | 13f15e0 | 2019-11-04 17:51:02 -0800 | [diff] [blame] | 3547 | (void *)android_media_tv_Tuner_open_descrambler }, |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3548 | { "nativeOpenDvrRecorder", "(J)Landroid/media/tv/tuner/dvr/DvrRecorder;", |
| 3549 | (void *)android_media_tv_Tuner_open_dvr_recorder }, |
| 3550 | { "nativeOpenDvrPlayback", "(J)Landroid/media/tv/tuner/dvr/DvrPlayback;", |
| 3551 | (void *)android_media_tv_Tuner_open_dvr_playback }, |
shubang | 3425893 | 2019-12-27 13:59:23 -0800 | [diff] [blame] | 3552 | { "nativeGetDemuxCapabilities", "()Landroid/media/tv/tuner/DemuxCapabilities;", |
| 3553 | (void *)android_media_tv_Tuner_get_demux_caps }, |
shubang | 66cc3aa | 2020-04-06 17:10:01 -0700 | [diff] [blame] | 3554 | { "nativeOpenDemuxByhandle", "(I)I", (void *)android_media_tv_Tuner_open_demux }, |
shubang | b3bfffe | 2020-03-26 17:44:31 -0700 | [diff] [blame^] | 3555 | { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_tuner }, |
| 3556 | { "nativeCloseFrontend", "(I)I", (void *)android_media_tv_Tuner_close_frontend }, |
| 3557 | { "nativeCloseDemux", "(I)I", (void *)android_media_tv_Tuner_close_demux }, |
shubang | 8ab43b1 | 2019-10-18 15:55:55 -0700 | [diff] [blame] | 3558 | }; |
| 3559 | |
shubang | d097790 | 2019-11-07 18:58:43 -0800 | [diff] [blame] | 3560 | static const JNINativeMethod gFilterMethods[] = { |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3561 | { "nativeConfigureFilter", "(IILandroid/media/tv/tuner/filter/FilterConfiguration;)I", |
shubang | 75c8708 | 2019-11-15 11:26:56 -0800 | [diff] [blame] | 3562 | (void *)android_media_tv_Tuner_configure_filter }, |
shubang | 793e570 | 2019-12-26 15:15:46 -0800 | [diff] [blame] | 3563 | { "nativeGetId", "()I", (void *)android_media_tv_Tuner_get_filter_id }, |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3564 | { "nativeSetDataSource", "(Landroid/media/tv/tuner/filter/Filter;)I", |
shubang | 793e570 | 2019-12-26 15:15:46 -0800 | [diff] [blame] | 3565 | (void *)android_media_tv_Tuner_set_filter_data_source }, |
| 3566 | { "nativeStartFilter", "()I", (void *)android_media_tv_Tuner_start_filter }, |
| 3567 | { "nativeStopFilter", "()I", (void *)android_media_tv_Tuner_stop_filter }, |
| 3568 | { "nativeFlushFilter", "()I", (void *)android_media_tv_Tuner_flush_filter }, |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3569 | { "nativeRead", "([BJJ)I", (void *)android_media_tv_Tuner_read_filter_fmq }, |
Amy | 1b301f4 | 2020-01-02 11:07:56 -0800 | [diff] [blame] | 3570 | { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_filter }, |
shubang | d097790 | 2019-11-07 18:58:43 -0800 | [diff] [blame] | 3571 | }; |
| 3572 | |
shubang | 4347e2e | 2019-12-13 17:20:40 -0800 | [diff] [blame] | 3573 | static const JNINativeMethod gTimeFilterMethods[] = { |
shubang | deb067c | 2020-01-27 13:21:55 -0800 | [diff] [blame] | 3574 | { "nativeSetTimestamp", "(J)I", (void *)android_media_tv_Tuner_time_filter_set_timestamp }, |
| 3575 | { "nativeClearTimestamp", "()I", (void *)android_media_tv_Tuner_time_filter_clear_timestamp }, |
| 3576 | { "nativeGetTimestamp", "()Ljava/lang/Long;", |
shubang | 4347e2e | 2019-12-13 17:20:40 -0800 | [diff] [blame] | 3577 | (void *)android_media_tv_Tuner_time_filter_get_timestamp }, |
| 3578 | { "nativeGetSourceTime", "()Ljava/lang/Long;", |
| 3579 | (void *)android_media_tv_Tuner_time_filter_get_source_time }, |
| 3580 | { "nativeClose", "()I", (void *)android_media_tv_Tuner_time_filter_close }, |
| 3581 | }; |
| 3582 | |
shubang | 13f15e0 | 2019-11-04 17:51:02 -0800 | [diff] [blame] | 3583 | static const JNINativeMethod gDescramblerMethods[] = { |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3584 | { "nativeAddPid", "(IILandroid/media/tv/tuner/filter/Filter;)I", |
shubang | 40454db | 2020-03-30 16:52:29 -0700 | [diff] [blame] | 3585 | (void *)android_media_tv_Tuner_descrambler_add_pid }, |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3586 | { "nativeRemovePid", "(IILandroid/media/tv/tuner/filter/Filter;)I", |
shubang | 40454db | 2020-03-30 16:52:29 -0700 | [diff] [blame] | 3587 | (void *)android_media_tv_Tuner_descrambler_remove_pid }, |
| 3588 | { "nativeSetKeyToken", "([B)I", (void *)android_media_tv_Tuner_descrambler_set_key_token }, |
Amy | 1b301f4 | 2020-01-02 11:07:56 -0800 | [diff] [blame] | 3589 | { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_descrambler }, |
shubang | 13f15e0 | 2019-11-04 17:51:02 -0800 | [diff] [blame] | 3590 | }; |
| 3591 | |
shubang | 5637a66 | 2020-02-27 18:06:21 -0800 | [diff] [blame] | 3592 | static const JNINativeMethod gDvrRecorderMethods[] = { |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3593 | { "nativeAttachFilter", "(Landroid/media/tv/tuner/filter/Filter;)I", |
shubang | 4a0eddf | 2019-11-08 17:10:18 -0800 | [diff] [blame] | 3594 | (void *)android_media_tv_Tuner_attach_filter }, |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3595 | { "nativeDetachFilter", "(Landroid/media/tv/tuner/filter/Filter;)I", |
shubang | 4a0eddf | 2019-11-08 17:10:18 -0800 | [diff] [blame] | 3596 | (void *)android_media_tv_Tuner_detach_filter }, |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3597 | { "nativeConfigureDvr", "(Landroid/media/tv/tuner/dvr/DvrSettings;)I", |
shubang | 030afb5 | 2019-11-27 16:09:02 -0800 | [diff] [blame] | 3598 | (void *)android_media_tv_Tuner_configure_dvr }, |
shubang | 793e570 | 2019-12-26 15:15:46 -0800 | [diff] [blame] | 3599 | { "nativeStartDvr", "()I", (void *)android_media_tv_Tuner_start_dvr }, |
| 3600 | { "nativeStopDvr", "()I", (void *)android_media_tv_Tuner_stop_dvr }, |
| 3601 | { "nativeFlushDvr", "()I", (void *)android_media_tv_Tuner_flush_dvr }, |
| 3602 | { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_dvr }, |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3603 | { "nativeSetFileDescriptor", "(I)V", (void *)android_media_tv_Tuner_dvr_set_fd }, |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3604 | { "nativeWrite", "(J)J", (void *)android_media_tv_Tuner_write_dvr }, |
| 3605 | { "nativeWrite", "([BJJ)J", (void *)android_media_tv_Tuner_write_dvr_to_array }, |
| 3606 | }; |
| 3607 | |
| 3608 | static const JNINativeMethod gDvrPlaybackMethods[] = { |
shubang | 5637a66 | 2020-02-27 18:06:21 -0800 | [diff] [blame] | 3609 | { "nativeAttachFilter", "(Landroid/media/tv/tuner/filter/Filter;)I", |
| 3610 | (void *)android_media_tv_Tuner_attach_filter }, |
| 3611 | { "nativeDetachFilter", "(Landroid/media/tv/tuner/filter/Filter;)I", |
| 3612 | (void *)android_media_tv_Tuner_detach_filter }, |
| 3613 | { "nativeConfigureDvr", "(Landroid/media/tv/tuner/dvr/DvrSettings;)I", |
| 3614 | (void *)android_media_tv_Tuner_configure_dvr }, |
| 3615 | { "nativeStartDvr", "()I", (void *)android_media_tv_Tuner_start_dvr }, |
| 3616 | { "nativeStopDvr", "()I", (void *)android_media_tv_Tuner_stop_dvr }, |
| 3617 | { "nativeFlushDvr", "()I", (void *)android_media_tv_Tuner_flush_dvr }, |
| 3618 | { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_dvr }, |
| 3619 | { "nativeSetFileDescriptor", "(I)V", (void *)android_media_tv_Tuner_dvr_set_fd }, |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3620 | { "nativeRead", "(J)J", (void *)android_media_tv_Tuner_read_dvr }, |
| 3621 | { "nativeRead", "([BJJ)J", (void *)android_media_tv_Tuner_read_dvr_from_array }, |
shubang | 4a0eddf | 2019-11-08 17:10:18 -0800 | [diff] [blame] | 3622 | }; |
| 3623 | |
shubang | 847fc0a | 2019-12-26 16:54:10 -0800 | [diff] [blame] | 3624 | static const JNINativeMethod gLnbMethods[] = { |
| 3625 | { "nativeSetVoltage", "(I)I", (void *)android_media_tv_Tuner_lnb_set_voltage }, |
| 3626 | { "nativeSetTone", "(I)I", (void *)android_media_tv_Tuner_lnb_set_tone }, |
| 3627 | { "nativeSetSatellitePosition", "(I)I", (void *)android_media_tv_Tuner_lnb_set_position }, |
| 3628 | { "nativeSendDiseqcMessage", "([B)I", (void *)android_media_tv_Tuner_lnb_send_diseqc_msg }, |
| 3629 | { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_lnb }, |
| 3630 | }; |
| 3631 | |
shubang | d097790 | 2019-11-07 18:58:43 -0800 | [diff] [blame] | 3632 | static bool register_android_media_tv_Tuner(JNIEnv *env) { |
| 3633 | if (AndroidRuntime::registerNativeMethods( |
| 3634 | env, "android/media/tv/tuner/Tuner", gTunerMethods, NELEM(gTunerMethods)) != JNI_OK) { |
| 3635 | ALOGE("Failed to register tuner native methods"); |
| 3636 | return false; |
| 3637 | } |
| 3638 | if (AndroidRuntime::registerNativeMethods( |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3639 | env, "android/media/tv/tuner/filter/Filter", |
shubang | d097790 | 2019-11-07 18:58:43 -0800 | [diff] [blame] | 3640 | gFilterMethods, |
| 3641 | NELEM(gFilterMethods)) != JNI_OK) { |
| 3642 | ALOGE("Failed to register filter native methods"); |
| 3643 | return false; |
| 3644 | } |
shubang | 13f15e0 | 2019-11-04 17:51:02 -0800 | [diff] [blame] | 3645 | if (AndroidRuntime::registerNativeMethods( |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3646 | env, "android/media/tv/tuner/filter/TimeFilter", |
shubang | 4347e2e | 2019-12-13 17:20:40 -0800 | [diff] [blame] | 3647 | gTimeFilterMethods, |
| 3648 | NELEM(gTimeFilterMethods)) != JNI_OK) { |
| 3649 | ALOGE("Failed to register time filter native methods"); |
| 3650 | return false; |
| 3651 | } |
| 3652 | if (AndroidRuntime::registerNativeMethods( |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3653 | env, "android/media/tv/tuner/Descrambler", |
shubang | 13f15e0 | 2019-11-04 17:51:02 -0800 | [diff] [blame] | 3654 | gDescramblerMethods, |
| 3655 | NELEM(gDescramblerMethods)) != JNI_OK) { |
| 3656 | ALOGE("Failed to register descrambler native methods"); |
| 3657 | return false; |
| 3658 | } |
shubang | 4a0eddf | 2019-11-08 17:10:18 -0800 | [diff] [blame] | 3659 | if (AndroidRuntime::registerNativeMethods( |
shubang | d351b82 | 2020-01-22 17:29:18 -0800 | [diff] [blame] | 3660 | env, "android/media/tv/tuner/dvr/DvrRecorder", |
| 3661 | gDvrRecorderMethods, |
| 3662 | NELEM(gDvrRecorderMethods)) != JNI_OK) { |
| 3663 | ALOGE("Failed to register dvr recorder native methods"); |
| 3664 | return false; |
| 3665 | } |
| 3666 | if (AndroidRuntime::registerNativeMethods( |
| 3667 | env, "android/media/tv/tuner/dvr/DvrPlayback", |
| 3668 | gDvrPlaybackMethods, |
| 3669 | NELEM(gDvrPlaybackMethods)) != JNI_OK) { |
| 3670 | ALOGE("Failed to register dvr playback native methods"); |
| 3671 | return false; |
| 3672 | } |
| 3673 | if (AndroidRuntime::registerNativeMethods( |
| 3674 | env, "android/media/tv/tuner/Lnb", |
shubang | 847fc0a | 2019-12-26 16:54:10 -0800 | [diff] [blame] | 3675 | gLnbMethods, |
| 3676 | NELEM(gLnbMethods)) != JNI_OK) { |
| 3677 | ALOGE("Failed to register lnb native methods"); |
| 3678 | return false; |
| 3679 | } |
shubang | d097790 | 2019-11-07 18:58:43 -0800 | [diff] [blame] | 3680 | return true; |
shubang | 8ab43b1 | 2019-10-18 15:55:55 -0700 | [diff] [blame] | 3681 | } |
| 3682 | |
| 3683 | jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) |
| 3684 | { |
| 3685 | JNIEnv* env = NULL; |
| 3686 | jint result = -1; |
| 3687 | |
| 3688 | if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { |
| 3689 | ALOGE("ERROR: GetEnv failed\n"); |
| 3690 | return result; |
| 3691 | } |
| 3692 | assert(env != NULL); |
| 3693 | |
shubang | d097790 | 2019-11-07 18:58:43 -0800 | [diff] [blame] | 3694 | if (!register_android_media_tv_Tuner(env)) { |
shubang | 8ab43b1 | 2019-10-18 15:55:55 -0700 | [diff] [blame] | 3695 | ALOGE("ERROR: Tuner native registration failed\n"); |
| 3696 | return result; |
| 3697 | } |
| 3698 | return JNI_VERSION_1_4; |
| 3699 | } |