blob: e21344ede2d5add74b74c8e0281e321ff950c6dd [file] [log] [blame]
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -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 "BroadcastRadioHalUtils"
17//#define LOG_NDEBUG 0
18
19#include <log/log.h>
20#include <system/radio_metadata.h>
21
22#include "Utils.h"
23
24namespace android {
25namespace hardware {
26namespace broadcastradio {
27namespace V1_1 {
28namespace implementation {
29
30using V1_0::Band;
31using V1_0::Deemphasis;
32using V1_0::Direction;
33using V1_0::MetadataKey;
34using V1_0::MetadataType;
35using V1_0::Rds;
36
37const char *Utils::sClassModuleNames[] = {
38 RADIO_HARDWARE_MODULE_ID_FM, /* corresponds to RADIO_CLASS_AM_FM */
39 RADIO_HARDWARE_MODULE_ID_SAT, /* corresponds to RADIO_CLASS_SAT */
40 RADIO_HARDWARE_MODULE_ID_DT, /* corresponds to RADIO_CLASS_DT */
41};
42
43// make sure HIDL enum values are aligned with legacy values
44static_assert(RADIO_CLASS_AM_FM == static_cast<int>(Class::AM_FM),
45 "AM/FM class mismatch with legacy");
46static_assert(RADIO_CLASS_SAT == static_cast<int>(Class::SAT),
47 "SAT class mismatch with legacy");
48static_assert(RADIO_CLASS_DT == static_cast<int>(Class::DT),
49 "DT class mismatch with legacy");
50
51static_assert(RADIO_BAND_AM == static_cast<int>(Band::AM),
52 "AM band mismatch with legacy");
53static_assert(RADIO_BAND_FM == static_cast<int>(Band::FM),
54 "FM band mismatch with legacy");
55static_assert(RADIO_BAND_AM_HD == static_cast<int>(Band::AM_HD),
56 "AM HD band mismatch with legacy");
57static_assert(RADIO_BAND_FM_HD == static_cast<int>(Band::FM_HD),
58 "FM HD band mismatch with legacy");
59
60static_assert(RADIO_RDS_NONE == static_cast<int>(Rds::NONE),
61 "RDS NONE mismatch with legacy");
62static_assert(RADIO_RDS_WORLD == static_cast<int>(Rds::WORLD),
63 "RDS WORLD mismatch with legacy");
64static_assert(RADIO_RDS_US == static_cast<int>(Rds::US),
65 "RDS US mismatch with legacy");
66
67static_assert(RADIO_DEEMPHASIS_50 == static_cast<int>(Deemphasis::D50),
68 "De-emphasis 50 mismatch with legacy");
69static_assert(RADIO_DEEMPHASIS_75 == static_cast<int>(Deemphasis::D75),
70 "De-emphasis 75 mismatch with legacy");
71
72static_assert(RADIO_DIRECTION_UP == static_cast<int>(Direction::UP),
73 "Direction Up mismatch with legacy");
74static_assert(RADIO_DIRECTION_DOWN == static_cast<int>(Direction::DOWN),
75 "Direction Up mismatch with legacy");
76
77static_assert(RADIO_METADATA_TYPE_INVALID == static_cast<int>(MetadataType::INVALID),
78 "Metadata type INVALID mismatch with legacy");
79static_assert(RADIO_METADATA_TYPE_INT == static_cast<int>(MetadataType::INT),
80 "Metadata type INT mismatch with legacy");
81static_assert(RADIO_METADATA_TYPE_TEXT == static_cast<int>(MetadataType::TEXT),
82 "Metadata type TEXT mismatch with legacy");
83static_assert(RADIO_METADATA_TYPE_RAW == static_cast<int>(MetadataType::RAW),
84 "Metadata type RAW mismatch with legacy");
85static_assert(RADIO_METADATA_TYPE_CLOCK == static_cast<int>(MetadataType::CLOCK),
86 "Metadata type CLOCK mismatch with legacy");
87
88static_assert(RADIO_METADATA_KEY_INVALID == static_cast<int>(MetadataKey::INVALID),
89 "Metadata key INVALID mismatch with legacy");
90static_assert(RADIO_METADATA_KEY_RDS_PI == static_cast<int>(MetadataKey::RDS_PI),
91 "Metadata key RDS_PI mismatch with legacy");
92static_assert(RADIO_METADATA_KEY_RDS_PS == static_cast<int>(MetadataKey::RDS_PS),
93 "Metadata key RDS_PS mismatch with legacy");
94static_assert(RADIO_METADATA_KEY_RDS_PTY == static_cast<int>(MetadataKey::RDS_PTY),
95 "Metadata key RDS_PTY mismatch with legacy");
96static_assert(RADIO_METADATA_KEY_RBDS_PTY == static_cast<int>(MetadataKey::RBDS_PTY),
97 "Metadata key RBDS_PTY mismatch with legacy");
98static_assert(RADIO_METADATA_KEY_RDS_RT == static_cast<int>(MetadataKey::RDS_RT),
99 "Metadata key RDS_RT mismatch with legacy");
100static_assert(RADIO_METADATA_KEY_TITLE == static_cast<int>(MetadataKey::TITLE),
101 "Metadata key TITLE mismatch with legacy");
102static_assert(RADIO_METADATA_KEY_ARTIST == static_cast<int>(MetadataKey::ARTIST),
103 "Metadata key ARTIST mismatch with legacy");
104static_assert(RADIO_METADATA_KEY_ALBUM == static_cast<int>(MetadataKey::ALBUM),
105 "Metadata key ALBUM mismatch with legacy");
106static_assert(RADIO_METADATA_KEY_GENRE == static_cast<int>(MetadataKey::GENRE),
107 "Metadata key GENRE mismatch with legacy");
108static_assert(RADIO_METADATA_KEY_ICON == static_cast<int>(MetadataKey::ICON),
109 "Metadata key ICON mismatch with legacy");
110static_assert(RADIO_METADATA_KEY_ART == static_cast<int>(MetadataKey::ART),
111 "Metadata key ART mismatch with legacy");
112static_assert(RADIO_METADATA_KEY_CLOCK == static_cast<int>(MetadataKey::CLOCK),
113 "Metadata key CLOCK mismatch with legacy");
114
115
116//static
117const char * Utils::getClassString(Class ClassId)
118{
119 int id = static_cast<int>(ClassId);
120
121 if ((id < 0) ||
122 (id >= NELEM(sClassModuleNames))) {
123 ALOGE("invalid class ID %d", id);
124 return NULL;
125 }
126 return sClassModuleNames[id];
127}
128
129//static
130Result Utils::convertHalResult(int rc)
131{
132 switch (rc) {
133 case 0:
134 return Result::OK;
135 case -EINVAL:
136 return Result::INVALID_ARGUMENTS;
137 case -ENOSYS:
138 return Result::INVALID_STATE;
139 case -ETIMEDOUT:
140 return Result::TIMEOUT;
141 case -ENODEV:
142 default:
143 return Result::NOT_INITIALIZED;
144 }
145}
146
147//static
148void Utils::convertBandConfigFromHal(
149 BandConfig *config,
150 const radio_hal_band_config_t *halConfig)
151{
152
153 config->type = static_cast<Band>(halConfig->type);
154 config->antennaConnected = halConfig->antenna_connected;
155 config->lowerLimit = halConfig->lower_limit;
156 config->upperLimit = halConfig->upper_limit;
157 config->spacings.setToExternal(const_cast<unsigned int *>(&halConfig->spacings[0]),
158 halConfig->num_spacings * sizeof(uint32_t));
159 // FIXME: transfer buffer ownership. should have a method for that in hidl_vec
160 config->spacings.resize(halConfig->num_spacings);
161
162 if (config->type == Band::FM) {
163 config->ext.fm.deemphasis = static_cast<Deemphasis>(halConfig->fm.deemphasis);
164 config->ext.fm.stereo = halConfig->fm.stereo;
165 config->ext.fm.rds = static_cast<Rds>(halConfig->fm.rds);
166 config->ext.fm.ta = halConfig->fm.ta;
167 config->ext.fm.af = halConfig->fm.af;
168 config->ext.fm.ea = halConfig->fm.ea;
169 } else {
170 config->ext.am.stereo = halConfig->am.stereo;
171 }
172}
173
174//static
175void Utils::convertPropertiesFromHal(Properties *properties,
176 const radio_hal_properties_t *halProperties)
177{
178 properties->classId = static_cast<Class>(halProperties->class_id);
179 properties->implementor.setToExternal(halProperties->implementor, strlen(halProperties->implementor));
180 properties->product.setToExternal(halProperties->product, strlen(halProperties->product));
181 properties->version.setToExternal(halProperties->version, strlen(halProperties->version));
182 properties->serial.setToExternal(halProperties->serial, strlen(halProperties->serial));
183 properties->numTuners = halProperties->num_tuners;
184 properties->numAudioSources = halProperties->num_audio_sources;
185 properties->supportsCapture = halProperties->supports_capture;
186
187 BandConfig *bands =
188 new BandConfig[halProperties->num_bands];
189 for (size_t i = 0; i < halProperties->num_bands; i++) {
190 convertBandConfigFromHal(&bands[i], &halProperties->bands[i]);
191 }
192 properties->bands.setToExternal(bands, halProperties->num_bands);
193 // FIXME: transfer buffer ownership. should have a method for that in hidl_vec
194 properties->bands.resize(halProperties->num_bands);
195 delete[] bands;
196}
197
198//static
199void Utils::convertBandConfigToHal(radio_hal_band_config_t *halConfig, const BandConfig *config)
200{
201 halConfig->type = static_cast<radio_band_t>(config->type);
202 halConfig->antenna_connected = config->antennaConnected;
203 halConfig->lower_limit = config->lowerLimit;
204 halConfig->upper_limit = config->upperLimit;
205 halConfig->num_spacings = config->spacings.size();
206 if (halConfig->num_spacings > RADIO_NUM_SPACINGS_MAX) {
207 halConfig->num_spacings = RADIO_NUM_SPACINGS_MAX;
208 }
209 memcpy(halConfig->spacings, config->spacings.data(),
210 sizeof(uint32_t) * halConfig->num_spacings);
211
212 if (config->type == Band::FM) {
213 halConfig->fm.deemphasis = static_cast<radio_deemphasis_t>(config->ext.fm.deemphasis);
214 halConfig->fm.stereo = config->ext.fm.stereo;
215 halConfig->fm.rds = static_cast<radio_rds_t>(config->ext.fm.rds);
216 halConfig->fm.ta = config->ext.fm.ta;
217 halConfig->fm.af = config->ext.fm.af;
218 halConfig->fm.ea = config->ext.fm.ea;
219 } else {
220 halConfig->am.stereo = config->ext.am.stereo;
221 }
222}
223
224
225//static
226void Utils::convertProgramInfoFromHal(ProgramInfo *info, radio_program_info_t *halInfo)
227{
228 auto &info_1_1 = *info;
229 auto &info_1_0 = info->base;
230
231 info_1_0.channel = halInfo->channel;
232 info_1_0.subChannel = halInfo->sub_channel;
233 info_1_0.tuned = halInfo->tuned;
234 info_1_0.stereo = halInfo->stereo;
235 info_1_0.digital = halInfo->digital;
236 info_1_0.signalStrength = halInfo->signal_strength;
237 convertMetaDataFromHal(info_1_0.metadata, halInfo->metadata);
238 // TODO(b/34348946): add support for HAL 1.1 fields
Tomasz Wasilczykc466b492017-03-01 12:03:14 -0800239 info_1_1.flags = 0;
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800240}
241
242//static
243int Utils::convertMetaDataFromHal(hidl_vec<MetaData>& metadata, radio_metadata_t *halMetadata)
244{
245 if (halMetadata == NULL) {
246 ALOGE("Invalid argument: halMetadata is NULL");
247 return 0;
248 }
249
250 int count = radio_metadata_get_count(halMetadata);
251 if (count <= 0) {
252 return count;
253 }
254 MetaData *newMetadata = new MetaData[count];
255 int outCount = 0;
256 for (int i = 0; i < count; i++) {
257 radio_metadata_key_t key;
258 radio_metadata_type_t type;
259 void *value;
260 size_t size;
261 if (radio_metadata_get_at_index(halMetadata, i , &key, &type, &value, &size) != 0 ||
262 size == 0) {
263 continue;
264 }
265 switch (type) {
266 case RADIO_METADATA_TYPE_INT: {
267 newMetadata[outCount].intValue = *(static_cast<int32_t *>(value));
268 } break;
269 case RADIO_METADATA_TYPE_TEXT: {
270 newMetadata[outCount].stringValue = static_cast<char *>(value);
271 } break;
272 case RADIO_METADATA_TYPE_RAW: {
273 newMetadata[outCount].rawValue.setToExternal(static_cast<uint8_t *>(value), size);
274 // FIXME: transfer buffer ownership. should have a method for that in hidl_vec
275 newMetadata[outCount].rawValue.resize(size);
276 } break;
277 case RADIO_METADATA_TYPE_CLOCK: {
278 radio_metadata_clock_t *clock = static_cast<radio_metadata_clock_t *>(value);
279 newMetadata[outCount].clockValue.utcSecondsSinceEpoch =
280 clock->utc_seconds_since_epoch;
281 newMetadata[outCount].clockValue.timezoneOffsetInMinutes =
282 clock->timezone_offset_in_minutes;
283 } break;
284 }
285 newMetadata[outCount].type = static_cast<MetadataType>(type);
286 newMetadata[outCount].key = static_cast<MetadataKey>(key);
287 outCount++;
288 }
289 metadata.setToExternal(newMetadata, outCount);
290 // FIXME: transfer buffer ownership. should have a method for that in hidl_vec
291 metadata.resize(outCount);
292 return outCount;
293}
294
295} // namespace implementation
296} // namespace V1_1
297} // namespace broadcastradio
298} // namespace hardware
299} // namespace android