1*4d7e907cSAndroid Build Coastguard Worker /*
2*4d7e907cSAndroid Build Coastguard Worker * Copyright (C) 2017 The Android Open Source Project
3*4d7e907cSAndroid Build Coastguard Worker *
4*4d7e907cSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*4d7e907cSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*4d7e907cSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*4d7e907cSAndroid Build Coastguard Worker *
8*4d7e907cSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*4d7e907cSAndroid Build Coastguard Worker *
10*4d7e907cSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*4d7e907cSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*4d7e907cSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*4d7e907cSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*4d7e907cSAndroid Build Coastguard Worker * limitations under the License.
15*4d7e907cSAndroid Build Coastguard Worker */
16*4d7e907cSAndroid Build Coastguard Worker
17*4d7e907cSAndroid Build Coastguard Worker #include "TunerSession.h"
18*4d7e907cSAndroid Build Coastguard Worker
19*4d7e907cSAndroid Build Coastguard Worker #include "BroadcastRadio.h"
20*4d7e907cSAndroid Build Coastguard Worker
21*4d7e907cSAndroid Build Coastguard Worker #include <android-base/logging.h>
22*4d7e907cSAndroid Build Coastguard Worker #include <broadcastradio-utils-2x/Utils.h>
23*4d7e907cSAndroid Build Coastguard Worker
24*4d7e907cSAndroid Build Coastguard Worker namespace android {
25*4d7e907cSAndroid Build Coastguard Worker namespace hardware {
26*4d7e907cSAndroid Build Coastguard Worker namespace broadcastradio {
27*4d7e907cSAndroid Build Coastguard Worker namespace V2_0 {
28*4d7e907cSAndroid Build Coastguard Worker namespace implementation {
29*4d7e907cSAndroid Build Coastguard Worker
30*4d7e907cSAndroid Build Coastguard Worker using namespace std::chrono_literals;
31*4d7e907cSAndroid Build Coastguard Worker
32*4d7e907cSAndroid Build Coastguard Worker using utils::tunesTo;
33*4d7e907cSAndroid Build Coastguard Worker
34*4d7e907cSAndroid Build Coastguard Worker using std::lock_guard;
35*4d7e907cSAndroid Build Coastguard Worker using std::move;
36*4d7e907cSAndroid Build Coastguard Worker using std::mutex;
37*4d7e907cSAndroid Build Coastguard Worker using std::sort;
38*4d7e907cSAndroid Build Coastguard Worker using std::vector;
39*4d7e907cSAndroid Build Coastguard Worker
40*4d7e907cSAndroid Build Coastguard Worker namespace delay {
41*4d7e907cSAndroid Build Coastguard Worker
42*4d7e907cSAndroid Build Coastguard Worker static constexpr auto seek = 200ms;
43*4d7e907cSAndroid Build Coastguard Worker static constexpr auto step = 100ms;
44*4d7e907cSAndroid Build Coastguard Worker static constexpr auto tune = 150ms;
45*4d7e907cSAndroid Build Coastguard Worker static constexpr auto list = 1s;
46*4d7e907cSAndroid Build Coastguard Worker
47*4d7e907cSAndroid Build Coastguard Worker } // namespace delay
48*4d7e907cSAndroid Build Coastguard Worker
TunerSession(BroadcastRadio & module,const sp<ITunerCallback> & callback)49*4d7e907cSAndroid Build Coastguard Worker TunerSession::TunerSession(BroadcastRadio& module, const sp<ITunerCallback>& callback)
50*4d7e907cSAndroid Build Coastguard Worker : mCallback(callback), mModule(module) {
51*4d7e907cSAndroid Build Coastguard Worker auto&& ranges = module.getAmFmConfig().ranges;
52*4d7e907cSAndroid Build Coastguard Worker if (ranges.size() > 0) {
53*4d7e907cSAndroid Build Coastguard Worker tuneInternalLocked(utils::make_selector_amfm(ranges[0].lowerBound));
54*4d7e907cSAndroid Build Coastguard Worker }
55*4d7e907cSAndroid Build Coastguard Worker }
56*4d7e907cSAndroid Build Coastguard Worker
57*4d7e907cSAndroid Build Coastguard Worker // makes ProgramInfo that points to no program
makeDummyProgramInfo(const ProgramSelector & selector)58*4d7e907cSAndroid Build Coastguard Worker static ProgramInfo makeDummyProgramInfo(const ProgramSelector& selector) {
59*4d7e907cSAndroid Build Coastguard Worker ProgramInfo info = {};
60*4d7e907cSAndroid Build Coastguard Worker info.selector = selector;
61*4d7e907cSAndroid Build Coastguard Worker info.logicallyTunedTo = utils::make_identifier(
62*4d7e907cSAndroid Build Coastguard Worker IdentifierType::AMFM_FREQUENCY, utils::getId(selector, IdentifierType::AMFM_FREQUENCY));
63*4d7e907cSAndroid Build Coastguard Worker info.physicallyTunedTo = info.logicallyTunedTo;
64*4d7e907cSAndroid Build Coastguard Worker return info;
65*4d7e907cSAndroid Build Coastguard Worker }
66*4d7e907cSAndroid Build Coastguard Worker
tuneInternalLocked(const ProgramSelector & sel)67*4d7e907cSAndroid Build Coastguard Worker void TunerSession::tuneInternalLocked(const ProgramSelector& sel) {
68*4d7e907cSAndroid Build Coastguard Worker LOG(VERBOSE) << "tune (internal) to " << toString(sel);
69*4d7e907cSAndroid Build Coastguard Worker
70*4d7e907cSAndroid Build Coastguard Worker VirtualProgram virtualProgram;
71*4d7e907cSAndroid Build Coastguard Worker ProgramInfo programInfo;
72*4d7e907cSAndroid Build Coastguard Worker if (virtualRadio().getProgram(sel, virtualProgram)) {
73*4d7e907cSAndroid Build Coastguard Worker mCurrentProgram = virtualProgram.selector;
74*4d7e907cSAndroid Build Coastguard Worker programInfo = virtualProgram;
75*4d7e907cSAndroid Build Coastguard Worker } else {
76*4d7e907cSAndroid Build Coastguard Worker mCurrentProgram = sel;
77*4d7e907cSAndroid Build Coastguard Worker programInfo = makeDummyProgramInfo(sel);
78*4d7e907cSAndroid Build Coastguard Worker }
79*4d7e907cSAndroid Build Coastguard Worker mIsTuneCompleted = true;
80*4d7e907cSAndroid Build Coastguard Worker
81*4d7e907cSAndroid Build Coastguard Worker mCallback->onCurrentProgramInfoChanged(programInfo);
82*4d7e907cSAndroid Build Coastguard Worker }
83*4d7e907cSAndroid Build Coastguard Worker
module() const84*4d7e907cSAndroid Build Coastguard Worker const BroadcastRadio& TunerSession::module() const {
85*4d7e907cSAndroid Build Coastguard Worker return mModule.get();
86*4d7e907cSAndroid Build Coastguard Worker }
87*4d7e907cSAndroid Build Coastguard Worker
virtualRadio() const88*4d7e907cSAndroid Build Coastguard Worker const VirtualRadio& TunerSession::virtualRadio() const {
89*4d7e907cSAndroid Build Coastguard Worker return module().mVirtualRadio;
90*4d7e907cSAndroid Build Coastguard Worker }
91*4d7e907cSAndroid Build Coastguard Worker
tune(const ProgramSelector & sel)92*4d7e907cSAndroid Build Coastguard Worker Return<Result> TunerSession::tune(const ProgramSelector& sel) {
93*4d7e907cSAndroid Build Coastguard Worker LOG(DEBUG) << "tune to " << toString(sel);
94*4d7e907cSAndroid Build Coastguard Worker
95*4d7e907cSAndroid Build Coastguard Worker lock_guard<mutex> lk(mMut);
96*4d7e907cSAndroid Build Coastguard Worker if (mIsClosed) return Result::INVALID_STATE;
97*4d7e907cSAndroid Build Coastguard Worker
98*4d7e907cSAndroid Build Coastguard Worker if (!utils::isSupported(module().mProperties, sel)) {
99*4d7e907cSAndroid Build Coastguard Worker LOG(WARNING) << "selector not supported: " << toString(sel);
100*4d7e907cSAndroid Build Coastguard Worker return Result::NOT_SUPPORTED;
101*4d7e907cSAndroid Build Coastguard Worker }
102*4d7e907cSAndroid Build Coastguard Worker
103*4d7e907cSAndroid Build Coastguard Worker if (!utils::isValid(sel)) {
104*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << "selector is not valid: " << toString(sel);
105*4d7e907cSAndroid Build Coastguard Worker return Result::INVALID_ARGUMENTS;
106*4d7e907cSAndroid Build Coastguard Worker }
107*4d7e907cSAndroid Build Coastguard Worker
108*4d7e907cSAndroid Build Coastguard Worker cancelLocked();
109*4d7e907cSAndroid Build Coastguard Worker
110*4d7e907cSAndroid Build Coastguard Worker mIsTuneCompleted = false;
111*4d7e907cSAndroid Build Coastguard Worker auto task = [this, sel]() {
112*4d7e907cSAndroid Build Coastguard Worker lock_guard<mutex> lk(mMut);
113*4d7e907cSAndroid Build Coastguard Worker tuneInternalLocked(sel);
114*4d7e907cSAndroid Build Coastguard Worker };
115*4d7e907cSAndroid Build Coastguard Worker mThread.schedule(task, delay::tune);
116*4d7e907cSAndroid Build Coastguard Worker
117*4d7e907cSAndroid Build Coastguard Worker return Result::OK;
118*4d7e907cSAndroid Build Coastguard Worker }
119*4d7e907cSAndroid Build Coastguard Worker
scan(bool directionUp,bool skipSubChannel)120*4d7e907cSAndroid Build Coastguard Worker Return<Result> TunerSession::scan(bool directionUp, bool skipSubChannel) {
121*4d7e907cSAndroid Build Coastguard Worker LOG(DEBUG) << "seek up=" << directionUp << " skipSubChannel=" << skipSubChannel;
122*4d7e907cSAndroid Build Coastguard Worker
123*4d7e907cSAndroid Build Coastguard Worker lock_guard<mutex> lk(mMut);
124*4d7e907cSAndroid Build Coastguard Worker if (mIsClosed) return Result::INVALID_STATE;
125*4d7e907cSAndroid Build Coastguard Worker
126*4d7e907cSAndroid Build Coastguard Worker cancelLocked();
127*4d7e907cSAndroid Build Coastguard Worker
128*4d7e907cSAndroid Build Coastguard Worker auto list = virtualRadio().getProgramList();
129*4d7e907cSAndroid Build Coastguard Worker
130*4d7e907cSAndroid Build Coastguard Worker if (list.empty()) {
131*4d7e907cSAndroid Build Coastguard Worker mIsTuneCompleted = false;
132*4d7e907cSAndroid Build Coastguard Worker auto task = [this]() {
133*4d7e907cSAndroid Build Coastguard Worker LOG(DEBUG) << "program list is empty, seek couldn't stop";
134*4d7e907cSAndroid Build Coastguard Worker
135*4d7e907cSAndroid Build Coastguard Worker mCallback->onTuneFailed(Result::TIMEOUT, {});
136*4d7e907cSAndroid Build Coastguard Worker };
137*4d7e907cSAndroid Build Coastguard Worker mThread.schedule(task, delay::seek);
138*4d7e907cSAndroid Build Coastguard Worker
139*4d7e907cSAndroid Build Coastguard Worker return Result::OK;
140*4d7e907cSAndroid Build Coastguard Worker }
141*4d7e907cSAndroid Build Coastguard Worker
142*4d7e907cSAndroid Build Coastguard Worker // Not optimal (O(sort) instead of O(n)), but not a big deal here;
143*4d7e907cSAndroid Build Coastguard Worker // also, it's likely that list is already sorted (so O(n) anyway).
144*4d7e907cSAndroid Build Coastguard Worker sort(list.begin(), list.end());
145*4d7e907cSAndroid Build Coastguard Worker auto current = mCurrentProgram;
146*4d7e907cSAndroid Build Coastguard Worker auto found = lower_bound(list.begin(), list.end(), VirtualProgram({current}));
147*4d7e907cSAndroid Build Coastguard Worker if (directionUp) {
148*4d7e907cSAndroid Build Coastguard Worker if (found < list.end() - 1) {
149*4d7e907cSAndroid Build Coastguard Worker if (tunesTo(current, found->selector)) found++;
150*4d7e907cSAndroid Build Coastguard Worker } else {
151*4d7e907cSAndroid Build Coastguard Worker found = list.begin();
152*4d7e907cSAndroid Build Coastguard Worker }
153*4d7e907cSAndroid Build Coastguard Worker } else {
154*4d7e907cSAndroid Build Coastguard Worker if (found > list.begin() && found != list.end()) {
155*4d7e907cSAndroid Build Coastguard Worker found--;
156*4d7e907cSAndroid Build Coastguard Worker } else {
157*4d7e907cSAndroid Build Coastguard Worker found = list.end() - 1;
158*4d7e907cSAndroid Build Coastguard Worker }
159*4d7e907cSAndroid Build Coastguard Worker }
160*4d7e907cSAndroid Build Coastguard Worker auto tuneTo = found->selector;
161*4d7e907cSAndroid Build Coastguard Worker
162*4d7e907cSAndroid Build Coastguard Worker mIsTuneCompleted = false;
163*4d7e907cSAndroid Build Coastguard Worker auto task = [this, tuneTo, directionUp]() {
164*4d7e907cSAndroid Build Coastguard Worker LOG(VERBOSE) << "executing seek up=" << directionUp;
165*4d7e907cSAndroid Build Coastguard Worker
166*4d7e907cSAndroid Build Coastguard Worker lock_guard<mutex> lk(mMut);
167*4d7e907cSAndroid Build Coastguard Worker tuneInternalLocked(tuneTo);
168*4d7e907cSAndroid Build Coastguard Worker };
169*4d7e907cSAndroid Build Coastguard Worker mThread.schedule(task, delay::seek);
170*4d7e907cSAndroid Build Coastguard Worker
171*4d7e907cSAndroid Build Coastguard Worker return Result::OK;
172*4d7e907cSAndroid Build Coastguard Worker }
173*4d7e907cSAndroid Build Coastguard Worker
step(bool directionUp)174*4d7e907cSAndroid Build Coastguard Worker Return<Result> TunerSession::step(bool directionUp) {
175*4d7e907cSAndroid Build Coastguard Worker LOG(DEBUG) << "step up=" << directionUp;
176*4d7e907cSAndroid Build Coastguard Worker lock_guard<mutex> lk(mMut);
177*4d7e907cSAndroid Build Coastguard Worker if (mIsClosed) return Result::INVALID_STATE;
178*4d7e907cSAndroid Build Coastguard Worker
179*4d7e907cSAndroid Build Coastguard Worker cancelLocked();
180*4d7e907cSAndroid Build Coastguard Worker
181*4d7e907cSAndroid Build Coastguard Worker if (!utils::hasId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY)) {
182*4d7e907cSAndroid Build Coastguard Worker LOG(WARNING) << "can't step in anything else than AM/FM";
183*4d7e907cSAndroid Build Coastguard Worker return Result::NOT_SUPPORTED;
184*4d7e907cSAndroid Build Coastguard Worker }
185*4d7e907cSAndroid Build Coastguard Worker
186*4d7e907cSAndroid Build Coastguard Worker auto stepTo = utils::getId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY);
187*4d7e907cSAndroid Build Coastguard Worker auto range = getAmFmRangeLocked();
188*4d7e907cSAndroid Build Coastguard Worker if (!range) {
189*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << "can't find current band";
190*4d7e907cSAndroid Build Coastguard Worker return Result::INTERNAL_ERROR;
191*4d7e907cSAndroid Build Coastguard Worker }
192*4d7e907cSAndroid Build Coastguard Worker
193*4d7e907cSAndroid Build Coastguard Worker if (directionUp) {
194*4d7e907cSAndroid Build Coastguard Worker stepTo += range->spacing;
195*4d7e907cSAndroid Build Coastguard Worker } else {
196*4d7e907cSAndroid Build Coastguard Worker stepTo -= range->spacing;
197*4d7e907cSAndroid Build Coastguard Worker }
198*4d7e907cSAndroid Build Coastguard Worker if (stepTo > range->upperBound) stepTo = range->lowerBound;
199*4d7e907cSAndroid Build Coastguard Worker if (stepTo < range->lowerBound) stepTo = range->upperBound;
200*4d7e907cSAndroid Build Coastguard Worker
201*4d7e907cSAndroid Build Coastguard Worker mIsTuneCompleted = false;
202*4d7e907cSAndroid Build Coastguard Worker auto task = [this, stepTo]() {
203*4d7e907cSAndroid Build Coastguard Worker LOG(VERBOSE) << "executing step to " << stepTo;
204*4d7e907cSAndroid Build Coastguard Worker
205*4d7e907cSAndroid Build Coastguard Worker lock_guard<mutex> lk(mMut);
206*4d7e907cSAndroid Build Coastguard Worker
207*4d7e907cSAndroid Build Coastguard Worker tuneInternalLocked(utils::make_selector_amfm(stepTo));
208*4d7e907cSAndroid Build Coastguard Worker };
209*4d7e907cSAndroid Build Coastguard Worker mThread.schedule(task, delay::step);
210*4d7e907cSAndroid Build Coastguard Worker
211*4d7e907cSAndroid Build Coastguard Worker return Result::OK;
212*4d7e907cSAndroid Build Coastguard Worker }
213*4d7e907cSAndroid Build Coastguard Worker
cancelLocked()214*4d7e907cSAndroid Build Coastguard Worker void TunerSession::cancelLocked() {
215*4d7e907cSAndroid Build Coastguard Worker LOG(VERBOSE) << "cancelling current operations...";
216*4d7e907cSAndroid Build Coastguard Worker
217*4d7e907cSAndroid Build Coastguard Worker mThread.cancelAll();
218*4d7e907cSAndroid Build Coastguard Worker if (utils::getType(mCurrentProgram.primaryId) != IdentifierType::INVALID) {
219*4d7e907cSAndroid Build Coastguard Worker mIsTuneCompleted = true;
220*4d7e907cSAndroid Build Coastguard Worker }
221*4d7e907cSAndroid Build Coastguard Worker }
222*4d7e907cSAndroid Build Coastguard Worker
cancel()223*4d7e907cSAndroid Build Coastguard Worker Return<void> TunerSession::cancel() {
224*4d7e907cSAndroid Build Coastguard Worker lock_guard<mutex> lk(mMut);
225*4d7e907cSAndroid Build Coastguard Worker if (mIsClosed) return {};
226*4d7e907cSAndroid Build Coastguard Worker
227*4d7e907cSAndroid Build Coastguard Worker cancelLocked();
228*4d7e907cSAndroid Build Coastguard Worker
229*4d7e907cSAndroid Build Coastguard Worker return {};
230*4d7e907cSAndroid Build Coastguard Worker }
231*4d7e907cSAndroid Build Coastguard Worker
startProgramListUpdates(const ProgramFilter & filter)232*4d7e907cSAndroid Build Coastguard Worker Return<Result> TunerSession::startProgramListUpdates(const ProgramFilter& filter) {
233*4d7e907cSAndroid Build Coastguard Worker LOG(DEBUG) << "requested program list updates, filter=" << toString(filter);
234*4d7e907cSAndroid Build Coastguard Worker lock_guard<mutex> lk(mMut);
235*4d7e907cSAndroid Build Coastguard Worker if (mIsClosed) return Result::INVALID_STATE;
236*4d7e907cSAndroid Build Coastguard Worker
237*4d7e907cSAndroid Build Coastguard Worker auto list = virtualRadio().getProgramList();
238*4d7e907cSAndroid Build Coastguard Worker vector<VirtualProgram> filteredList;
239*4d7e907cSAndroid Build Coastguard Worker auto filterCb = [&filter](const VirtualProgram& program) {
240*4d7e907cSAndroid Build Coastguard Worker return utils::satisfies(filter, program.selector);
241*4d7e907cSAndroid Build Coastguard Worker };
242*4d7e907cSAndroid Build Coastguard Worker std::copy_if(list.begin(), list.end(), std::back_inserter(filteredList), filterCb);
243*4d7e907cSAndroid Build Coastguard Worker
244*4d7e907cSAndroid Build Coastguard Worker auto task = [this, filteredList]() {
245*4d7e907cSAndroid Build Coastguard Worker lock_guard<mutex> lk(mMut);
246*4d7e907cSAndroid Build Coastguard Worker
247*4d7e907cSAndroid Build Coastguard Worker ProgramListChunk chunk = {};
248*4d7e907cSAndroid Build Coastguard Worker chunk.purge = true;
249*4d7e907cSAndroid Build Coastguard Worker chunk.complete = true;
250*4d7e907cSAndroid Build Coastguard Worker chunk.modified = hidl_vec<ProgramInfo>(filteredList.begin(), filteredList.end());
251*4d7e907cSAndroid Build Coastguard Worker
252*4d7e907cSAndroid Build Coastguard Worker mCallback->onProgramListUpdated(chunk);
253*4d7e907cSAndroid Build Coastguard Worker };
254*4d7e907cSAndroid Build Coastguard Worker mThread.schedule(task, delay::list);
255*4d7e907cSAndroid Build Coastguard Worker
256*4d7e907cSAndroid Build Coastguard Worker return Result::OK;
257*4d7e907cSAndroid Build Coastguard Worker }
258*4d7e907cSAndroid Build Coastguard Worker
stopProgramListUpdates()259*4d7e907cSAndroid Build Coastguard Worker Return<void> TunerSession::stopProgramListUpdates() {
260*4d7e907cSAndroid Build Coastguard Worker LOG(DEBUG) << "requested program list updates to stop";
261*4d7e907cSAndroid Build Coastguard Worker return {};
262*4d7e907cSAndroid Build Coastguard Worker }
263*4d7e907cSAndroid Build Coastguard Worker
isConfigFlagSet(ConfigFlag flag,isConfigFlagSet_cb _hidl_cb)264*4d7e907cSAndroid Build Coastguard Worker Return<void> TunerSession::isConfigFlagSet(ConfigFlag flag, isConfigFlagSet_cb _hidl_cb) {
265*4d7e907cSAndroid Build Coastguard Worker LOG(VERBOSE) << __func__ << " " << toString(flag);
266*4d7e907cSAndroid Build Coastguard Worker
267*4d7e907cSAndroid Build Coastguard Worker _hidl_cb(Result::NOT_SUPPORTED, false);
268*4d7e907cSAndroid Build Coastguard Worker return {};
269*4d7e907cSAndroid Build Coastguard Worker }
270*4d7e907cSAndroid Build Coastguard Worker
setConfigFlag(ConfigFlag flag,bool value)271*4d7e907cSAndroid Build Coastguard Worker Return<Result> TunerSession::setConfigFlag(ConfigFlag flag, bool value) {
272*4d7e907cSAndroid Build Coastguard Worker LOG(VERBOSE) << __func__ << " " << toString(flag) << " " << value;
273*4d7e907cSAndroid Build Coastguard Worker
274*4d7e907cSAndroid Build Coastguard Worker return Result::NOT_SUPPORTED;
275*4d7e907cSAndroid Build Coastguard Worker }
276*4d7e907cSAndroid Build Coastguard Worker
setParameters(const hidl_vec<VendorKeyValue> &,setParameters_cb _hidl_cb)277*4d7e907cSAndroid Build Coastguard Worker Return<void> TunerSession::setParameters(const hidl_vec<VendorKeyValue>& /* parameters */,
278*4d7e907cSAndroid Build Coastguard Worker setParameters_cb _hidl_cb) {
279*4d7e907cSAndroid Build Coastguard Worker _hidl_cb({});
280*4d7e907cSAndroid Build Coastguard Worker return {};
281*4d7e907cSAndroid Build Coastguard Worker }
282*4d7e907cSAndroid Build Coastguard Worker
getParameters(const hidl_vec<hidl_string> &,getParameters_cb _hidl_cb)283*4d7e907cSAndroid Build Coastguard Worker Return<void> TunerSession::getParameters(const hidl_vec<hidl_string>& /* keys */,
284*4d7e907cSAndroid Build Coastguard Worker getParameters_cb _hidl_cb) {
285*4d7e907cSAndroid Build Coastguard Worker _hidl_cb({});
286*4d7e907cSAndroid Build Coastguard Worker return {};
287*4d7e907cSAndroid Build Coastguard Worker }
288*4d7e907cSAndroid Build Coastguard Worker
close()289*4d7e907cSAndroid Build Coastguard Worker Return<void> TunerSession::close() {
290*4d7e907cSAndroid Build Coastguard Worker LOG(DEBUG) << "closing session...";
291*4d7e907cSAndroid Build Coastguard Worker lock_guard<mutex> lk(mMut);
292*4d7e907cSAndroid Build Coastguard Worker if (mIsClosed) return {};
293*4d7e907cSAndroid Build Coastguard Worker
294*4d7e907cSAndroid Build Coastguard Worker mIsClosed = true;
295*4d7e907cSAndroid Build Coastguard Worker mThread.cancelAll();
296*4d7e907cSAndroid Build Coastguard Worker return {};
297*4d7e907cSAndroid Build Coastguard Worker }
298*4d7e907cSAndroid Build Coastguard Worker
getAmFmRangeLocked() const299*4d7e907cSAndroid Build Coastguard Worker std::optional<AmFmBandRange> TunerSession::getAmFmRangeLocked() const {
300*4d7e907cSAndroid Build Coastguard Worker if (!mIsTuneCompleted) {
301*4d7e907cSAndroid Build Coastguard Worker LOG(WARNING) << "tune operation is in process";
302*4d7e907cSAndroid Build Coastguard Worker return {};
303*4d7e907cSAndroid Build Coastguard Worker }
304*4d7e907cSAndroid Build Coastguard Worker if (!utils::hasId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY)) return {};
305*4d7e907cSAndroid Build Coastguard Worker
306*4d7e907cSAndroid Build Coastguard Worker auto freq = utils::getId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY);
307*4d7e907cSAndroid Build Coastguard Worker for (auto&& range : module().getAmFmConfig().ranges) {
308*4d7e907cSAndroid Build Coastguard Worker if (range.lowerBound <= freq && range.upperBound >= freq) return range;
309*4d7e907cSAndroid Build Coastguard Worker }
310*4d7e907cSAndroid Build Coastguard Worker
311*4d7e907cSAndroid Build Coastguard Worker return {};
312*4d7e907cSAndroid Build Coastguard Worker }
313*4d7e907cSAndroid Build Coastguard Worker
314*4d7e907cSAndroid Build Coastguard Worker } // namespace implementation
315*4d7e907cSAndroid Build Coastguard Worker } // namespace V2_0
316*4d7e907cSAndroid Build Coastguard Worker } // namespace broadcastradio
317*4d7e907cSAndroid Build Coastguard Worker } // namespace hardware
318*4d7e907cSAndroid Build Coastguard Worker } // namespace android
319