Initial Broadcast Radio HAL 1.1 default implementation.
The new implementation does not rely on legacy HAL, it implements
HAL 1.1 directly instead.
This is not a full implementation yet, but passes all existing tests.
Bug: b/36864090
Test: VTS, instrumentalization, Unit
Change-Id: Ic8eddd19d0bf6777b4086d099183d71e05d7da0e
diff --git a/broadcastradio/1.1/default/BroadcastRadio.cpp b/broadcastradio/1.1/default/BroadcastRadio.cpp
index d65fe6d..3aac127 100644
--- a/broadcastradio/1.1/default/BroadcastRadio.cpp
+++ b/broadcastradio/1.1/default/BroadcastRadio.cpp
@@ -13,14 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#define LOG_TAG "BroadcastRadio"
-//#define LOG_NDEBUG 0
-
-#include <log/log.h>
+#define LOG_TAG "BroadcastRadioDefault.module"
+#define LOG_NDEBUG 0
#include "BroadcastRadio.h"
-#include "Tuner.h"
-#include "Utils.h"
+
+#include <log/log.h>
namespace android {
namespace hardware {
@@ -28,125 +26,126 @@
namespace V1_1 {
namespace implementation {
-using ::android::sp;
+using V1_0::Band;
+using V1_0::BandConfig;
+using V1_0::Class;
+using V1_0::Deemphasis;
+using V1_0::Rds;
+
+using std::lock_guard;
+using std::map;
+using std::mutex;
+using std::vector;
+
+// clang-format off
+static const map<Class, ModuleConfig> gModuleConfigs{
+ {Class::AM_FM, ModuleConfig({
+ "Digital radio mock",
+ { // amFmBands
+ AmFmBandConfig({
+ Band::AM_HD,
+ 540, // lowerLimit
+ 1610, // upperLimit
+ 10, // spacing
+ }),
+ AmFmBandConfig({
+ Band::FM_HD,
+ 87900, // lowerLimit
+ 107900, // upperLimit
+ 200, // spacing
+ }),
+ },
+ })},
+
+ {Class::SAT, ModuleConfig({
+ "Satellite radio mock",
+ {}, // amFmBands
+ })},
+};
+// clang-format on
BroadcastRadio::BroadcastRadio(Class classId)
- : mStatus(Result::NOT_INITIALIZED), mClassId(classId), mHwDevice(NULL)
-{
+ : mClassId(classId), mConfig(gModuleConfigs.at(classId)) {}
+
+bool BroadcastRadio::isSupported(Class classId) {
+ return gModuleConfigs.find(classId) != gModuleConfigs.end();
}
-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_1::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::getProperties(getProperties_cb _hidl_cb) {
+ ALOGV("%s", __func__);
+ return getProperties_1_1(
+ [&](const Properties& properties) { _hidl_cb(Result::OK, properties.base); });
}
Return<void> BroadcastRadio::getProperties_1_1(getProperties_1_1_cb _hidl_cb) {
- radio_hal_properties_t halProperties;
- V1_1::Properties properties = {};
+ ALOGV("%s", __func__);
+ Properties prop11 = {};
+ auto& prop10 = prop11.base;
- LOG_ALWAYS_FATAL_IF(mHwDevice == nullptr, "HW device is not set");
- int rc = mHwDevice->get_properties(mHwDevice, &halProperties);
- LOG_ALWAYS_FATAL_IF(rc != 0, "Couldn't get device properties");
- Utils::convertPropertiesFromHal(&properties.base, &halProperties);
+ prop10.classId = mClassId;
+ prop10.implementor = "Google";
+ prop10.product = mConfig.productName;
+ prop10.numTuners = 1;
+ prop10.numAudioSources = 1;
+ prop10.supportsCapture = false;
+ prop11.supportsBackgroundScanning = false;
+ prop11.vendorExension = "dummy";
- _hidl_cb(properties);
- return Void();
-}
+ prop10.bands.resize(mConfig.amFmBands.size());
+ for (size_t i = 0; i < mConfig.amFmBands.size(); i++) {
+ auto& src = mConfig.amFmBands[i];
+ auto& dst = prop10.bands[i];
-Return<void> BroadcastRadio::openTuner(const BandConfig& config, bool audio,
- const sp<V1_0::ITunerCallback>& callback, openTuner_cb _hidl_cb)
-{
- sp<Tuner> tunerImpl = new Tuner(callback, this);
+ dst.type = src.type;
+ dst.antennaConnected = true;
+ dst.lowerLimit = src.lowerLimit;
+ dst.upperLimit = src.upperLimit;
+ dst.spacings = vector<uint32_t>({src.spacing});
- 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);
+ if (src.type == Band::AM) {
+ dst.ext.am.stereo = true;
+ } else if (src.type == Band::FM) {
+ dst.ext.fm.deemphasis = Deemphasis::D75;
+ dst.ext.fm.stereo = true;
+ dst.ext.fm.rds = Rds::US;
+ dst.ext.fm.ta = true;
+ dst.ext.fm.af = true;
+ dst.ext.fm.ea = true;
+ }
}
- _hidl_cb(Utils::convertHalResult(rc), tunerImpl);
+ _hidl_cb(prop11);
return Void();
}
-} // namespace implementation
+Return<void> BroadcastRadio::openTuner(const BandConfig& config, bool audio __unused,
+ const sp<V1_0::ITunerCallback>& callback,
+ openTuner_cb _hidl_cb) {
+ ALOGV("%s", __func__);
+ lock_guard<mutex> lk(mMut);
+
+ auto oldTuner = mTuner.promote();
+ if (oldTuner != nullptr) {
+ ALOGI("Force-closing previously opened tuner");
+ oldTuner->forceClose();
+ mTuner = nullptr;
+ }
+
+ sp<Tuner> newTuner = new Tuner(callback);
+ mTuner = newTuner;
+ if (mClassId == Class::AM_FM) {
+ auto ret = newTuner->setConfiguration(config);
+ if (ret != Result::OK) {
+ _hidl_cb(Result::INVALID_ARGUMENTS, {});
+ return Void();
+ }
+ }
+
+ _hidl_cb(Result::OK, newTuner);
+ return Void();
+}
+
+} // namespace implementation
} // namespace V1_1
} // namespace broadcastradio
} // namespace hardware