xref: /aosp_15_r20/hardware/interfaces/broadcastradio/2.0/default/TunerSession.cpp (revision 4d7e907c777eeecc4c5bd7cf640a754fac206ff7)
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