1 /** 2 * Copyright (C) 2017 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 "BroadcastRadioService.regions.jni" 18 #define LOG_NDEBUG 0 19 20 #include "regions.h" 21 22 #include <broadcastradio-utils-1x/Utils.h> 23 #include <utils/Log.h> 24 25 namespace android { 26 namespace server { 27 namespace BroadcastRadio { 28 namespace regions { 29 30 namespace utils = hardware::broadcastradio::utils; 31 32 using hardware::hidl_vec; 33 34 using V1_0::Band; 35 using V1_0::BandConfig; 36 using V1_0::Deemphasis; 37 using V1_0::Rds; 38 39 class RegionalBandDefinition { 40 public: 41 std::vector<Region> mRegions; 42 std::vector<Band> mTypes; 43 uint32_t mLowerLimit; 44 uint32_t mUpperLimit; 45 uint32_t mSpacing; 46 47 Deemphasis mFmDeemphasis = {}; 48 Rds mFmRds = Rds::NONE; 49 50 bool fitsInsideBand(const BandConfig &bandConfig) const; 51 std::vector<RegionalBandConfig> withConfig(BandConfig bandConfig) const; 52 }; 53 54 static const RegionalBandDefinition kKnownRegionConfigs[] = { 55 { 56 { Region::ITU_1 }, 57 { Band::FM }, 58 87500, 59 108000, 60 100, 61 Deemphasis::D50, 62 Rds::WORLD, 63 }, 64 { 65 { Region::ITU_2 }, 66 { Band::FM, Band::FM_HD }, 67 87700, 68 107900, 69 200, 70 Deemphasis::D75, 71 Rds::US, 72 }, 73 { 74 { Region::OIRT }, 75 { Band::FM }, 76 65800, 77 74000, 78 10, 79 Deemphasis::D50, 80 Rds::WORLD, 81 }, 82 { 83 { Region::JAPAN }, 84 { Band::FM }, 85 76000, 86 90000, 87 100, 88 Deemphasis::D50, 89 Rds::WORLD, 90 }, 91 { 92 { Region::KOREA }, 93 { Band::FM }, 94 87500, 95 108000, 96 100, 97 Deemphasis::D75, 98 Rds::WORLD, 99 }, 100 { // AM LW 101 { Region::ITU_1, Region::OIRT, Region::JAPAN, Region::KOREA }, 102 { Band::AM }, 103 153, 104 282, 105 9, 106 }, 107 { // AM MW 108 { Region::ITU_1, Region::OIRT, Region::JAPAN, Region::KOREA }, 109 { Band::AM }, 110 531, 111 1620, 112 9, 113 }, 114 { // AM SW 115 { Region::ITU_1, Region::OIRT, Region::JAPAN, Region::KOREA }, 116 { Band::AM }, 117 2300, 118 26100, 119 5, 120 }, 121 { // AM LW ITU2 122 { Region::ITU_2 }, 123 { Band::AM, Band::AM_HD }, 124 153, 125 279, 126 9, 127 }, 128 { // AM MW ITU2 129 { Region::ITU_2 }, 130 { Band::AM, Band::AM_HD }, 131 530, 132 1700, 133 10, 134 }, 135 { // AM SW ITU2 136 { Region::ITU_2 }, 137 { Band::AM, Band::AM_HD }, 138 2300, 139 26100, 140 5, 141 }, 142 }; 143 144 bool RegionalBandDefinition::fitsInsideBand(const BandConfig &bandConfig) const { 145 if (std::find(mTypes.begin(), mTypes.end(), bandConfig.type) == mTypes.end()) return false; 146 if (mLowerLimit < bandConfig.lowerLimit) return false; 147 if (mUpperLimit > bandConfig.upperLimit) return false; 148 auto&& spacings = bandConfig.spacings; 149 if (std::find(spacings.begin(), spacings.end(), mSpacing) == spacings.end()) return false; 150 if (utils::isFm(bandConfig.type)) { 151 if (0 == (mFmDeemphasis & bandConfig.ext.fm.deemphasis)) return false; 152 } 153 154 return true; 155 } 156 157 std::vector<RegionalBandConfig> RegionalBandDefinition::withConfig(BandConfig config) const { 158 config.lowerLimit = mLowerLimit; 159 config.upperLimit = mUpperLimit; 160 config.spacings = hidl_vec<uint32_t>({ mSpacing }); 161 if (utils::isFm(config.type)) { 162 auto&& fm = config.ext.fm; 163 fm.deemphasis = mFmDeemphasis; 164 fm.rds = static_cast<Rds>(mFmRds & fm.rds); 165 } 166 167 std::vector<RegionalBandConfig> configs; 168 for (auto region : mRegions) { 169 configs.push_back({region, config}); 170 } 171 172 return configs; 173 } 174 175 std::vector<RegionalBandConfig> mapRegions(const hidl_vec<BandConfig>& bands) { 176 ALOGV("%s", __func__); 177 178 std::vector<RegionalBandConfig> out; 179 180 for (auto&& regionalBand : kKnownRegionConfigs) { 181 for (auto&& tunerBand : bands) { 182 if (regionalBand.fitsInsideBand(tunerBand)) { 183 auto mapped = regionalBand.withConfig(tunerBand); 184 out.insert(out.end(), mapped.begin(), mapped.end()); 185 } 186 } 187 } 188 189 ALOGI("Mapped %zu tuner bands to %zu regional bands", bands.size(), out.size()); 190 return out; 191 } 192 193 } // namespace regions 194 } // namespace BroadcastRadio 195 } // namespace server 196 } // namespace android 197