You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
295 lines
12 KiB
295 lines
12 KiB
/* |
|
* Copyright (C) 2016 The Android Open Source Project |
|
* |
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
* you may not use this file except in compliance with the License. |
|
* You may obtain a copy of the License at |
|
* |
|
* http://www.apache.org/licenses/LICENSE-2.0 |
|
* |
|
* Unless required by applicable law or agreed to in writing, software |
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
* See the License for the specific language governing permissions and |
|
* limitations under the License. |
|
*/ |
|
#define LOG_TAG "BroadcastRadioHalUtils" |
|
//#define LOG_NDEBUG 0 |
|
|
|
#include <log/log.h> |
|
#include <utils/misc.h> |
|
#include <system/radio_metadata.h> |
|
|
|
#include "Utils.h" |
|
|
|
namespace android { |
|
namespace hardware { |
|
namespace broadcastradio { |
|
namespace V1_0 { |
|
namespace implementation { |
|
|
|
const char *Utils::sClassModuleNames[] = { |
|
RADIO_HARDWARE_MODULE_ID_FM, /* corresponds to RADIO_CLASS_AM_FM */ |
|
RADIO_HARDWARE_MODULE_ID_SAT, /* corresponds to RADIO_CLASS_SAT */ |
|
RADIO_HARDWARE_MODULE_ID_DT, /* corresponds to RADIO_CLASS_DT */ |
|
}; |
|
|
|
// make sure HIDL enum values are aligned with legacy values |
|
static_assert(RADIO_CLASS_AM_FM == static_cast<int>(Class::AM_FM), |
|
"AM/FM class mismatch with legacy"); |
|
static_assert(RADIO_CLASS_SAT == static_cast<int>(Class::SAT), |
|
"SAT class mismatch with legacy"); |
|
static_assert(RADIO_CLASS_DT == static_cast<int>(Class::DT), |
|
"DT class mismatch with legacy"); |
|
|
|
static_assert(RADIO_BAND_AM == static_cast<int>(Band::AM), |
|
"AM band mismatch with legacy"); |
|
static_assert(RADIO_BAND_FM == static_cast<int>(Band::FM), |
|
"FM band mismatch with legacy"); |
|
static_assert(RADIO_BAND_AM_HD == static_cast<int>(Band::AM_HD), |
|
"AM HD band mismatch with legacy"); |
|
static_assert(RADIO_BAND_FM_HD == static_cast<int>(Band::FM_HD), |
|
"FM HD band mismatch with legacy"); |
|
|
|
static_assert(RADIO_RDS_NONE == static_cast<int>(Rds::NONE), |
|
"RDS NONE mismatch with legacy"); |
|
static_assert(RADIO_RDS_WORLD == static_cast<int>(Rds::WORLD), |
|
"RDS WORLD mismatch with legacy"); |
|
static_assert(RADIO_RDS_US == static_cast<int>(Rds::US), |
|
"RDS US mismatch with legacy"); |
|
|
|
static_assert(RADIO_DEEMPHASIS_50 == static_cast<int>(Deemphasis::D50), |
|
"De-emphasis 50 mismatch with legacy"); |
|
static_assert(RADIO_DEEMPHASIS_75 == static_cast<int>(Deemphasis::D75), |
|
"De-emphasis 75 mismatch with legacy"); |
|
|
|
static_assert(RADIO_DIRECTION_UP == static_cast<int>(Direction::UP), |
|
"Direction Up mismatch with legacy"); |
|
static_assert(RADIO_DIRECTION_DOWN == static_cast<int>(Direction::DOWN), |
|
"Direction Up mismatch with legacy"); |
|
|
|
static_assert(RADIO_METADATA_TYPE_INVALID == static_cast<int>(MetadataType::INVALID), |
|
"Metadata type INVALID mismatch with legacy"); |
|
static_assert(RADIO_METADATA_TYPE_INT == static_cast<int>(MetadataType::INT), |
|
"Metadata type INT mismatch with legacy"); |
|
static_assert(RADIO_METADATA_TYPE_TEXT == static_cast<int>(MetadataType::TEXT), |
|
"Metadata type TEXT mismatch with legacy"); |
|
static_assert(RADIO_METADATA_TYPE_RAW == static_cast<int>(MetadataType::RAW), |
|
"Metadata type RAW mismatch with legacy"); |
|
static_assert(RADIO_METADATA_TYPE_CLOCK == static_cast<int>(MetadataType::CLOCK), |
|
"Metadata type CLOCK mismatch with legacy"); |
|
|
|
static_assert(RADIO_METADATA_KEY_INVALID == static_cast<int>(MetadataKey::INVALID), |
|
"Metadata key INVALID mismatch with legacy"); |
|
static_assert(RADIO_METADATA_KEY_RDS_PI == static_cast<int>(MetadataKey::RDS_PI), |
|
"Metadata key RDS_PI mismatch with legacy"); |
|
static_assert(RADIO_METADATA_KEY_RDS_PS == static_cast<int>(MetadataKey::RDS_PS), |
|
"Metadata key RDS_PS mismatch with legacy"); |
|
static_assert(RADIO_METADATA_KEY_RDS_PTY == static_cast<int>(MetadataKey::RDS_PTY), |
|
"Metadata key RDS_PTY mismatch with legacy"); |
|
static_assert(RADIO_METADATA_KEY_RBDS_PTY == static_cast<int>(MetadataKey::RBDS_PTY), |
|
"Metadata key RBDS_PTY mismatch with legacy"); |
|
static_assert(RADIO_METADATA_KEY_RDS_RT == static_cast<int>(MetadataKey::RDS_RT), |
|
"Metadata key RDS_RT mismatch with legacy"); |
|
static_assert(RADIO_METADATA_KEY_TITLE == static_cast<int>(MetadataKey::TITLE), |
|
"Metadata key TITLE mismatch with legacy"); |
|
static_assert(RADIO_METADATA_KEY_ARTIST == static_cast<int>(MetadataKey::ARTIST), |
|
"Metadata key ARTIST mismatch with legacy"); |
|
static_assert(RADIO_METADATA_KEY_ALBUM == static_cast<int>(MetadataKey::ALBUM), |
|
"Metadata key ALBUM mismatch with legacy"); |
|
static_assert(RADIO_METADATA_KEY_GENRE == static_cast<int>(MetadataKey::GENRE), |
|
"Metadata key GENRE mismatch with legacy"); |
|
static_assert(RADIO_METADATA_KEY_ICON == static_cast<int>(MetadataKey::ICON), |
|
"Metadata key ICON mismatch with legacy"); |
|
static_assert(RADIO_METADATA_KEY_ART == static_cast<int>(MetadataKey::ART), |
|
"Metadata key ART mismatch with legacy"); |
|
static_assert(RADIO_METADATA_KEY_CLOCK == static_cast<int>(MetadataKey::CLOCK), |
|
"Metadata key CLOCK mismatch with legacy"); |
|
|
|
|
|
//static |
|
const char * Utils::getClassString(Class ClassId) |
|
{ |
|
int id = static_cast<int>(ClassId); |
|
|
|
if ((id < 0) || |
|
(id >= NELEM(sClassModuleNames))) { |
|
ALOGE("invalid class ID %d", id); |
|
return NULL; |
|
} |
|
return sClassModuleNames[id]; |
|
} |
|
|
|
//static |
|
Result Utils::convertHalResult(int rc) |
|
{ |
|
switch (rc) { |
|
case 0: |
|
return Result::OK; |
|
case -EINVAL: |
|
return Result::INVALID_ARGUMENTS; |
|
case -ENOSYS: |
|
return Result::INVALID_STATE; |
|
case -ETIMEDOUT: |
|
return Result::TIMEOUT; |
|
case -ENODEV: |
|
default: |
|
return Result::NOT_INITIALIZED; |
|
} |
|
} |
|
|
|
//static |
|
void Utils::convertBandConfigFromHal( |
|
BandConfig *config, |
|
const radio_hal_band_config_t *halConfig) |
|
{ |
|
|
|
config->type = static_cast<Band>(halConfig->type); |
|
config->antennaConnected = halConfig->antenna_connected; |
|
config->lowerLimit = halConfig->lower_limit; |
|
config->upperLimit = halConfig->upper_limit; |
|
config->spacings.setToExternal(const_cast<unsigned int *>(&halConfig->spacings[0]), |
|
halConfig->num_spacings * sizeof(uint32_t)); |
|
// FIXME: transfer buffer ownership. should have a method for that in hidl_vec |
|
config->spacings.resize(halConfig->num_spacings); |
|
|
|
if (config->type == Band::FM) { |
|
config->ext.fm.deemphasis = static_cast<Deemphasis>(halConfig->fm.deemphasis); |
|
config->ext.fm.stereo = halConfig->fm.stereo; |
|
config->ext.fm.rds = static_cast<Rds>(halConfig->fm.rds); |
|
config->ext.fm.ta = halConfig->fm.ta; |
|
config->ext.fm.af = halConfig->fm.af; |
|
config->ext.fm.ea = halConfig->fm.ea; |
|
} else { |
|
config->ext.am.stereo = halConfig->am.stereo; |
|
} |
|
} |
|
|
|
//static |
|
void Utils::convertPropertiesFromHal( |
|
Properties *properties, |
|
const radio_hal_properties_t *halProperties) |
|
{ |
|
properties->classId = static_cast<Class>(halProperties->class_id); |
|
properties->implementor.setToExternal(halProperties->implementor, strlen(halProperties->implementor)); |
|
properties->product.setToExternal(halProperties->product, strlen(halProperties->product)); |
|
properties->version.setToExternal(halProperties->version, strlen(halProperties->version)); |
|
properties->serial.setToExternal(halProperties->serial, strlen(halProperties->serial)); |
|
properties->numTuners = halProperties->num_tuners; |
|
properties->numAudioSources = halProperties->num_audio_sources; |
|
properties->supportsCapture = halProperties->supports_capture; |
|
|
|
BandConfig *bands = |
|
new BandConfig[halProperties->num_bands]; |
|
for (size_t i = 0; i < halProperties->num_bands; i++) { |
|
convertBandConfigFromHal(&bands[i], &halProperties->bands[i]); |
|
} |
|
properties->bands.setToExternal(bands, halProperties->num_bands); |
|
// FIXME: transfer buffer ownership. should have a method for that in hidl_vec |
|
properties->bands.resize(halProperties->num_bands); |
|
delete[] bands; |
|
} |
|
|
|
//static |
|
void Utils::convertBandConfigToHal( |
|
radio_hal_band_config_t *halConfig, |
|
const BandConfig *config) |
|
{ |
|
|
|
halConfig->type = static_cast<radio_band_t>(config->type); |
|
halConfig->antenna_connected = config->antennaConnected; |
|
halConfig->lower_limit = config->lowerLimit; |
|
halConfig->upper_limit = config->upperLimit; |
|
halConfig->num_spacings = config->spacings.size(); |
|
if (halConfig->num_spacings > RADIO_NUM_SPACINGS_MAX) { |
|
halConfig->num_spacings = RADIO_NUM_SPACINGS_MAX; |
|
} |
|
memcpy(halConfig->spacings, config->spacings.data(), |
|
sizeof(uint32_t) * halConfig->num_spacings); |
|
|
|
if (config->type == Band::FM) { |
|
halConfig->fm.deemphasis = static_cast<radio_deemphasis_t>(config->ext.fm.deemphasis); |
|
halConfig->fm.stereo = config->ext.fm.stereo; |
|
halConfig->fm.rds = static_cast<radio_rds_t>(config->ext.fm.rds); |
|
halConfig->fm.ta = config->ext.fm.ta; |
|
halConfig->fm.af = config->ext.fm.af; |
|
halConfig->fm.ea = config->ext.fm.ea; |
|
} else { |
|
halConfig->am.stereo = config->ext.am.stereo; |
|
} |
|
} |
|
|
|
|
|
//static |
|
void Utils::convertProgramInfoFromHal(ProgramInfo *info, |
|
radio_program_info_t *halInfo) |
|
{ |
|
info->channel = halInfo->channel; |
|
info->subChannel = halInfo->sub_channel; |
|
info->tuned = halInfo->tuned; |
|
info->stereo = halInfo->stereo; |
|
info->digital = halInfo->digital; |
|
info->signalStrength = halInfo->signal_strength; |
|
convertMetaDataFromHal(info->metadata, halInfo->metadata); |
|
} |
|
|
|
//static |
|
int Utils::convertMetaDataFromHal(hidl_vec<MetaData>& metadata, |
|
radio_metadata_t *halMetadata) |
|
{ |
|
if (halMetadata == NULL) { |
|
ALOGE("Invalid argument: halMetadata is NULL"); |
|
return 0; |
|
} |
|
|
|
int count = radio_metadata_get_count(halMetadata); |
|
if (count <= 0) { |
|
return count; |
|
} |
|
MetaData *newMetadata = |
|
new MetaData[count]; |
|
int outCount = 0; |
|
for (int i = 0; i < count; i++) { |
|
radio_metadata_key_t key; |
|
radio_metadata_type_t type; |
|
void *value; |
|
size_t size; |
|
if (radio_metadata_get_at_index(halMetadata, i , &key, &type, &value, &size) != 0 || |
|
size == 0) { |
|
continue; |
|
} |
|
switch (type) { |
|
case RADIO_METADATA_TYPE_INT: { |
|
newMetadata[outCount].intValue = *(static_cast<int32_t *>(value)); |
|
} break; |
|
case RADIO_METADATA_TYPE_TEXT: { |
|
newMetadata[outCount].stringValue = static_cast<char *>(value); |
|
} break; |
|
case RADIO_METADATA_TYPE_RAW: { |
|
newMetadata[outCount].rawValue.setToExternal(static_cast<uint8_t *>(value), size); |
|
// FIXME: transfer buffer ownership. should have a method for that in hidl_vec |
|
newMetadata[outCount].rawValue.resize(size); |
|
} break; |
|
case RADIO_METADATA_TYPE_CLOCK: { |
|
radio_metadata_clock_t *clock = static_cast<radio_metadata_clock_t *>(value); |
|
newMetadata[outCount].clockValue.utcSecondsSinceEpoch = |
|
clock->utc_seconds_since_epoch; |
|
newMetadata[outCount].clockValue.timezoneOffsetInMinutes = |
|
clock->timezone_offset_in_minutes; |
|
} break; |
|
} |
|
newMetadata[outCount].type = static_cast<MetadataType>(type); |
|
newMetadata[outCount].key = static_cast<MetadataKey>(key); |
|
outCount++; |
|
} |
|
metadata.setToExternal(newMetadata, outCount); |
|
// FIXME: transfer buffer ownership. should have a method for that in hidl_vec |
|
metadata.resize(outCount); |
|
return outCount; |
|
} |
|
|
|
} // namespace implementation |
|
} // namespace V1_0 |
|
} // namespace broadcastradio |
|
} // namespace hardware |
|
} // namespace android
|
|
|