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