diff options
author | Eric Laurent <elaurent@google.com> | 2016-11-21 10:41:22 -0800 |
---|---|---|
committer | Eric Laurent <elaurent@google.com> | 2016-11-21 10:41:22 -0800 |
commit | a174588f8d2bb17cd0eb90ff3ed2700c000c8d65 (patch) | |
tree | 737a195ce9fb615bb017f60d9b76f43029080f2b /broadcastradio/1.0 | |
parent | 0b855f81c8928b5f48e20274a15f032475872be2 (diff) | |
download | android_hardware_interfaces-a174588f8d2bb17cd0eb90ff3ed2700c000c8d65.tar.gz android_hardware_interfaces-a174588f8d2bb17cd0eb90ff3ed2700c000c8d65.tar.bz2 android_hardware_interfaces-a174588f8d2bb17cd0eb90ff3ed2700c000c8d65.zip |
Revert "Revert "Initial implementation of broadcast radio HAL.""
This reverts commit 2c2df013b25bd96976af82db7e6f3480f0571c6e.
Diffstat (limited to 'broadcastradio/1.0')
-rw-r--r-- | broadcastradio/1.0/ITunerCallback.hal | 6 | ||||
-rw-r--r-- | broadcastradio/1.0/default/Android.mk | 27 | ||||
-rw-r--r-- | broadcastradio/1.0/default/BroadcastRadio.cpp | 141 | ||||
-rw-r--r-- | broadcastradio/1.0/default/BroadcastRadio.h | 71 | ||||
-rw-r--r-- | broadcastradio/1.0/default/BroadcastRadioFactory.cpp | 45 | ||||
-rw-r--r-- | broadcastradio/1.0/default/BroadcastRadioFactory.h | 43 | ||||
-rw-r--r-- | broadcastradio/1.0/default/Tuner.cpp | 199 | ||||
-rw-r--r-- | broadcastradio/1.0/default/Tuner.h | 67 | ||||
-rw-r--r-- | broadcastradio/1.0/default/Utils.cpp | 297 | ||||
-rw-r--r-- | broadcastradio/1.0/default/Utils.h | 54 | ||||
-rw-r--r-- | broadcastradio/1.0/types.hal | 4 |
11 files changed, 950 insertions, 4 deletions
diff --git a/broadcastradio/1.0/ITunerCallback.hal b/broadcastradio/1.0/ITunerCallback.hal index f80547231..a7e126020 100644 --- a/broadcastradio/1.0/ITunerCallback.hal +++ b/broadcastradio/1.0/ITunerCallback.hal @@ -72,7 +72,9 @@ interface ITunerCallback { /* * Method called by the HAL when metadata for current station * are updated. - * @param metadatas A list of all updated metada. + * @param channel The channel the metadata is associated with. + * @param subChannel The sub channel the metadata is associated with. + * @param metadata A list of all updated metada. */ - oneway newMetadata(vec<MetaData> metadatas); + oneway newMetadata(uint32_t channel, uint32_t subChannel, vec<MetaData> metadata); };
\ No newline at end of file diff --git a/broadcastradio/1.0/default/Android.mk b/broadcastradio/1.0/default/Android.mk new file mode 100644 index 000000000..843b8debc --- /dev/null +++ b/broadcastradio/1.0/default/Android.mk @@ -0,0 +1,27 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE := android.hardware.broadcastradio@1.0-impl +LOCAL_MODULE_RELATIVE_PATH := hw +LOCAL_SRC_FILES := \ + BroadcastRadio.cpp \ + BroadcastRadioFactory.cpp \ + Tuner.cpp \ + Utils.cpp + +LOCAL_SHARED_LIBRARIES := \ + libhidl \ + libhwbinder \ + libutils \ + liblog \ + libhardware \ + android.hardware.broadcastradio@1.0 \ + libradio_metadata + +ifeq ($(strip $(AUDIOSERVER_MULTILIB)),) +LOCAL_MULTILIB := 32 +else +LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB) +endif + +include $(BUILD_SHARED_LIBRARY) diff --git a/broadcastradio/1.0/default/BroadcastRadio.cpp b/broadcastradio/1.0/default/BroadcastRadio.cpp new file mode 100644 index 000000000..b97b6095a --- /dev/null +++ b/broadcastradio/1.0/default/BroadcastRadio.cpp @@ -0,0 +1,141 @@ +/* + * 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 "BroadcastRadio" +//#define LOG_NDEBUG 0 + +#include <utils/Log.h> +#include <hardware/radio.h> + +#include "BroadcastRadio.h" +#include "Tuner.h" +#include "Utils.h" + +namespace android { +namespace hardware { +namespace broadcastradio { +namespace V1_0 { +namespace implementation { + +BroadcastRadio::BroadcastRadio(Class classId) + : mStatus(Result::NOT_INITIALIZED), mClassId(classId), mHwDevice(NULL) +{ +} + +BroadcastRadio::~BroadcastRadio() +{ + if (mHwDevice != NULL) { + radio_hw_device_close(mHwDevice); + } +} + +void BroadcastRadio::onFirstRef() +{ + const hw_module_t *mod; + int rc; + ALOGI("%s mClassId %d", __FUNCTION__, mClassId); + + mHwDevice = NULL; + const char *classString = Utils::getClassString(mClassId); + if (classString == NULL) { + ALOGE("invalid class ID %d", mClassId); + mStatus = Result::INVALID_ARGUMENTS; + return; + } + + ALOGI("%s RADIO_HARDWARE_MODULE_ID %s %s", + __FUNCTION__, RADIO_HARDWARE_MODULE_ID, classString); + + rc = hw_get_module_by_class(RADIO_HARDWARE_MODULE_ID, classString, &mod); + if (rc != 0) { + ALOGE("couldn't load radio module %s.%s (%s)", + RADIO_HARDWARE_MODULE_ID, classString, strerror(-rc)); + return; + } + rc = radio_hw_device_open(mod, &mHwDevice); + if (rc != 0) { + ALOGE("couldn't open radio hw device in %s.%s (%s)", + RADIO_HARDWARE_MODULE_ID, "primary", strerror(-rc)); + mHwDevice = NULL; + return; + } + if (mHwDevice->common.version != RADIO_DEVICE_API_VERSION_CURRENT) { + ALOGE("wrong radio hw device version %04x", mHwDevice->common.version); + radio_hw_device_close(mHwDevice); + mHwDevice = NULL; + } else { + mStatus = Result::OK; + } +} + +int BroadcastRadio::closeHalTuner(const struct radio_tuner *halTuner) +{ + ALOGV("%s", __FUNCTION__); + if (mHwDevice == NULL) { + return -ENODEV; + } + if (halTuner == 0) { + return -EINVAL; + } + return mHwDevice->close_tuner(mHwDevice, halTuner); +} + + +// Methods from ::android::hardware::broadcastradio::V1_0::IBroadcastRadio follow. +Return<void> BroadcastRadio::getProperties(getProperties_cb _hidl_cb) +{ + int rc; + radio_hal_properties_t halProperties; + Properties properties; + + if (mHwDevice == NULL) { + rc = -ENODEV; + goto exit; + } + rc = mHwDevice->get_properties(mHwDevice, &halProperties); + if (rc == 0) { + Utils::convertPropertiesFromHal(&properties, &halProperties); + } + +exit: + _hidl_cb(Utils::convertHalResult(rc), properties); + return Void(); +} + +Return<void> BroadcastRadio::openTuner(const BandConfig& config, bool audio, + const sp<ITunerCallback>& callback, openTuner_cb _hidl_cb) +{ + sp<Tuner> tunerImpl = new Tuner(callback, this); + + radio_hal_band_config_t halConfig; + const struct radio_tuner *halTuner; + Utils::convertBandConfigToHal(&halConfig, &config); + int rc = mHwDevice->open_tuner(mHwDevice, &halConfig, audio, + Tuner::callback, tunerImpl.get(), + &halTuner); + if (rc == 0) { + tunerImpl->setHalTuner(halTuner); + } + + _hidl_cb(Utils::convertHalResult(rc), tunerImpl); + return Void(); +} + + +} // namespace implementation +} // namespace V1_0 +} // namespace broadcastradio +} // namespace hardware +} // namespace android diff --git a/broadcastradio/1.0/default/BroadcastRadio.h b/broadcastradio/1.0/default/BroadcastRadio.h new file mode 100644 index 000000000..dbd6e0777 --- /dev/null +++ b/broadcastradio/1.0/default/BroadcastRadio.h @@ -0,0 +1,71 @@ +/* + * 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. + */ +#ifndef HIDL_GENERATED_android_hardware_broadcastradio_V1_0_BroadcastRadio_H_ +#define HIDL_GENERATED_android_hardware_broadcastradio_V1_0_BroadcastRadio_H_ + +#include <android/hardware/broadcastradio/1.0/IBroadcastRadio.h> +#include <hidl/Status.h> +#include <hardware/radio.h> + +#include <hidl/MQDescriptor.h> +namespace android { +namespace hardware { +namespace broadcastradio { +namespace V1_0 { +namespace implementation { + +struct BroadcastRadio : public IBroadcastRadio { + + BroadcastRadio(Class classId); + + // Methods from ::android::hardware::broadcastradio::V1_0::IBroadcastRadio follow. + Return<void> getProperties(getProperties_cb _hidl_cb) override; + Return<void> openTuner(const BandConfig& config, bool audio, + const sp<ITunerCallback>& callback, + openTuner_cb _hidl_cb) override; + + + // RefBase + virtual void onFirstRef(); + + Result initCheck() { return mStatus; } + int closeHalTuner(const struct radio_tuner *halTuner); + +private: + virtual ~BroadcastRadio(); + + static const char * sClassModuleNames[]; + + Result convertHalResult(int rc); + void convertBandConfigFromHal(BandConfig *config, + const radio_hal_band_config_t *halConfig); + void convertPropertiesFromHal(Properties *properties, + const radio_hal_properties_t *halProperties); + void convertBandConfigToHal(radio_hal_band_config_t *halConfig, + const BandConfig *config); + + Result mStatus; + Class mClassId; + struct radio_hw_device *mHwDevice; +}; + +} // namespace implementation +} // namespace V1_0 +} // namespace broadcastradio +} // namespace hardware +} // namespace android + +#endif // HIDL_GENERATED_android_hardware_broadcastradio_V1_0_BroadcastRadio_H_ diff --git a/broadcastradio/1.0/default/BroadcastRadioFactory.cpp b/broadcastradio/1.0/default/BroadcastRadioFactory.cpp new file mode 100644 index 000000000..d5d214c32 --- /dev/null +++ b/broadcastradio/1.0/default/BroadcastRadioFactory.cpp @@ -0,0 +1,45 @@ +/* + * 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. + */ +#include "BroadcastRadioFactory.h" +#include "BroadcastRadio.h" + +namespace android { +namespace hardware { +namespace broadcastradio { +namespace V1_0 { +namespace implementation { + +// Methods from ::android::hardware::broadcastradio::V1_0::IBroadcastRadioFactory follow. +Return<void> BroadcastRadioFactory::connectModule(Class classId, connectModule_cb _hidl_cb) { + sp<BroadcastRadio> impl = new BroadcastRadio(classId); + Result retval = Result::NOT_INITIALIZED; + if (impl != 0) { + retval = impl->initCheck(); + } + _hidl_cb(retval, impl); + return Void(); +} + + +IBroadcastRadioFactory* HIDL_FETCH_IBroadcastRadioFactory(const char* /* name */) { + return new BroadcastRadioFactory(); +} + +} // namespace implementation +} // namespace V1_0 +} // namespace broadcastradio +} // namespace hardware +} // namespace android diff --git a/broadcastradio/1.0/default/BroadcastRadioFactory.h b/broadcastradio/1.0/default/BroadcastRadioFactory.h new file mode 100644 index 000000000..9b2ca17ef --- /dev/null +++ b/broadcastradio/1.0/default/BroadcastRadioFactory.h @@ -0,0 +1,43 @@ +/* + * 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. + */ +#ifndef HIDL_GENERATED_android_hardware_broadcastradio_V1_0_BroadcastRadioFactory_H_ +#define HIDL_GENERATED_android_hardware_broadcastradio_V1_0_BroadcastRadioFactory_H_ + +#include <android/hardware/broadcastradio/1.0/IBroadcastRadioFactory.h> +#include <hidl/Status.h> + +#include <hidl/MQDescriptor.h> +namespace android { +namespace hardware { +namespace broadcastradio { +namespace V1_0 { +namespace implementation { + +struct BroadcastRadioFactory : public IBroadcastRadioFactory { + // Methods from ::android::hardware::broadcastradio::V1_0::IBroadcastRadioFactory follow. + Return<void> connectModule(Class classId, connectModule_cb _hidl_cb) override; + +}; + +extern "C" IBroadcastRadioFactory* HIDL_FETCH_IBroadcastRadioFactory(const char* name); + +} // namespace implementation +} // namespace V1_0 +} // namespace broadcastradio +} // namespace hardware +} // namespace android + +#endif // HIDL_GENERATED_android_hardware_broadcastradio_V1_0_BroadcastRadioFactory_H_ diff --git a/broadcastradio/1.0/default/Tuner.cpp b/broadcastradio/1.0/default/Tuner.cpp new file mode 100644 index 000000000..0c1d8ab5b --- /dev/null +++ b/broadcastradio/1.0/default/Tuner.cpp @@ -0,0 +1,199 @@ +/* + * 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 "Tuner" +//#define LOG_NDEBUG 0 + +#include <utils/Log.h> + +#include "BroadcastRadio.h" +#include "Tuner.h" +#include "Utils.h" +#include <system/radio_metadata.h> + +namespace android { +namespace hardware { +namespace broadcastradio { +namespace V1_0 { +namespace implementation { + +void Tuner::onCallback(radio_hal_event_t *halEvent) +{ + BandConfig config; + ProgramInfo info; + hidl_vec<MetaData> metadata; + + if (mCallback != 0) { + switch(halEvent->type) { + case RADIO_EVENT_CONFIG: + Utils::convertBandConfigFromHal(&config, &halEvent->config); + mCallback->configChange(Utils::convertHalResult(halEvent->status), config); + break; + case RADIO_EVENT_ANTENNA: + mCallback->antennaStateChange(halEvent->on); + break; + case RADIO_EVENT_TUNED: + Utils::convertProgramInfoFromHal(&info, &halEvent->info, true); + mCallback->tuneComplete(Utils::convertHalResult(halEvent->status), info); + break; + case RADIO_EVENT_METADATA: { + uint32_t channel; + uint32_t sub_channel; + if (radio_metadata_get_channel(halEvent->metadata, &channel, &sub_channel) == 0) { + Utils::convertMetaDataFromHal(metadata, halEvent->metadata); + mCallback->newMetadata(channel, sub_channel, metadata); + } + } break; + case RADIO_EVENT_TA: + mCallback->trafficAnnouncement(halEvent->on); + break; + case RADIO_EVENT_AF_SWITCH: + Utils::convertProgramInfoFromHal(&info, &halEvent->info, true); + mCallback->afSwitch(info); + break; + case RADIO_EVENT_EA: + mCallback->emergencyAnnouncement(halEvent->on); + break; + case RADIO_EVENT_HW_FAILURE: + default: + mCallback->hardwareFailure(); + break; + } + } +} + +//static +void Tuner::callback(radio_hal_event_t *halEvent, void *cookie) +{ + wp<Tuner> weak(reinterpret_cast<Tuner*>(cookie)); + sp<Tuner> tuner = weak.promote(); + if (tuner == 0) return; + tuner->onCallback(halEvent); +} + +Tuner::Tuner(const sp<ITunerCallback>& callback, const wp<BroadcastRadio>& parentDevice) + : mHalTuner(NULL), mCallback(callback), mParentDevice(parentDevice) +{ + ALOGV("%s", __FUNCTION__); +} + + +Tuner::~Tuner() +{ + ALOGV("%s", __FUNCTION__); + const sp<BroadcastRadio> parentDevice = mParentDevice.promote(); + if (parentDevice != 0) { + parentDevice->closeHalTuner(mHalTuner); + } +} + +// Methods from ::android::hardware::broadcastradio::V1_0::ITuner follow. +Return<Result> Tuner::setConfiguration(const BandConfig& config) { + ALOGV("%s", __FUNCTION__); + if (mHalTuner == NULL) { + return Utils::convertHalResult(-ENODEV); + } + radio_hal_band_config_t halConfig; + Utils::convertBandConfigToHal(&halConfig, &config); + int rc = mHalTuner->set_configuration(mHalTuner, &halConfig); + return Utils::convertHalResult(rc); +} + +Return<void> Tuner::getConfiguration(getConfiguration_cb _hidl_cb) { + int rc; + radio_hal_band_config_t halConfig; + BandConfig config; + + ALOGV("%s", __FUNCTION__); + if (mHalTuner == NULL) { + rc = -ENODEV; + goto exit; + } + rc = mHalTuner->get_configuration(mHalTuner, &halConfig); + if (rc == 0) { + Utils::convertBandConfigFromHal(&config, &halConfig); + } + +exit: + _hidl_cb(Utils::convertHalResult(rc), config); + return Void(); +} + +Return<Result> Tuner::scan(Direction direction, bool skipSubChannel) { + if (mHalTuner == NULL) { + return Utils::convertHalResult(-ENODEV); + } + int rc = mHalTuner->scan(mHalTuner, static_cast<radio_direction_t>(direction), skipSubChannel); + return Utils::convertHalResult(rc); +} + +Return<Result> Tuner::step(Direction direction, bool skipSubChannel) { + if (mHalTuner == NULL) { + return Utils::convertHalResult(-ENODEV); + } + int rc = mHalTuner->step(mHalTuner, static_cast<radio_direction_t>(direction), skipSubChannel); + return Utils::convertHalResult(rc); +} + +Return<Result> Tuner::tune(uint32_t channel, uint32_t subChannel) { + if (mHalTuner == NULL) { + return Utils::convertHalResult(-ENODEV); + } + int rc = mHalTuner->tune(mHalTuner, channel, subChannel); + return Utils::convertHalResult(rc); +} + +Return<Result> Tuner::cancel() { + if (mHalTuner == NULL) { + return Utils::convertHalResult(-ENODEV); + } + int rc = mHalTuner->cancel(mHalTuner); + return Utils::convertHalResult(rc); +} + +Return<void> Tuner::getProgramInformation(bool withMetadata, getProgramInformation_cb _hidl_cb) { + int rc; + radio_program_info_t halInfo; + ProgramInfo info; + + ALOGV("%s", __FUNCTION__); + if (mHalTuner == NULL) { + rc = -ENODEV; + goto exit; + } + if (withMetadata) { + radio_metadata_allocate(&halInfo.metadata, 0, 0); + } else { + halInfo.metadata = NULL; + } + rc = mHalTuner->get_program_information(mHalTuner, &halInfo); + if (rc == 0) { + Utils::convertProgramInfoFromHal(&info, &halInfo, withMetadata); + } + if (withMetadata) { + radio_metadata_deallocate(halInfo.metadata); + } + +exit: + _hidl_cb(Utils::convertHalResult(rc), info); + return Void(); +} + +} // namespace implementation +} // namespace V1_0 +} // namespace broadcastradio +} // namespace hardware +} // namespace android diff --git a/broadcastradio/1.0/default/Tuner.h b/broadcastradio/1.0/default/Tuner.h new file mode 100644 index 000000000..94e216e57 --- /dev/null +++ b/broadcastradio/1.0/default/Tuner.h @@ -0,0 +1,67 @@ +/* + * 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. + */ +#ifndef HIDL_GENERATED_android_hardware_broadcastradio_V1_0_Tuner_H_ +#define HIDL_GENERATED_android_hardware_broadcastradio_V1_0_Tuner_H_ + +#include <android/hardware/broadcastradio/1.0/ITuner.h> +#include <android/hardware/broadcastradio/1.0/ITunerCallback.h> +#include <hidl/Status.h> +#include <hardware/radio.h> + +namespace android { +namespace hardware { +namespace broadcastradio { +namespace V1_0 { +namespace implementation { + +struct BroadcastRadio; + +struct Tuner : public ITuner { + + Tuner(const sp<ITunerCallback>& callback, const wp<BroadcastRadio>& mParentDevice); + + // Methods from ::android::hardware::broadcastradio::V1_0::ITuner follow. + Return<Result> setConfiguration(const BandConfig& config) override; + Return<void> getConfiguration(getConfiguration_cb _hidl_cb) override; + Return<Result> scan(Direction direction, bool skipSubChannel) override; + Return<Result> step(Direction direction, bool skipSubChannel) override; + Return<Result> tune(uint32_t channel, uint32_t subChannel) override; + Return<Result> cancel() override; + Return<void> getProgramInformation(bool withMetadata, + getProgramInformation_cb _hidl_cb) override; + + static void callback(radio_hal_event_t *halEvent, void *cookie); + void onCallback(radio_hal_event_t *halEvent); + + void setHalTuner(const struct radio_tuner *halTuner) { mHalTuner = halTuner; } + const struct radio_tuner *getHalTuner() { return mHalTuner; } + + private: + ~Tuner(); + + const struct radio_tuner *mHalTuner; + const sp<ITunerCallback> mCallback; + const wp<BroadcastRadio> mParentDevice; +}; + + +} // namespace implementation +} // namespace V1_0 +} // namespace broadcastradio +} // namespace hardware +} // namespace android + +#endif // HIDL_GENERATED_android_hardware_broadcastradio_V1_0_Tuner_H_ diff --git a/broadcastradio/1.0/default/Utils.cpp b/broadcastradio/1.0/default/Utils.cpp new file mode 100644 index 000000000..bdaae0023 --- /dev/null +++ b/broadcastradio/1.0/default/Utils.cpp @@ -0,0 +1,297 @@ +/* + * 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 <utils/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, + bool withMetadata) +{ + 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; + if (withMetadata && halInfo->metadata != NULL) { + convertMetaDataFromHal(info->metadata, halInfo->metadata); + } +} + +//static +int Utils::convertMetaDataFromHal(hidl_vec<MetaData>& metadata, + radio_metadata_t *halMetadata) +{ + if (halMetadata == 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 diff --git a/broadcastradio/1.0/default/Utils.h b/broadcastradio/1.0/default/Utils.h new file mode 100644 index 000000000..25eb6eeba --- /dev/null +++ b/broadcastradio/1.0/default/Utils.h @@ -0,0 +1,54 @@ +/* + * 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. + */ +#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_0_UTILS_H +#define ANDROID_HARDWARE_BROADCASTRADIO_V1_0_UTILS_H + +#include <android/hardware/broadcastradio/1.0/types.h> +#include <hardware/radio.h> + +namespace android { +namespace hardware { +namespace broadcastradio { +namespace V1_0 { +namespace implementation { + +class Utils { +public: + static const char * getClassString(Class ClassId); + static Result convertHalResult(int rc); + static void convertBandConfigFromHal(BandConfig *config, + const radio_hal_band_config_t *halConfig); + static void convertPropertiesFromHal(Properties *properties, + const radio_hal_properties_t *halProperties); + static void convertBandConfigToHal(radio_hal_band_config_t *halConfig, + const BandConfig *config); + static void convertProgramInfoFromHal(ProgramInfo *info, + radio_program_info_t *halInfo, + bool withMetadata); + static int convertMetaDataFromHal(hidl_vec<MetaData>& metadata, + radio_metadata_t *halMetadata); +private: + static const char * sClassModuleNames[]; + +}; + +} // namespace implementation +} // namespace V1_0 +} // namespace broadcastradio +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_BROADCASTRADIO_V1_0_UTILS_H diff --git a/broadcastradio/1.0/types.hal b/broadcastradio/1.0/types.hal index c5b441196..d04359cd4 100644 --- a/broadcastradio/1.0/types.hal +++ b/broadcastradio/1.0/types.hal @@ -54,7 +54,7 @@ enum Band : uint32_t { enum Rds : uint32_t { NONE = 0, WORLD = (1<<0), - RDS_US = (1<<1), + US = (1<<1), }; @@ -111,7 +111,7 @@ struct BandConfig { union Ext { FmBandConfig fm; AmBandConfig am; - }; + } ext; }; /* Exposes properties of a given hardware radio module. |