blob: d15710810a4eec9f6d1cb8cd786aeaa0c0f7df71 [file] [log] [blame]
Tomasz Wasilczyk06100b32017-12-04 09:53:32 -08001/*
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#define LOG_TAG "BcRadioDef.utils"
17//#define LOG_NDEBUG 0
18
19#include <broadcastradio-utils-2x/Utils.h>
20
21#include <log/log.h>
22
23namespace android {
24namespace hardware {
25namespace broadcastradio {
26namespace utils {
27
28using V2_0::IdentifierType;
29using V2_0::Metadata;
30using V2_0::MetadataKey;
31using V2_0::ProgramIdentifier;
32using V2_0::ProgramSelector;
33
34using std::string;
Tomasz Wasilczyk31e86322017-12-05 09:36:11 -080035using std::vector;
Tomasz Wasilczyk06100b32017-12-04 09:53:32 -080036
37IdentifierType getType(const ProgramIdentifier& id) {
38 return static_cast<IdentifierType>(id.type);
39}
40
41static bool bothHaveId(const ProgramSelector& a, const ProgramSelector& b,
42 const IdentifierType type) {
43 return hasId(a, type) && hasId(b, type);
44}
45
46static bool haveEqualIds(const ProgramSelector& a, const ProgramSelector& b,
47 const IdentifierType type) {
48 if (!bothHaveId(a, b, type)) return false;
49 /* We should check all Ids of a given type (ie. other AF),
50 * but it doesn't matter for default implementation.
51 */
52 return getId(a, type) == getId(b, type);
53}
54
55static int getHdSubchannel(const ProgramSelector& sel) {
56 auto hdsidext = getId(sel, IdentifierType::HD_STATION_ID_EXT, 0);
57 hdsidext >>= 32; // Station ID number
58 return hdsidext & 0xF; // HD Radio subchannel
59}
60
61bool tunesTo(const ProgramSelector& a, const ProgramSelector& b) {
62 auto type = getType(b.primaryId);
63
64 switch (type) {
65 case IdentifierType::HD_STATION_ID_EXT:
66 case IdentifierType::RDS_PI:
67 case IdentifierType::AMFM_FREQUENCY:
68 if (haveEqualIds(a, b, IdentifierType::HD_STATION_ID_EXT)) return true;
69 if (haveEqualIds(a, b, IdentifierType::RDS_PI)) return true;
70 return getHdSubchannel(b) == 0 && haveEqualIds(a, b, IdentifierType::AMFM_FREQUENCY);
71 case IdentifierType::DAB_SID_EXT:
72 return haveEqualIds(a, b, IdentifierType::DAB_SID_EXT);
73 case IdentifierType::DRMO_SERVICE_ID:
74 return haveEqualIds(a, b, IdentifierType::DRMO_SERVICE_ID);
75 case IdentifierType::SXM_SERVICE_ID:
76 return haveEqualIds(a, b, IdentifierType::SXM_SERVICE_ID);
77 default: // includes all vendor types
78 ALOGW("Unsupported program type: %s", toString(type).c_str());
79 return false;
80 }
81}
82
83static bool maybeGetId(const ProgramSelector& sel, const IdentifierType type, uint64_t* val) {
84 auto itype = static_cast<uint32_t>(type);
85
86 if (sel.primaryId.type == itype) {
87 if (val) *val = sel.primaryId.value;
88 return true;
89 }
90
91 // not optimal, but we don't care in default impl
92 for (auto&& id : sel.secondaryIds) {
93 if (id.type == itype) {
94 if (val) *val = id.value;
95 return true;
96 }
97 }
98
99 return false;
100}
101
102bool hasId(const ProgramSelector& sel, const IdentifierType type) {
103 return maybeGetId(sel, type, nullptr);
104}
105
106uint64_t getId(const ProgramSelector& sel, const IdentifierType type) {
107 uint64_t val;
108
109 if (maybeGetId(sel, type, &val)) {
110 return val;
111 }
112
113 ALOGW("Identifier %s not found", toString(type).c_str());
114 return 0;
115}
116
117uint64_t getId(const ProgramSelector& sel, const IdentifierType type, uint64_t defval) {
118 if (!hasId(sel, type)) return defval;
119 return getId(sel, type);
120}
121
Tomasz Wasilczyk31e86322017-12-05 09:36:11 -0800122vector<uint64_t> getAllIds(const ProgramSelector& sel, const IdentifierType type) {
123 vector<uint64_t> ret;
124 auto itype = static_cast<uint32_t>(type);
125
126 if (sel.primaryId.type == itype) ret.push_back(sel.primaryId.value);
127
128 for (auto&& id : sel.secondaryIds) {
129 if (id.type == itype) ret.push_back(id.value);
130 }
131
132 return ret;
133}
134
Tomasz Wasilczyk06100b32017-12-04 09:53:32 -0800135bool isSupported(const V2_0::Properties& prop, const V2_0::ProgramSelector& sel) {
136 // Not optimal, but it doesn't matter for default impl nor VTS tests.
137 for (auto&& idTypeI : prop.supportedIdentifierTypes) {
138 auto idType = static_cast<IdentifierType>(idTypeI);
139 if (hasId(sel, idType)) return true;
140 }
141 return false;
142}
143
144static bool isValid(const ProgramIdentifier& id) {
145 auto val = id.value;
146 bool valid = true;
147
148 auto expect = [&valid](bool condition, std::string message) {
149 if (!condition) {
150 valid = false;
151 ALOGE("Identifier not valid, expected %s", message.c_str());
152 }
153 };
154
155 switch (static_cast<IdentifierType>(id.type)) {
156 case IdentifierType::AMFM_FREQUENCY:
157 case IdentifierType::DAB_FREQUENCY:
158 case IdentifierType::DRMO_FREQUENCY:
159 expect(val > 100u, "f > 100kHz");
160 expect(val < 10000000u, "f < 10GHz");
161 break;
162 case IdentifierType::RDS_PI:
163 expect(val != 0u, "RDS PI != 0");
164 expect(val <= 0xFFFFu, "16bit id");
165 break;
166 case IdentifierType::HD_STATION_ID_EXT: {
167 auto stationId = val & 0xFFFFFFFF; // 32bit
168 val >>= 32;
169 auto subchannel = val & 0xF; // 4bit
170 val >>= 4;
171 auto freq = val & 0x3FFFF; // 18bit
172 expect(stationId != 0u, "HD station id != 0");
173 expect(subchannel < 8u, "HD subch < 8");
174 expect(freq > 100u, "f > 100kHz");
175 expect(freq < 10000000u, "f < 10GHz");
176 break;
177 }
178 case IdentifierType::DAB_SID_EXT: {
179 auto sid = val & 0xFFFF; // 16bit
180 val >>= 16;
181 auto ecc = val & 0xFF; // 8bit
182 expect(sid != 0u, "DAB SId != 0");
183 expect(ecc >= 0xA0u && ecc <= 0xF6u, "Invalid ECC, see ETSI TS 101 756 V2.1.1");
184 break;
185 }
186 case IdentifierType::DAB_ENSEMBLE:
187 expect(val != 0u, "DAB ensemble != 0");
188 expect(val <= 0xFFFFu, "16bit id");
189 break;
190 case IdentifierType::DAB_SCID:
191 expect(val > 0xFu, "12bit SCId (not 4bit SCIdS)");
192 expect(val <= 0xFFFu, "12bit id");
193 break;
194 case IdentifierType::DRMO_SERVICE_ID:
195 expect(val != 0u, "DRM SId != 0");
196 expect(val <= 0xFFFFFFu, "24bit id");
197 break;
198 case IdentifierType::SXM_SERVICE_ID:
199 expect(val != 0u, "SXM SId != 0");
200 expect(val <= 0xFFFFFFFFu, "32bit id");
201 break;
202 case IdentifierType::SXM_CHANNEL:
203 expect(val < 1000u, "SXM channel < 1000");
204 break;
205 case IdentifierType::VENDOR_START:
206 case IdentifierType::VENDOR_END:
207 // skip
208 break;
209 }
210
211 return valid;
212}
213
214bool isValid(const V2_0::ProgramSelector& sel) {
215 if (!isValid(sel.primaryId)) return false;
216 for (auto&& id : sel.secondaryIds) {
217 if (!isValid(id)) return false;
218 }
219 return true;
220}
221
222ProgramIdentifier make_identifier(IdentifierType type, uint64_t value) {
223 return {static_cast<uint32_t>(type), value};
224}
225
226ProgramSelector make_selector_amfm(uint32_t frequency) {
227 ProgramSelector sel = {};
228 sel.primaryId = make_identifier(IdentifierType::AMFM_FREQUENCY, frequency);
229 return sel;
230}
231
232Metadata make_metadata(MetadataKey key, int64_t value) {
233 Metadata meta = {};
234 meta.key = static_cast<uint32_t>(key);
235 meta.intValue = value;
236 return meta;
237}
238
239Metadata make_metadata(MetadataKey key, string value) {
240 Metadata meta = {};
241 meta.key = static_cast<uint32_t>(key);
242 meta.stringValue = value;
243 return meta;
244}
245
246} // namespace utils
247} // namespace broadcastradio
248} // namespace hardware
249} // namespace android