/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "BroadcastRadioDefault.module" #define LOG_NDEBUG 0 #include "BroadcastRadio.h" #include <log/log.h> #include "resources.h" namespace android { namespace hardware { namespace broadcastradio { namespace V1_1 { namespace implementation { using V1_0::Band; using V1_0::BandConfig; using V1_0::Class; using V1_0::Deemphasis; using V1_0::Rds; using V1_1::IdentifierType; using V1_1::ProgramSelector; using V1_1::ProgramType; using V1_1::Properties; using V1_1::VendorKeyValue; using std::lock_guard; using std::map; using std::mutex; using std::vector; // clang-format off static const map<Class, ModuleConfig> gModuleConfigs{ {Class::AM_FM, ModuleConfig({ "Digital radio mock", { // amFmBands AmFmBandConfig({ Band::AM, 153, // lowerLimit 26100, // upperLimit {5, 9, 10}, // spacings }), AmFmBandConfig({ Band::FM, 65800, // lowerLimit 108000, // upperLimit {10, 100, 200}, // spacings }), AmFmBandConfig({ Band::AM_HD, 153, // lowerLimit 26100, // upperLimit {5, 9, 10}, // spacings }), AmFmBandConfig({ Band::FM_HD, 87700, // lowerLimit 107900, // upperLimit {200}, // spacings }), }, })}, {Class::SAT, ModuleConfig({ "Satellite radio mock", {}, // amFmBands })}, }; // clang-format on BroadcastRadio::BroadcastRadio(Class classId) : mClassId(classId), mConfig(gModuleConfigs.at(classId)) {} bool BroadcastRadio::isSupported(Class classId) { return gModuleConfigs.find(classId) != gModuleConfigs.end(); } Return<void> BroadcastRadio::getProperties(getProperties_cb _hidl_cb) { ALOGV("%s", __func__); return getProperties_1_1( [&](const Properties& properties) { _hidl_cb(Result::OK, properties.base); }); } Return<void> BroadcastRadio::getProperties_1_1(getProperties_1_1_cb _hidl_cb) { ALOGV("%s", __func__); Properties prop11 = {}; auto& prop10 = prop11.base; prop10.classId = mClassId; prop10.implementor = "Google"; prop10.product = mConfig.productName; prop10.numTuners = 1; prop10.numAudioSources = 1; prop10.supportsCapture = false; prop11.supportsBackgroundScanning = true; prop11.supportedProgramTypes = hidl_vec<uint32_t>({ static_cast<uint32_t>(ProgramType::AM), static_cast<uint32_t>(ProgramType::FM), static_cast<uint32_t>(ProgramType::AM_HD), static_cast<uint32_t>(ProgramType::FM_HD), }); prop11.supportedIdentifierTypes = hidl_vec<uint32_t>({ static_cast<uint32_t>(IdentifierType::AMFM_FREQUENCY), static_cast<uint32_t>(IdentifierType::RDS_PI), static_cast<uint32_t>(IdentifierType::HD_STATION_ID_EXT), static_cast<uint32_t>(IdentifierType::HD_SUBCHANNEL), }); prop11.vendorInfo = hidl_vec<VendorKeyValue>({ {"com.google.dummy", "dummy"}, }); prop10.bands = getAmFmBands(); _hidl_cb(prop11); return Void(); } Return<void> BroadcastRadio::openTuner(const BandConfig& config, bool audio __unused, const sp<V1_0::ITunerCallback>& callback, openTuner_cb _hidl_cb) { ALOGV("%s(%s)", __func__, toString(config.type).c_str()); lock_guard<mutex> lk(mMut); auto oldTuner = mTuner.promote(); if (oldTuner != nullptr) { ALOGI("Force-closing previously opened tuner"); oldTuner->forceClose(); mTuner = nullptr; } sp<Tuner> newTuner = new Tuner(this, mClassId, callback); mTuner = newTuner; if (mClassId == Class::AM_FM) { auto ret = newTuner->setConfiguration(config); if (ret != Result::OK) { _hidl_cb(Result::INVALID_ARGUMENTS, {}); return Void(); } } _hidl_cb(Result::OK, newTuner); return Void(); } Return<void> BroadcastRadio::getImage(int32_t id, getImage_cb _hidl_cb) { ALOGV("%s(%x)", __func__, id); if (id == resources::demoPngId) { _hidl_cb(std::vector<uint8_t>(resources::demoPng, std::end(resources::demoPng))); return {}; } ALOGI("Image %x doesn't exists", id); _hidl_cb({}); return Void(); } std::vector<V1_0::BandConfig> BroadcastRadio::getAmFmBands() const { std::vector<V1_0::BandConfig> out; for (auto&& src : mConfig.amFmBands) { V1_0::BandConfig dst; dst.type = src.type; dst.antennaConnected = true; dst.lowerLimit = src.lowerLimit; dst.upperLimit = src.upperLimit; dst.spacings = src.spacings; if (utils::isAm(src.type)) { dst.ext.am.stereo = true; } else if (utils::isFm(src.type)) { dst.ext.fm.deemphasis = static_cast<Deemphasis>(Deemphasis::D50 | Deemphasis::D75); dst.ext.fm.stereo = true; dst.ext.fm.rds = static_cast<Rds>(Rds::WORLD | Rds::US); dst.ext.fm.ta = true; dst.ext.fm.af = true; dst.ext.fm.ea = true; } out.push_back(dst); } return out; } } // namespace implementation } // namespace V1_1 } // namespace broadcastradio } // namespace hardware } // namespace android