| Amy Zhang | bf68a16 | 2020-11-23 17:42:40 -0800 | [diff] [blame] | 1 | /* | 
|  | 2 | * Copyright 2020 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 "TunerClient" | 
|  | 18 |  | 
|  | 19 | #include <android/binder_manager.h> | 
|  | 20 | #include <android-base/logging.h> | 
|  | 21 | #include <utils/Log.h> | 
|  | 22 |  | 
|  | 23 | #include "TunerClient.h" | 
|  | 24 |  | 
|  | 25 | using ::android::hardware::tv::tuner::V1_0::FrontendId; | 
|  | 26 | using ::android::hardware::tv::tuner::V1_0::FrontendType; | 
|  | 27 |  | 
|  | 28 | namespace android { | 
|  | 29 |  | 
|  | 30 | sp<ITuner> TunerClient::mTuner; | 
|  | 31 | sp<::android::hardware::tv::tuner::V1_1::ITuner> TunerClient::mTuner_1_1; | 
|  | 32 | shared_ptr<ITunerService> TunerClient::mTunerService; | 
|  | 33 | int TunerClient::mTunerVersion; | 
|  | 34 |  | 
|  | 35 | /////////////// TunerClient /////////////////////// | 
|  | 36 |  | 
|  | 37 | TunerClient::TunerClient() { | 
|  | 38 | // Get HIDL Tuner in migration stage. | 
|  | 39 | getHidlTuner(); | 
|  | 40 | // Connect with Tuner Service. | 
|  | 41 | ::ndk::SpAIBinder binder(AServiceManager_getService("media.tuner")); | 
|  | 42 | mTunerService = ITunerService::fromBinder(binder); | 
| Amy Zhang | 9a9ed60 | 2020-12-07 16:37:33 -0800 | [diff] [blame] | 43 | // TODO: Remove after JNI migration is done. | 
|  | 44 | mTunerService = NULL; | 
| Amy Zhang | bf68a16 | 2020-11-23 17:42:40 -0800 | [diff] [blame] | 45 | if (mTunerService == NULL) { | 
|  | 46 | ALOGE("Failed to get tuner service"); | 
|  | 47 | } | 
|  | 48 | } | 
|  | 49 |  | 
|  | 50 | TunerClient::~TunerClient() { | 
|  | 51 | mTuner = NULL; | 
|  | 52 | mTuner_1_1 = NULL; | 
|  | 53 | mTunerVersion = 0; | 
|  | 54 | mTunerService = NULL; | 
|  | 55 | } | 
|  | 56 |  | 
|  | 57 | vector<FrontendId> TunerClient::getFrontendIds() { | 
|  | 58 | vector<FrontendId> ids; | 
| shubang | 68f32a3 | 2020-12-29 00:34:24 -0800 | [diff] [blame] | 59 |  | 
|  | 60 | if (mTunerService != NULL) { | 
|  | 61 | vector<int32_t> v; | 
|  | 62 | int aidl_return; | 
|  | 63 | Status s = mTunerService->getFrontendIds(&v, &aidl_return); | 
|  | 64 | if (!s.isOk() || aidl_return != (int) Result::SUCCESS | 
|  | 65 | || v.size() == 0) { | 
|  | 66 | ids.clear(); | 
|  | 67 | return ids; | 
|  | 68 | } | 
|  | 69 | for (int32_t id : v) { | 
|  | 70 | ids.push_back(static_cast<FrontendId>(id)); | 
|  | 71 | } | 
|  | 72 | return ids; | 
|  | 73 | } | 
| Amy Zhang | bf68a16 | 2020-11-23 17:42:40 -0800 | [diff] [blame] | 74 |  | 
|  | 75 | if (mTuner != NULL) { | 
|  | 76 | Result res; | 
|  | 77 | mTuner->getFrontendIds([&](Result r, const hardware::hidl_vec<FrontendId>& frontendIds) { | 
|  | 78 | res = r; | 
|  | 79 | ids = frontendIds; | 
|  | 80 | }); | 
|  | 81 | if (res != Result::SUCCESS || ids.size() == 0) { | 
|  | 82 | ALOGW("Frontend ids not available"); | 
|  | 83 | ids.clear(); | 
|  | 84 | return ids; | 
|  | 85 | } | 
|  | 86 | return ids; | 
|  | 87 | } | 
|  | 88 |  | 
|  | 89 | return ids; | 
|  | 90 | } | 
|  | 91 |  | 
|  | 92 |  | 
|  | 93 | sp<FrontendClient> TunerClient::openFrontend(int frontendHandle) { | 
|  | 94 | if (mTunerService != NULL) { | 
|  | 95 | // TODO: handle error code | 
|  | 96 | shared_ptr<ITunerFrontend> tunerFrontend; | 
|  | 97 | mTunerService->openFrontend(frontendHandle, &tunerFrontend); | 
| Amy Zhang | 6bfeaa0 | 2020-11-30 15:16:39 -0800 | [diff] [blame] | 98 | return new FrontendClient(tunerFrontend, frontendHandle); | 
| Amy Zhang | bf68a16 | 2020-11-23 17:42:40 -0800 | [diff] [blame] | 99 | } | 
|  | 100 |  | 
|  | 101 | if (mTuner != NULL) { | 
| Amy Zhang | 210c26a | 2021-01-12 11:25:27 -0800 | [diff] [blame] | 102 | int id = getResourceIdFromHandle(frontendHandle, FRONTEND); | 
|  | 103 | sp<IFrontend> hidlFrontend = openHidlFrontendById(id); | 
| Amy Zhang | bf68a16 | 2020-11-23 17:42:40 -0800 | [diff] [blame] | 104 | if (hidlFrontend != NULL) { | 
| Amy Zhang | 210c26a | 2021-01-12 11:25:27 -0800 | [diff] [blame] | 105 | sp<FrontendClient> frontendClient = new FrontendClient(NULL, id); | 
| Amy Zhang | bf68a16 | 2020-11-23 17:42:40 -0800 | [diff] [blame] | 106 | frontendClient->setHidlFrontend(hidlFrontend); | 
|  | 107 | return frontendClient; | 
|  | 108 | } | 
|  | 109 | } | 
|  | 110 |  | 
|  | 111 | return NULL; | 
|  | 112 | } | 
|  | 113 |  | 
|  | 114 | shared_ptr<FrontendInfo> TunerClient::getFrontendInfo(int id) { | 
|  | 115 | if (mTunerService != NULL) { | 
|  | 116 | TunerServiceFrontendInfo aidlFrontendInfo; | 
|  | 117 | // TODO: handle error code | 
|  | 118 | mTunerService->getFrontendInfo(id, &aidlFrontendInfo); | 
|  | 119 | return make_shared<FrontendInfo>(FrontendInfoAidlToHidl(aidlFrontendInfo)); | 
|  | 120 | } | 
|  | 121 |  | 
|  | 122 | if (mTuner != NULL) { | 
|  | 123 | FrontendInfo hidlInfo; | 
|  | 124 | Result res = getHidlFrontendInfo(id, hidlInfo); | 
|  | 125 | if (res != Result::SUCCESS) { | 
|  | 126 | return NULL; | 
|  | 127 | } | 
|  | 128 | return make_shared<FrontendInfo>(hidlInfo); | 
|  | 129 | } | 
|  | 130 |  | 
|  | 131 | return NULL; | 
|  | 132 | } | 
|  | 133 |  | 
|  | 134 | shared_ptr<FrontendDtmbCapabilities> TunerClient::getFrontendDtmbCapabilities(int id) { | 
|  | 135 | // pending aidl interface | 
|  | 136 |  | 
|  | 137 | if (mTuner_1_1 != NULL) { | 
|  | 138 | Result result; | 
|  | 139 | FrontendDtmbCapabilities dtmbCaps; | 
|  | 140 | mTuner_1_1->getFrontendDtmbCapabilities(id, | 
|  | 141 | [&](Result r, const FrontendDtmbCapabilities& caps) { | 
|  | 142 | dtmbCaps = caps; | 
|  | 143 | result = r; | 
|  | 144 | }); | 
|  | 145 | if (result == Result::SUCCESS) { | 
|  | 146 | return make_shared<FrontendDtmbCapabilities>(dtmbCaps); | 
|  | 147 | } | 
|  | 148 | } | 
|  | 149 |  | 
|  | 150 | return NULL; | 
|  | 151 | } | 
|  | 152 |  | 
| Amy Zhang | 6bfeaa0 | 2020-11-30 15:16:39 -0800 | [diff] [blame] | 153 | sp<DemuxClient> TunerClient::openDemux(int /*demuxHandle*/) { | 
|  | 154 | if (mTunerService != NULL) { | 
|  | 155 | // TODO: handle error code | 
|  | 156 | /*shared_ptr<ITunerDemux> tunerDemux; | 
|  | 157 | mTunerService->openDemux(demuxHandle, &tunerDemux); | 
|  | 158 | return new DemuxClient(tunerDemux);*/ | 
|  | 159 | } | 
|  | 160 |  | 
|  | 161 | if (mTuner != NULL) { | 
|  | 162 | // TODO: pending aidl interface | 
|  | 163 | sp<DemuxClient> demuxClient = new DemuxClient(); | 
|  | 164 | sp<IDemux> hidlDemux = openHidlDemux(); | 
|  | 165 | if (hidlDemux != NULL) { | 
|  | 166 | demuxClient->setHidlDemux(hidlDemux); | 
|  | 167 | return demuxClient; | 
|  | 168 | } | 
|  | 169 | } | 
|  | 170 |  | 
|  | 171 | return NULL; | 
|  | 172 | } | 
|  | 173 |  | 
| Amy Zhang | b0f63ab | 2021-01-06 17:19:27 -0800 | [diff] [blame^] | 174 | DemuxCapabilities TunerClient::getDemuxCaps() { | 
|  | 175 | DemuxCapabilities caps; | 
|  | 176 | return caps; | 
|  | 177 | } | 
|  | 178 |  | 
|  | 179 | sp<DescramblerClient> TunerClient::openDescrambler(int /*descramblerHandle*/) { | 
|  | 180 | return NULL; | 
|  | 181 | } | 
|  | 182 |  | 
|  | 183 | sp<LnbClient> TunerClient::openLnb(int /*lnbHandle*/) { | 
|  | 184 | return NULL; | 
|  | 185 | } | 
|  | 186 |  | 
|  | 187 | sp<LnbClient> TunerClient::openLnbByName(string /*lnbName*/) { | 
|  | 188 | return NULL; | 
|  | 189 | } | 
|  | 190 |  | 
| Amy Zhang | bf68a16 | 2020-11-23 17:42:40 -0800 | [diff] [blame] | 191 | /////////////// TunerClient Helper Methods /////////////////////// | 
|  | 192 |  | 
|  | 193 | sp<ITuner> TunerClient::getHidlTuner() { | 
|  | 194 | if (mTuner == NULL) { | 
|  | 195 | mTunerVersion = 0; | 
|  | 196 | mTuner_1_1 = ::android::hardware::tv::tuner::V1_1::ITuner::getService(); | 
|  | 197 |  | 
|  | 198 | if (mTuner_1_1 == NULL) { | 
|  | 199 | ALOGW("Failed to get tuner 1.1 service."); | 
|  | 200 | mTuner = ITuner::getService(); | 
|  | 201 | if (mTuner == NULL) { | 
|  | 202 | ALOGW("Failed to get tuner 1.0 service."); | 
|  | 203 | } else { | 
|  | 204 | mTunerVersion = 1 << 16; | 
|  | 205 | } | 
|  | 206 | } else { | 
|  | 207 | mTuner = static_cast<sp<ITuner>>(mTuner_1_1); | 
|  | 208 | mTunerVersion = ((1 << 16) | 1); | 
|  | 209 | } | 
|  | 210 | } | 
|  | 211 | return mTuner; | 
|  | 212 | } | 
|  | 213 |  | 
| Amy Zhang | 210c26a | 2021-01-12 11:25:27 -0800 | [diff] [blame] | 214 | sp<IFrontend> TunerClient::openHidlFrontendById(int id) { | 
| Amy Zhang | bf68a16 | 2020-11-23 17:42:40 -0800 | [diff] [blame] | 215 | sp<IFrontend> fe; | 
|  | 216 | Result res; | 
| Amy Zhang | bf68a16 | 2020-11-23 17:42:40 -0800 | [diff] [blame] | 217 | mTuner->openFrontendById(id, [&](Result r, const sp<IFrontend>& frontend) { | 
|  | 218 | fe = frontend; | 
|  | 219 | res = r; | 
|  | 220 | }); | 
|  | 221 | if (res != Result::SUCCESS || fe == nullptr) { | 
|  | 222 | ALOGE("Failed to open frontend"); | 
|  | 223 | return NULL; | 
|  | 224 | } | 
|  | 225 | return fe; | 
|  | 226 | } | 
|  | 227 |  | 
|  | 228 | Result TunerClient::getHidlFrontendInfo(int id, FrontendInfo& feInfo) { | 
|  | 229 | Result res; | 
|  | 230 | mTuner->getFrontendInfo(id, [&](Result r, const FrontendInfo& info) { | 
|  | 231 | feInfo = info; | 
|  | 232 | res = r; | 
|  | 233 | }); | 
|  | 234 | return res; | 
|  | 235 | } | 
|  | 236 |  | 
| Amy Zhang | 6bfeaa0 | 2020-11-30 15:16:39 -0800 | [diff] [blame] | 237 | sp<IDemux> TunerClient::openHidlDemux() { | 
|  | 238 | sp<IDemux> demux; | 
|  | 239 | Result res; | 
|  | 240 |  | 
|  | 241 | mTuner->openDemux([&](Result result, uint32_t /*id*/, const sp<IDemux>& demuxSp) { | 
|  | 242 | demux = demuxSp; | 
|  | 243 | res = result; | 
|  | 244 | }); | 
|  | 245 | if (res != Result::SUCCESS || demux == nullptr) { | 
|  | 246 | ALOGE("Failed to open demux"); | 
|  | 247 | return NULL; | 
|  | 248 | } | 
|  | 249 | return demux; | 
|  | 250 | } | 
|  | 251 |  | 
| Amy Zhang | bf68a16 | 2020-11-23 17:42:40 -0800 | [diff] [blame] | 252 | FrontendInfo TunerClient::FrontendInfoAidlToHidl(TunerServiceFrontendInfo aidlFrontendInfo) { | 
|  | 253 | FrontendInfo hidlFrontendInfo { | 
|  | 254 | .type = static_cast<FrontendType>(aidlFrontendInfo.type), | 
|  | 255 | .minFrequency = static_cast<uint32_t>(aidlFrontendInfo.minFrequency), | 
|  | 256 | .maxFrequency = static_cast<uint32_t>(aidlFrontendInfo.maxFrequency), | 
|  | 257 | .minSymbolRate = static_cast<uint32_t>(aidlFrontendInfo.minSymbolRate), | 
|  | 258 | .maxSymbolRate = static_cast<uint32_t>(aidlFrontendInfo.maxSymbolRate), | 
|  | 259 | .acquireRange = static_cast<uint32_t>(aidlFrontendInfo.acquireRange), | 
|  | 260 | .exclusiveGroupId = static_cast<uint32_t>(aidlFrontendInfo.exclusiveGroupId), | 
|  | 261 | }; | 
|  | 262 | // TODO: handle Frontend caps | 
|  | 263 |  | 
|  | 264 | return hidlFrontendInfo; | 
|  | 265 | } | 
| Amy Zhang | 210c26a | 2021-01-12 11:25:27 -0800 | [diff] [blame] | 266 |  | 
|  | 267 | int TunerClient::getResourceIdFromHandle(int handle, int /*resourceType*/) { | 
|  | 268 | return (handle & 0x00ff0000) >> 16; | 
|  | 269 | } | 
|  | 270 |  | 
|  | 271 | int TunerClient::getResourceHandleFromId(int id, int resourceType) { | 
|  | 272 | // TODO: build up randomly generated id to handle mapping | 
|  | 273 | return (resourceType & 0x000000ff) << 24 | 
|  | 274 | | (id << 16) | 
|  | 275 | | (mResourceRequestCount++ & 0xffff); | 
|  | 276 | } | 
| Amy Zhang | bf68a16 | 2020-11-23 17:42:40 -0800 | [diff] [blame] | 277 | }  // namespace android |