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.
203 lines
6.0 KiB
203 lines
6.0 KiB
4 months ago
|
/*
|
||
|
* Copyright (C) 2017 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 "BroadcastRadioDefault.module"
|
||
|
#define LOG_NDEBUG 0
|
||
|
|
||
|
#include "BroadcastRadio.h"
|
||
|
|
||
|
#include <log/log.h>
|
||
|
|
||
|
#include "resources.h"
|
||
|
|
||
|
namespace android {
|
||
|
namespace hardware {
|
||
|
namespace broadcastradio {
|
||
|
namespace V1_1 {
|
||
|
namespace implementation {
|
||
|
|
||
|
using V1_0::Band;
|
||
|
using V1_0::BandConfig;
|
||
|
using V1_0::Class;
|
||
|
using V1_0::Deemphasis;
|
||
|
using V1_0::Rds;
|
||
|
using V1_1::IdentifierType;
|
||
|
using V1_1::ProgramSelector;
|
||
|
using V1_1::ProgramType;
|
||
|
using V1_1::Properties;
|
||
|
using V1_1::VendorKeyValue;
|
||
|
|
||
|
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,
|
||
|
153, // lowerLimit
|
||
|
26100, // upperLimit
|
||
|
{5, 9, 10}, // spacings
|
||
|
}),
|
||
|
AmFmBandConfig({
|
||
|
Band::FM,
|
||
|
65800, // lowerLimit
|
||
|
108000, // upperLimit
|
||
|
{10, 100, 200}, // spacings
|
||
|
}),
|
||
|
AmFmBandConfig({
|
||
|
Band::AM_HD,
|
||
|
153, // lowerLimit
|
||
|
26100, // upperLimit
|
||
|
{5, 9, 10}, // spacings
|
||
|
}),
|
||
|
AmFmBandConfig({
|
||
|
Band::FM_HD,
|
||
|
87700, // lowerLimit
|
||
|
107900, // upperLimit
|
||
|
{200}, // spacings
|
||
|
}),
|
||
|
},
|
||
|
})},
|
||
|
|
||
|
{Class::SAT, ModuleConfig({
|
||
|
"Satellite radio mock",
|
||
|
{}, // amFmBands
|
||
|
})},
|
||
|
};
|
||
|
// clang-format on
|
||
|
|
||
|
BroadcastRadio::BroadcastRadio(Class classId)
|
||
|
: mClassId(classId), mConfig(gModuleConfigs.at(classId)) {}
|
||
|
|
||
|
bool BroadcastRadio::isSupported(Class classId) {
|
||
|
return gModuleConfigs.find(classId) != gModuleConfigs.end();
|
||
|
}
|
||
|
|
||
|
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) {
|
||
|
ALOGV("%s", __func__);
|
||
|
Properties prop11 = {};
|
||
|
auto& prop10 = prop11.base;
|
||
|
|
||
|
prop10.classId = mClassId;
|
||
|
prop10.implementor = "Google";
|
||
|
prop10.product = mConfig.productName;
|
||
|
prop10.numTuners = 1;
|
||
|
prop10.numAudioSources = 1;
|
||
|
prop10.supportsCapture = false;
|
||
|
prop11.supportsBackgroundScanning = true;
|
||
|
prop11.supportedProgramTypes = hidl_vec<uint32_t>({
|
||
|
static_cast<uint32_t>(ProgramType::AM), static_cast<uint32_t>(ProgramType::FM),
|
||
|
static_cast<uint32_t>(ProgramType::AM_HD), static_cast<uint32_t>(ProgramType::FM_HD),
|
||
|
});
|
||
|
prop11.supportedIdentifierTypes = hidl_vec<uint32_t>({
|
||
|
static_cast<uint32_t>(IdentifierType::AMFM_FREQUENCY),
|
||
|
static_cast<uint32_t>(IdentifierType::RDS_PI),
|
||
|
static_cast<uint32_t>(IdentifierType::HD_STATION_ID_EXT),
|
||
|
static_cast<uint32_t>(IdentifierType::HD_SUBCHANNEL),
|
||
|
});
|
||
|
prop11.vendorInfo = hidl_vec<VendorKeyValue>({
|
||
|
{"com.google.dummy", "dummy"},
|
||
|
});
|
||
|
|
||
|
prop10.bands = getAmFmBands();
|
||
|
|
||
|
_hidl_cb(prop11);
|
||
|
return Void();
|
||
|
}
|
||
|
|
||
|
Return<void> BroadcastRadio::openTuner(const BandConfig& config, bool audio __unused,
|
||
|
const sp<V1_0::ITunerCallback>& callback,
|
||
|
openTuner_cb _hidl_cb) {
|
||
|
ALOGV("%s(%s)", __func__, toString(config.type).c_str());
|
||
|
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(this, mClassId, 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();
|
||
|
}
|
||
|
|
||
|
Return<void> BroadcastRadio::getImage(int32_t id, getImage_cb _hidl_cb) {
|
||
|
ALOGV("%s(%x)", __func__, id);
|
||
|
|
||
|
if (id == resources::demoPngId) {
|
||
|
_hidl_cb(std::vector<uint8_t>(resources::demoPng, std::end(resources::demoPng)));
|
||
|
return {};
|
||
|
}
|
||
|
|
||
|
ALOGI("Image %x doesn't exists", id);
|
||
|
_hidl_cb({});
|
||
|
return Void();
|
||
|
}
|
||
|
|
||
|
std::vector<V1_0::BandConfig> BroadcastRadio::getAmFmBands() const {
|
||
|
std::vector<V1_0::BandConfig> out;
|
||
|
for (auto&& src : mConfig.amFmBands) {
|
||
|
V1_0::BandConfig dst;
|
||
|
|
||
|
dst.type = src.type;
|
||
|
dst.antennaConnected = true;
|
||
|
dst.lowerLimit = src.lowerLimit;
|
||
|
dst.upperLimit = src.upperLimit;
|
||
|
dst.spacings = src.spacings;
|
||
|
|
||
|
if (utils::isAm(src.type)) {
|
||
|
dst.ext.am.stereo = true;
|
||
|
} else if (utils::isFm(src.type)) {
|
||
|
dst.ext.fm.deemphasis = static_cast<Deemphasis>(Deemphasis::D50 | Deemphasis::D75);
|
||
|
dst.ext.fm.stereo = true;
|
||
|
dst.ext.fm.rds = static_cast<Rds>(Rds::WORLD | Rds::US);
|
||
|
dst.ext.fm.ta = true;
|
||
|
dst.ext.fm.af = true;
|
||
|
dst.ext.fm.ea = true;
|
||
|
}
|
||
|
|
||
|
out.push_back(dst);
|
||
|
}
|
||
|
return out;
|
||
|
}
|
||
|
|
||
|
} // namespace implementation
|
||
|
} // namespace V1_1
|
||
|
} // namespace broadcastradio
|
||
|
} // namespace hardware
|
||
|
} // namespace android
|