Fix boadcastradio HAL 1.1 tuneByProgramSelector implementation.

It was not compliant with the HAL definition - it didn't auto-change
band if necessary.

Bug: 74353024
Test: manual
Change-Id: I015faffc42778fa27fca3030306f31b0abe409c7
This commit is contained in:
Tomasz Wasilczyk
2018-03-07 14:28:55 -08:00
parent 486c1de215
commit c863a957d4
4 changed files with 71 additions and 40 deletions

View File

@@ -122,28 +122,7 @@ Return<void> BroadcastRadio::getProperties_1_1(getProperties_1_1_cb _hidl_cb) {
{"com.google.dummy", "dummy"},
});
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];
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;
}
}
prop10.bands = getAmFmBands();
_hidl_cb(prop11);
return Void();
@@ -162,7 +141,7 @@ Return<void> BroadcastRadio::openTuner(const BandConfig& config, bool audio __un
mTuner = nullptr;
}
sp<Tuner> newTuner = new Tuner(mClassId, callback);
sp<Tuner> newTuner = new Tuner(this, mClassId, callback);
mTuner = newTuner;
if (mClassId == Class::AM_FM) {
auto ret = newTuner->setConfiguration(config);
@@ -189,6 +168,33 @@ Return<void> BroadcastRadio::getImage(int32_t id, getImage_cb _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

View File

@@ -65,6 +65,8 @@ struct BroadcastRadio : public V1_1::IBroadcastRadio {
openTuner_cb _hidl_cb) override;
Return<void> getImage(int32_t id, getImage_cb _hidl_cb);
std::vector<V1_0::BandConfig> getAmFmBands() const;
private:
std::mutex mMut;
V1_0::Class mClassId;

View File

@@ -58,8 +58,10 @@ const struct {
milliseconds tune = 150ms;
} gDefaultDelay;
Tuner::Tuner(V1_0::Class classId, const sp<V1_0::ITunerCallback>& callback)
: mClassId(classId),
Tuner::Tuner(const sp<BroadcastRadio> module, V1_0::Class classId,
const sp<V1_0::ITunerCallback>& callback)
: mModule(module),
mClassId(classId),
mCallback(callback),
mCallback1_1(V1_1::ITunerCallback::castFrom(callback).withDefault(nullptr)),
mVirtualRadio(getRadio(classId)),
@@ -71,6 +73,33 @@ void Tuner::forceClose() {
mThread.cancelAll();
}
void Tuner::setConfigurationInternalLocked(const BandConfig& config) {
mAmfmConfig = config;
mAmfmConfig.antennaConnected = true;
mCurrentProgram = utils::make_selector(mAmfmConfig.type, mAmfmConfig.lowerLimit);
if (utils::isFm(mAmfmConfig.type)) {
mVirtualRadio = std::ref(getFmRadio());
} else {
mVirtualRadio = std::ref(getAmRadio());
}
mIsAmfmConfigSet = true;
mCallback->configChange(Result::OK, mAmfmConfig);
}
bool Tuner::autoConfigureLocked(uint64_t frequency) {
for (auto&& config : mModule->getAmFmBands()) {
// The check here is rather poor, but it's enough for default implementation.
if (config.lowerLimit <= frequency && config.upperLimit >= frequency) {
ALOGI("Auto-switching band to %s", toString(config).c_str());
setConfigurationInternalLocked(config);
return true;
}
}
return false;
}
Return<Result> Tuner::setConfiguration(const BandConfig& config) {
ALOGV("%s", __func__);
lock_guard<mutex> lk(mMut);
@@ -85,19 +114,7 @@ Return<Result> Tuner::setConfiguration(const BandConfig& config) {
auto task = [this, config]() {
ALOGI("Setting AM/FM config");
lock_guard<mutex> lk(mMut);
mAmfmConfig = move(config);
mAmfmConfig.antennaConnected = true;
mCurrentProgram = utils::make_selector(mAmfmConfig.type, mAmfmConfig.lowerLimit);
if (utils::isFm(mAmfmConfig.type)) {
mVirtualRadio = std::ref(getFmRadio());
} else {
mVirtualRadio = std::ref(getAmRadio());
}
mIsAmfmConfigSet = true;
mCallback->configChange(Result::OK, mAmfmConfig);
setConfigurationInternalLocked(config);
};
mThread.schedule(task, gDefaultDelay.config);
@@ -276,7 +293,7 @@ Return<Result> Tuner::tuneByProgramSelector(const ProgramSelector& sel) {
auto freq = utils::getId(sel, IdentifierType::AMFM_FREQUENCY);
if (freq < mAmfmConfig.lowerLimit || freq > mAmfmConfig.upperLimit) {
return Result::INVALID_ARGUMENTS;
if (!autoConfigureLocked(freq)) return Result::INVALID_ARGUMENTS;
}
} else if (programType == ProgramType::DAB) {
if (!utils::hasId(sel, IdentifierType::DAB_SIDECC)) return Result::INVALID_ARGUMENTS;

View File

@@ -28,8 +28,11 @@ namespace broadcastradio {
namespace V1_1 {
namespace implementation {
struct BroadcastRadio;
struct Tuner : public ITuner {
Tuner(V1_0::Class classId, const sp<V1_0::ITunerCallback>& callback);
Tuner(const sp<BroadcastRadio> module, V1_0::Class classId,
const sp<V1_0::ITunerCallback>& callback);
void forceClose();
@@ -55,6 +58,7 @@ struct Tuner : public ITuner {
WorkerThread mThread;
bool mIsClosed = false;
const sp<BroadcastRadio> mModule;
V1_0::Class mClassId;
const sp<V1_0::ITunerCallback> mCallback;
const sp<V1_1::ITunerCallback> mCallback1_1;
@@ -68,7 +72,9 @@ struct Tuner : public ITuner {
std::atomic<bool> mIsAnalogForced;
utils::HalRevision getHalRev() const;
void setConfigurationInternalLocked(const V1_0::BandConfig& config);
void tuneInternalLocked(const V1_1::ProgramSelector& sel);
bool autoConfigureLocked(uint64_t frequency);
};
} // namespace implementation