blob: ef739df117e1f6472c0dd400cf0dd1c2b26c05e4 [file] [log] [blame]
Weilin Xu25409e52023-09-06 10:36:24 -07001/*
2 * Copyright (C) 2023 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 "BcRadioAidlDef.utilsV2"
18
19#include "broadcastradio-utils-aidl/UtilsV2.h"
20
21#include <android-base/logging.h>
22#include <android-base/strings.h>
23
24namespace aidl::android::hardware::broadcastradio {
25
26namespace utils {
27
28bool isValidV2(const ProgramIdentifier& id) {
29 uint64_t val = static_cast<uint64_t>(id.value);
30 bool valid = true;
31
32 auto expect = [&valid](bool condition, const std::string& message) {
33 if (!condition) {
34 valid = false;
35 LOG(ERROR) << "identifier not valid, expected " << message;
36 }
37 };
38
39 switch (id.type) {
40 case IdentifierType::INVALID:
41 expect(false, "IdentifierType::INVALID");
42 break;
43 case IdentifierType::DAB_FREQUENCY_KHZ:
44 expect(val > 100000u, "f > 100MHz");
45 [[fallthrough]];
46 case IdentifierType::AMFM_FREQUENCY_KHZ:
47 case IdentifierType::DRMO_FREQUENCY_KHZ:
48 expect(val > 100u, "f > 100kHz");
49 expect(val < 10000000u, "f < 10GHz");
50 break;
51 case IdentifierType::RDS_PI:
52 expect(val != 0u, "RDS PI != 0");
53 expect(val <= 0xFFFFu, "16bit id");
54 break;
55 case IdentifierType::HD_STATION_ID_EXT: {
56 uint64_t stationId = val & 0xFFFFFFFF; // 32bit
57 val >>= 32;
58 uint64_t subchannel = val & 0xF; // 4bit
59 val >>= 4;
60 uint64_t freq = val & 0x3FFFF; // 18bit
61 expect(stationId != 0u, "HD station id != 0");
62 expect(subchannel < 8u, "HD subch < 8");
63 expect(freq > 100u, "f > 100kHz");
64 expect(freq < 10000000u, "f < 10GHz");
65 break;
66 }
67 case IdentifierType::HD_STATION_NAME: {
68 while (val > 0) {
69 char ch = static_cast<char>(val & 0xFF);
70 val >>= 8;
71 expect((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z'),
72 "HD_STATION_NAME does not match [A-Z0-9]+");
73 }
74 break;
75 }
76 case IdentifierType::DAB_SID_EXT: {
77 uint64_t sid = val & 0xFFFFFFFF; // 32bit
78 val >>= 32;
79 uint64_t ecc = val & 0xFF; // 8bit
80 expect(sid != 0u, "DAB SId != 0");
81 expect(ecc >= 0xA0u && ecc <= 0xF6u, "Invalid ECC, see ETSI TS 101 756 V2.1.1");
82 break;
83 }
84 case IdentifierType::DAB_ENSEMBLE:
85 expect(val != 0u, "DAB ensemble != 0");
86 expect(val <= 0xFFFFu, "16bit id");
87 break;
88 case IdentifierType::DAB_SCID:
89 expect(val > 0xFu, "12bit SCId (not 4bit SCIdS)");
90 expect(val <= 0xFFFu, "12bit id");
91 break;
92 case IdentifierType::DRMO_SERVICE_ID:
93 expect(val != 0u, "DRM SId != 0");
94 expect(val <= 0xFFFFFFu, "24bit id");
95 break;
96 case IdentifierType::SXM_SERVICE_ID:
97 expect(val != 0u, "SXM SId != 0");
98 expect(val <= 0xFFFFFFFFu, "32bit id");
99 break;
100 case IdentifierType::SXM_CHANNEL:
101 expect(val < 1000u, "SXM channel < 1000");
102 break;
103 case IdentifierType::HD_STATION_LOCATION: {
104 uint64_t latitudeBit = val & 0x1;
105 expect(latitudeBit == 1u, "Latitude comes first");
106 val >>= 27;
107 uint64_t latitudePad = val & 0x1Fu;
108 expect(latitudePad == 0u, "Latitude padding");
109 val >>= 5;
110 uint64_t longitudeBit = val & 0x1;
111 expect(longitudeBit == 1u, "Longitude comes next");
112 val >>= 27;
113 uint64_t longitudePad = val & 0x1Fu;
114 expect(longitudePad == 0u, "Latitude padding");
115 break;
116 }
117 default:
118 expect(id.type >= IdentifierType::VENDOR_START && id.type <= IdentifierType::VENDOR_END,
119 "Undefined identifier type");
120 break;
121 }
122
123 return valid;
124}
125
126bool isValidV2(const ProgramSelector& sel) {
127 if (sel.primaryId.type != IdentifierType::AMFM_FREQUENCY_KHZ &&
128 sel.primaryId.type != IdentifierType::RDS_PI &&
129 sel.primaryId.type != IdentifierType::HD_STATION_ID_EXT &&
130 sel.primaryId.type != IdentifierType::DAB_SID_EXT &&
131 sel.primaryId.type != IdentifierType::DRMO_SERVICE_ID &&
132 sel.primaryId.type != IdentifierType::SXM_SERVICE_ID &&
133 (sel.primaryId.type < IdentifierType::VENDOR_START ||
134 sel.primaryId.type > IdentifierType::VENDOR_END)) {
135 return false;
136 }
137 return isValidV2(sel.primaryId);
138}
139
140std::optional<std::string> getMetadataStringV2(const ProgramInfo& info, const Metadata::Tag& tag) {
141 auto isRdsPs = [tag](const Metadata& item) { return item.getTag() == tag; };
142
143 auto it = std::find_if(info.metadata.begin(), info.metadata.end(), isRdsPs);
144 if (it == info.metadata.end()) {
145 return std::nullopt;
146 }
147
148 std::string metadataString;
149 switch (it->getTag()) {
150 case Metadata::rdsPs:
151 metadataString = it->get<Metadata::rdsPs>();
152 break;
153 case Metadata::rdsPty:
154 metadataString = std::to_string(it->get<Metadata::rdsPty>());
155 break;
156 case Metadata::rbdsPty:
157 metadataString = std::to_string(it->get<Metadata::rbdsPty>());
158 break;
159 case Metadata::rdsRt:
160 metadataString = it->get<Metadata::rdsRt>();
161 break;
162 case Metadata::songTitle:
163 metadataString = it->get<Metadata::songTitle>();
164 break;
165 case Metadata::songArtist:
166 metadataString = it->get<Metadata::songArtist>();
167 break;
168 case Metadata::songAlbum:
169 metadataString = it->get<Metadata::songAlbum>();
170 break;
171 case Metadata::stationIcon:
172 metadataString = std::to_string(it->get<Metadata::stationIcon>());
173 break;
174 case Metadata::albumArt:
175 metadataString = std::to_string(it->get<Metadata::albumArt>());
176 break;
177 case Metadata::programName:
178 metadataString = it->get<Metadata::programName>();
179 break;
180 case Metadata::dabEnsembleName:
181 metadataString = it->get<Metadata::dabEnsembleName>();
182 break;
183 case Metadata::dabEnsembleNameShort:
184 metadataString = it->get<Metadata::dabEnsembleNameShort>();
185 break;
186 case Metadata::dabServiceName:
187 metadataString = it->get<Metadata::dabServiceName>();
188 break;
189 case Metadata::dabServiceNameShort:
190 metadataString = it->get<Metadata::dabServiceNameShort>();
191 break;
192 case Metadata::dabComponentName:
193 metadataString = it->get<Metadata::dabComponentName>();
194 break;
195 case Metadata::dabComponentNameShort:
196 metadataString = it->get<Metadata::dabComponentNameShort>();
197 break;
198 case Metadata::genre:
199 metadataString = it->get<Metadata::genre>();
200 break;
201 case Metadata::commentShortDescription:
202 metadataString = it->get<Metadata::commentShortDescription>();
203 break;
204 case Metadata::commentActualText:
205 metadataString = it->get<Metadata::commentActualText>();
206 break;
207 case Metadata::commercial:
208 metadataString = it->get<Metadata::commercial>();
209 break;
210 case Metadata::ufids: {
211 auto& ufids = it->get<Metadata::ufids>();
212 metadataString = "[";
213 for (const auto& ufid : ufids) {
214 metadataString += std::string(ufid) + ",";
215 }
216 if (ufids.empty()) {
217 metadataString += "]";
218 } else {
219 metadataString[metadataString.size() - 1] = ']';
220 }
221 } break;
222 case Metadata::hdStationNameShort:
223 metadataString = it->get<Metadata::hdStationNameShort>();
224 break;
225 case Metadata::hdStationNameLong:
226 metadataString = it->get<Metadata::hdStationNameLong>();
227 break;
228 case Metadata::hdSubChannelsAvailable:
229 metadataString = std::to_string(it->get<Metadata::hdSubChannelsAvailable>());
230 break;
231 default:
232 LOG(ERROR) << "Metadata " << it->toString() << " is not converted.";
233 return std::nullopt;
234 }
235 return metadataString;
236}
237
238} // namespace utils
239
240} // namespace aidl::android::hardware::broadcastradio