1 /* 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 <log/log.h> 20 #include <utils/misc.h> 21 #include <system/radio_metadata.h> 22 23 #include "Utils.h" 24 25 namespace android { 26 namespace hardware { 27 namespace broadcastradio { 28 namespace V1_0 { 29 namespace implementation { 30 31 const 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 38 static_assert(RADIO_CLASS_AM_FM == static_cast<int>(Class::AM_FM), 39 "AM/FM class mismatch with legacy"); 40 static_assert(RADIO_CLASS_SAT == static_cast<int>(Class::SAT), 41 "SAT class mismatch with legacy"); 42 static_assert(RADIO_CLASS_DT == static_cast<int>(Class::DT), 43 "DT class mismatch with legacy"); 44 45 static_assert(RADIO_BAND_AM == static_cast<int>(Band::AM), 46 "AM band mismatch with legacy"); 47 static_assert(RADIO_BAND_FM == static_cast<int>(Band::FM), 48 "FM band mismatch with legacy"); 49 static_assert(RADIO_BAND_AM_HD == static_cast<int>(Band::AM_HD), 50 "AM HD band mismatch with legacy"); 51 static_assert(RADIO_BAND_FM_HD == static_cast<int>(Band::FM_HD), 52 "FM HD band mismatch with legacy"); 53 54 static_assert(RADIO_RDS_NONE == static_cast<int>(Rds::NONE), 55 "RDS NONE mismatch with legacy"); 56 static_assert(RADIO_RDS_WORLD == static_cast<int>(Rds::WORLD), 57 "RDS WORLD mismatch with legacy"); 58 static_assert(RADIO_RDS_US == static_cast<int>(Rds::US), 59 "RDS US mismatch with legacy"); 60 61 static_assert(RADIO_DEEMPHASIS_50 == static_cast<int>(Deemphasis::D50), 62 "De-emphasis 50 mismatch with legacy"); 63 static_assert(RADIO_DEEMPHASIS_75 == static_cast<int>(Deemphasis::D75), 64 "De-emphasis 75 mismatch with legacy"); 65 66 static_assert(RADIO_DIRECTION_UP == static_cast<int>(Direction::UP), 67 "Direction Up mismatch with legacy"); 68 static_assert(RADIO_DIRECTION_DOWN == static_cast<int>(Direction::DOWN), 69 "Direction Up mismatch with legacy"); 70 71 static_assert(RADIO_METADATA_TYPE_INVALID == static_cast<int>(MetadataType::INVALID), 72 "Metadata type INVALID mismatch with legacy"); 73 static_assert(RADIO_METADATA_TYPE_INT == static_cast<int>(MetadataType::INT), 74 "Metadata type INT mismatch with legacy"); 75 static_assert(RADIO_METADATA_TYPE_TEXT == static_cast<int>(MetadataType::TEXT), 76 "Metadata type TEXT mismatch with legacy"); 77 static_assert(RADIO_METADATA_TYPE_RAW == static_cast<int>(MetadataType::RAW), 78 "Metadata type RAW mismatch with legacy"); 79 static_assert(RADIO_METADATA_TYPE_CLOCK == static_cast<int>(MetadataType::CLOCK), 80 "Metadata type CLOCK mismatch with legacy"); 81 82 static_assert(RADIO_METADATA_KEY_INVALID == static_cast<int>(MetadataKey::INVALID), 83 "Metadata key INVALID mismatch with legacy"); 84 static_assert(RADIO_METADATA_KEY_RDS_PI == static_cast<int>(MetadataKey::RDS_PI), 85 "Metadata key RDS_PI mismatch with legacy"); 86 static_assert(RADIO_METADATA_KEY_RDS_PS == static_cast<int>(MetadataKey::RDS_PS), 87 "Metadata key RDS_PS mismatch with legacy"); 88 static_assert(RADIO_METADATA_KEY_RDS_PTY == static_cast<int>(MetadataKey::RDS_PTY), 89 "Metadata key RDS_PTY mismatch with legacy"); 90 static_assert(RADIO_METADATA_KEY_RBDS_PTY == static_cast<int>(MetadataKey::RBDS_PTY), 91 "Metadata key RBDS_PTY mismatch with legacy"); 92 static_assert(RADIO_METADATA_KEY_RDS_RT == static_cast<int>(MetadataKey::RDS_RT), 93 "Metadata key RDS_RT mismatch with legacy"); 94 static_assert(RADIO_METADATA_KEY_TITLE == static_cast<int>(MetadataKey::TITLE), 95 "Metadata key TITLE mismatch with legacy"); 96 static_assert(RADIO_METADATA_KEY_ARTIST == static_cast<int>(MetadataKey::ARTIST), 97 "Metadata key ARTIST mismatch with legacy"); 98 static_assert(RADIO_METADATA_KEY_ALBUM == static_cast<int>(MetadataKey::ALBUM), 99 "Metadata key ALBUM mismatch with legacy"); 100 static_assert(RADIO_METADATA_KEY_GENRE == static_cast<int>(MetadataKey::GENRE), 101 "Metadata key GENRE mismatch with legacy"); 102 static_assert(RADIO_METADATA_KEY_ICON == static_cast<int>(MetadataKey::ICON), 103 "Metadata key ICON mismatch with legacy"); 104 static_assert(RADIO_METADATA_KEY_ART == static_cast<int>(MetadataKey::ART), 105 "Metadata key ART mismatch with legacy"); 106 static_assert(RADIO_METADATA_KEY_CLOCK == static_cast<int>(MetadataKey::CLOCK), 107 "Metadata key CLOCK mismatch with legacy"); 108 109 110 //static 111 const 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 124 Result 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 142 void 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 169 void 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 194 void 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 224 void Utils::convertProgramInfoFromHal(ProgramInfo *info, 225 radio_program_info_t *halInfo) 226 { 227 info->channel = halInfo->channel; 228 info->subChannel = halInfo->sub_channel; 229 info->tuned = halInfo->tuned; 230 info->stereo = halInfo->stereo; 231 info->digital = halInfo->digital; 232 info->signalStrength = halInfo->signal_strength; 233 convertMetaDataFromHal(info->metadata, halInfo->metadata); 234 } 235 236 //static 237 int Utils::convertMetaDataFromHal(hidl_vec<MetaData>& metadata, 238 radio_metadata_t *halMetadata) 239 { 240 if (halMetadata == NULL) { 241 ALOGE("Invalid argument: halMetadata is NULL"); 242 return 0; 243 } 244 245 int count = radio_metadata_get_count(halMetadata); 246 if (count <= 0) { 247 return count; 248 } 249 MetaData *newMetadata = 250 new MetaData[count]; 251 int outCount = 0; 252 for (int i = 0; i < count; i++) { 253 radio_metadata_key_t key; 254 radio_metadata_type_t type; 255 void *value; 256 size_t size; 257 if (radio_metadata_get_at_index(halMetadata, i , &key, &type, &value, &size) != 0 || 258 size == 0) { 259 continue; 260 } 261 switch (type) { 262 case RADIO_METADATA_TYPE_INT: { 263 newMetadata[outCount].intValue = *(static_cast<int32_t *>(value)); 264 } break; 265 case RADIO_METADATA_TYPE_TEXT: { 266 newMetadata[outCount].stringValue = static_cast<char *>(value); 267 } break; 268 case RADIO_METADATA_TYPE_RAW: { 269 newMetadata[outCount].rawValue.setToExternal(static_cast<uint8_t *>(value), size); 270 // FIXME: transfer buffer ownership. should have a method for that in hidl_vec 271 newMetadata[outCount].rawValue.resize(size); 272 } break; 273 case RADIO_METADATA_TYPE_CLOCK: { 274 radio_metadata_clock_t *clock = static_cast<radio_metadata_clock_t *>(value); 275 newMetadata[outCount].clockValue.utcSecondsSinceEpoch = 276 clock->utc_seconds_since_epoch; 277 newMetadata[outCount].clockValue.timezoneOffsetInMinutes = 278 clock->timezone_offset_in_minutes; 279 } break; 280 } 281 newMetadata[outCount].type = static_cast<MetadataType>(type); 282 newMetadata[outCount].key = static_cast<MetadataKey>(key); 283 outCount++; 284 } 285 metadata.setToExternal(newMetadata, outCount); 286 // FIXME: transfer buffer ownership. should have a method for that in hidl_vec 287 metadata.resize(outCount); 288 return outCount; 289 } 290 291 } // namespace implementation 292 } // namespace V1_0 293 } // namespace broadcastradio 294 } // namespace hardware 295 } // namespace android 296