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
fitsInsideBand(const BandConfig & bandConfig) const144 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
withConfig(BandConfig config) const157 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
mapRegions(const hidl_vec<BandConfig> & bands)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