/** * 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 "BroadcastRadioService.regions.jni" #define LOG_NDEBUG 0 #include "regions.h" #include #include namespace android { namespace server { namespace BroadcastRadio { namespace regions { namespace utils = hardware::broadcastradio::utils; using hardware::hidl_vec; using V1_0::Band; using V1_0::BandConfig; using V1_0::Deemphasis; using V1_0::Rds; class RegionalBandDefinition { public: std::vector mRegions; std::vector mTypes; uint32_t mLowerLimit; uint32_t mUpperLimit; uint32_t mSpacing; Deemphasis mFmDeemphasis = {}; Rds mFmRds = Rds::NONE; bool fitsInsideBand(const BandConfig &bandConfig) const; std::vector withConfig(BandConfig bandConfig) const; }; static const RegionalBandDefinition kKnownRegionConfigs[] = { { { Region::ITU_1 }, { Band::FM }, 87500, 108000, 100, Deemphasis::D50, Rds::WORLD, }, { { Region::ITU_2 }, { Band::FM, Band::FM_HD }, 87700, 107900, 200, Deemphasis::D75, Rds::US, }, { { Region::OIRT }, { Band::FM }, 65800, 74000, 10, Deemphasis::D50, Rds::WORLD, }, { { Region::JAPAN }, { Band::FM }, 76000, 90000, 100, Deemphasis::D50, Rds::WORLD, }, { { Region::KOREA }, { Band::FM }, 87500, 108000, 100, Deemphasis::D75, Rds::WORLD, }, { // AM LW { Region::ITU_1, Region::OIRT, Region::JAPAN, Region::KOREA }, { Band::AM }, 153, 282, 9, }, { // AM MW { Region::ITU_1, Region::OIRT, Region::JAPAN, Region::KOREA }, { Band::AM }, 531, 1620, 9, }, { // AM SW { Region::ITU_1, Region::OIRT, Region::JAPAN, Region::KOREA }, { Band::AM }, 2300, 26100, 5, }, { // AM LW ITU2 { Region::ITU_2 }, { Band::AM, Band::AM_HD }, 153, 279, 9, }, { // AM MW ITU2 { Region::ITU_2 }, { Band::AM, Band::AM_HD }, 530, 1700, 10, }, { // AM SW ITU2 { Region::ITU_2 }, { Band::AM, Band::AM_HD }, 2300, 26100, 5, }, }; bool RegionalBandDefinition::fitsInsideBand(const BandConfig &bandConfig) const { if (std::find(mTypes.begin(), mTypes.end(), bandConfig.type) == mTypes.end()) return false; if (mLowerLimit < bandConfig.lowerLimit) return false; if (mUpperLimit > bandConfig.upperLimit) return false; auto&& spacings = bandConfig.spacings; if (std::find(spacings.begin(), spacings.end(), mSpacing) == spacings.end()) return false; if (utils::isFm(bandConfig.type)) { if (0 == (mFmDeemphasis & bandConfig.ext.fm.deemphasis)) return false; } return true; } std::vector RegionalBandDefinition::withConfig(BandConfig config) const { config.lowerLimit = mLowerLimit; config.upperLimit = mUpperLimit; config.spacings = hidl_vec({ mSpacing }); if (utils::isFm(config.type)) { auto&& fm = config.ext.fm; fm.deemphasis = mFmDeemphasis; fm.rds = static_cast(mFmRds & fm.rds); } std::vector configs; for (auto region : mRegions) { configs.push_back({region, config}); } return configs; } std::vector mapRegions(const hidl_vec& bands) { ALOGV("%s", __func__); std::vector out; for (auto&& regionalBand : kKnownRegionConfigs) { for (auto&& tunerBand : bands) { if (regionalBand.fitsInsideBand(tunerBand)) { auto mapped = regionalBand.withConfig(tunerBand); out.insert(out.end(), mapped.begin(), mapped.end()); } } } ALOGI("Mapped %zu tuner bands to %zu regional bands", bands.size(), out.size()); return out; } } // namespace regions } // namespace BroadcastRadio } // namespace server } // namespace android