xref: /aosp_15_r20/hardware/interfaces/broadcastradio/1.1/default/BroadcastRadio.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 #define LOG_TAG "BroadcastRadioDefault.module"
17*4d7e907cSAndroid Build Coastguard Worker #define LOG_NDEBUG 0
18*4d7e907cSAndroid Build Coastguard Worker 
19*4d7e907cSAndroid Build Coastguard Worker #include "BroadcastRadio.h"
20*4d7e907cSAndroid Build Coastguard Worker 
21*4d7e907cSAndroid Build Coastguard Worker #include <log/log.h>
22*4d7e907cSAndroid Build Coastguard Worker 
23*4d7e907cSAndroid Build Coastguard Worker #include "resources.h"
24*4d7e907cSAndroid Build Coastguard Worker 
25*4d7e907cSAndroid Build Coastguard Worker namespace android {
26*4d7e907cSAndroid Build Coastguard Worker namespace hardware {
27*4d7e907cSAndroid Build Coastguard Worker namespace broadcastradio {
28*4d7e907cSAndroid Build Coastguard Worker namespace V1_1 {
29*4d7e907cSAndroid Build Coastguard Worker namespace implementation {
30*4d7e907cSAndroid Build Coastguard Worker 
31*4d7e907cSAndroid Build Coastguard Worker using V1_0::Band;
32*4d7e907cSAndroid Build Coastguard Worker using V1_0::BandConfig;
33*4d7e907cSAndroid Build Coastguard Worker using V1_0::Class;
34*4d7e907cSAndroid Build Coastguard Worker using V1_0::Deemphasis;
35*4d7e907cSAndroid Build Coastguard Worker using V1_0::Rds;
36*4d7e907cSAndroid Build Coastguard Worker using V1_1::IdentifierType;
37*4d7e907cSAndroid Build Coastguard Worker using V1_1::ProgramSelector;
38*4d7e907cSAndroid Build Coastguard Worker using V1_1::ProgramType;
39*4d7e907cSAndroid Build Coastguard Worker using V1_1::Properties;
40*4d7e907cSAndroid Build Coastguard Worker using V1_1::VendorKeyValue;
41*4d7e907cSAndroid Build Coastguard Worker 
42*4d7e907cSAndroid Build Coastguard Worker using std::lock_guard;
43*4d7e907cSAndroid Build Coastguard Worker using std::map;
44*4d7e907cSAndroid Build Coastguard Worker using std::mutex;
45*4d7e907cSAndroid Build Coastguard Worker using std::vector;
46*4d7e907cSAndroid Build Coastguard Worker 
47*4d7e907cSAndroid Build Coastguard Worker // clang-format off
48*4d7e907cSAndroid Build Coastguard Worker static const map<Class, ModuleConfig> gModuleConfigs{
49*4d7e907cSAndroid Build Coastguard Worker     {Class::AM_FM, ModuleConfig({
50*4d7e907cSAndroid Build Coastguard Worker         "Digital radio mock",
51*4d7e907cSAndroid Build Coastguard Worker         {  // amFmBands
52*4d7e907cSAndroid Build Coastguard Worker             AmFmBandConfig({
53*4d7e907cSAndroid Build Coastguard Worker                 Band::AM,
54*4d7e907cSAndroid Build Coastguard Worker                 153,         // lowerLimit
55*4d7e907cSAndroid Build Coastguard Worker                 26100,       // upperLimit
56*4d7e907cSAndroid Build Coastguard Worker                 {5, 9, 10},  // spacings
57*4d7e907cSAndroid Build Coastguard Worker             }),
58*4d7e907cSAndroid Build Coastguard Worker             AmFmBandConfig({
59*4d7e907cSAndroid Build Coastguard Worker                 Band::FM,
60*4d7e907cSAndroid Build Coastguard Worker                 65800,           // lowerLimit
61*4d7e907cSAndroid Build Coastguard Worker                 108000,          // upperLimit
62*4d7e907cSAndroid Build Coastguard Worker                 {10, 100, 200},  // spacings
63*4d7e907cSAndroid Build Coastguard Worker             }),
64*4d7e907cSAndroid Build Coastguard Worker             AmFmBandConfig({
65*4d7e907cSAndroid Build Coastguard Worker                 Band::AM_HD,
66*4d7e907cSAndroid Build Coastguard Worker                 153,         // lowerLimit
67*4d7e907cSAndroid Build Coastguard Worker                 26100,       // upperLimit
68*4d7e907cSAndroid Build Coastguard Worker                 {5, 9, 10},  // spacings
69*4d7e907cSAndroid Build Coastguard Worker             }),
70*4d7e907cSAndroid Build Coastguard Worker             AmFmBandConfig({
71*4d7e907cSAndroid Build Coastguard Worker                 Band::FM_HD,
72*4d7e907cSAndroid Build Coastguard Worker                 87700,   // lowerLimit
73*4d7e907cSAndroid Build Coastguard Worker                 107900,  // upperLimit
74*4d7e907cSAndroid Build Coastguard Worker                 {200},   // spacings
75*4d7e907cSAndroid Build Coastguard Worker             }),
76*4d7e907cSAndroid Build Coastguard Worker         },
77*4d7e907cSAndroid Build Coastguard Worker     })},
78*4d7e907cSAndroid Build Coastguard Worker 
79*4d7e907cSAndroid Build Coastguard Worker     {Class::SAT, ModuleConfig({
80*4d7e907cSAndroid Build Coastguard Worker         "Satellite radio mock",
81*4d7e907cSAndroid Build Coastguard Worker         {},  // amFmBands
82*4d7e907cSAndroid Build Coastguard Worker     })},
83*4d7e907cSAndroid Build Coastguard Worker };
84*4d7e907cSAndroid Build Coastguard Worker // clang-format on
85*4d7e907cSAndroid Build Coastguard Worker 
BroadcastRadio(Class classId)86*4d7e907cSAndroid Build Coastguard Worker BroadcastRadio::BroadcastRadio(Class classId)
87*4d7e907cSAndroid Build Coastguard Worker     : mClassId(classId), mConfig(gModuleConfigs.at(classId)) {}
88*4d7e907cSAndroid Build Coastguard Worker 
isSupported(Class classId)89*4d7e907cSAndroid Build Coastguard Worker bool BroadcastRadio::isSupported(Class classId) {
90*4d7e907cSAndroid Build Coastguard Worker     return gModuleConfigs.find(classId) != gModuleConfigs.end();
91*4d7e907cSAndroid Build Coastguard Worker }
92*4d7e907cSAndroid Build Coastguard Worker 
getProperties(getProperties_cb _hidl_cb)93*4d7e907cSAndroid Build Coastguard Worker Return<void> BroadcastRadio::getProperties(getProperties_cb _hidl_cb) {
94*4d7e907cSAndroid Build Coastguard Worker     ALOGV("%s", __func__);
95*4d7e907cSAndroid Build Coastguard Worker     return getProperties_1_1(
96*4d7e907cSAndroid Build Coastguard Worker         [&](const Properties& properties) { _hidl_cb(Result::OK, properties.base); });
97*4d7e907cSAndroid Build Coastguard Worker }
98*4d7e907cSAndroid Build Coastguard Worker 
getProperties_1_1(getProperties_1_1_cb _hidl_cb)99*4d7e907cSAndroid Build Coastguard Worker Return<void> BroadcastRadio::getProperties_1_1(getProperties_1_1_cb _hidl_cb) {
100*4d7e907cSAndroid Build Coastguard Worker     ALOGV("%s", __func__);
101*4d7e907cSAndroid Build Coastguard Worker     Properties prop11 = {};
102*4d7e907cSAndroid Build Coastguard Worker     auto& prop10 = prop11.base;
103*4d7e907cSAndroid Build Coastguard Worker 
104*4d7e907cSAndroid Build Coastguard Worker     prop10.classId = mClassId;
105*4d7e907cSAndroid Build Coastguard Worker     prop10.implementor = "Google";
106*4d7e907cSAndroid Build Coastguard Worker     prop10.product = mConfig.productName;
107*4d7e907cSAndroid Build Coastguard Worker     prop10.numTuners = 1;
108*4d7e907cSAndroid Build Coastguard Worker     prop10.numAudioSources = 1;
109*4d7e907cSAndroid Build Coastguard Worker     prop10.supportsCapture = false;
110*4d7e907cSAndroid Build Coastguard Worker     prop11.supportsBackgroundScanning = true;
111*4d7e907cSAndroid Build Coastguard Worker     prop11.supportedProgramTypes = hidl_vec<uint32_t>({
112*4d7e907cSAndroid Build Coastguard Worker         static_cast<uint32_t>(ProgramType::AM), static_cast<uint32_t>(ProgramType::FM),
113*4d7e907cSAndroid Build Coastguard Worker         static_cast<uint32_t>(ProgramType::AM_HD), static_cast<uint32_t>(ProgramType::FM_HD),
114*4d7e907cSAndroid Build Coastguard Worker     });
115*4d7e907cSAndroid Build Coastguard Worker     prop11.supportedIdentifierTypes = hidl_vec<uint32_t>({
116*4d7e907cSAndroid Build Coastguard Worker         static_cast<uint32_t>(IdentifierType::AMFM_FREQUENCY),
117*4d7e907cSAndroid Build Coastguard Worker         static_cast<uint32_t>(IdentifierType::RDS_PI),
118*4d7e907cSAndroid Build Coastguard Worker         static_cast<uint32_t>(IdentifierType::HD_STATION_ID_EXT),
119*4d7e907cSAndroid Build Coastguard Worker         static_cast<uint32_t>(IdentifierType::HD_SUBCHANNEL),
120*4d7e907cSAndroid Build Coastguard Worker     });
121*4d7e907cSAndroid Build Coastguard Worker     prop11.vendorInfo = hidl_vec<VendorKeyValue>({
122*4d7e907cSAndroid Build Coastguard Worker         {"com.google.dummy", "dummy"},
123*4d7e907cSAndroid Build Coastguard Worker     });
124*4d7e907cSAndroid Build Coastguard Worker 
125*4d7e907cSAndroid Build Coastguard Worker     prop10.bands = getAmFmBands();
126*4d7e907cSAndroid Build Coastguard Worker 
127*4d7e907cSAndroid Build Coastguard Worker     _hidl_cb(prop11);
128*4d7e907cSAndroid Build Coastguard Worker     return Void();
129*4d7e907cSAndroid Build Coastguard Worker }
130*4d7e907cSAndroid Build Coastguard Worker 
openTuner(const BandConfig & config,bool audio __unused,const sp<V1_0::ITunerCallback> & callback,openTuner_cb _hidl_cb)131*4d7e907cSAndroid Build Coastguard Worker Return<void> BroadcastRadio::openTuner(const BandConfig& config, bool audio __unused,
132*4d7e907cSAndroid Build Coastguard Worker                                        const sp<V1_0::ITunerCallback>& callback,
133*4d7e907cSAndroid Build Coastguard Worker                                        openTuner_cb _hidl_cb) {
134*4d7e907cSAndroid Build Coastguard Worker     ALOGV("%s(%s)", __func__, toString(config.type).c_str());
135*4d7e907cSAndroid Build Coastguard Worker     lock_guard<mutex> lk(mMut);
136*4d7e907cSAndroid Build Coastguard Worker 
137*4d7e907cSAndroid Build Coastguard Worker     auto oldTuner = mTuner.promote();
138*4d7e907cSAndroid Build Coastguard Worker     if (oldTuner != nullptr) {
139*4d7e907cSAndroid Build Coastguard Worker         ALOGI("Force-closing previously opened tuner");
140*4d7e907cSAndroid Build Coastguard Worker         oldTuner->forceClose();
141*4d7e907cSAndroid Build Coastguard Worker         mTuner = nullptr;
142*4d7e907cSAndroid Build Coastguard Worker     }
143*4d7e907cSAndroid Build Coastguard Worker 
144*4d7e907cSAndroid Build Coastguard Worker     sp<Tuner> newTuner = new Tuner(this, mClassId, callback);
145*4d7e907cSAndroid Build Coastguard Worker     mTuner = newTuner;
146*4d7e907cSAndroid Build Coastguard Worker     if (mClassId == Class::AM_FM) {
147*4d7e907cSAndroid Build Coastguard Worker         auto ret = newTuner->setConfiguration(config);
148*4d7e907cSAndroid Build Coastguard Worker         if (ret != Result::OK) {
149*4d7e907cSAndroid Build Coastguard Worker             _hidl_cb(Result::INVALID_ARGUMENTS, {});
150*4d7e907cSAndroid Build Coastguard Worker             return Void();
151*4d7e907cSAndroid Build Coastguard Worker         }
152*4d7e907cSAndroid Build Coastguard Worker     }
153*4d7e907cSAndroid Build Coastguard Worker 
154*4d7e907cSAndroid Build Coastguard Worker     _hidl_cb(Result::OK, newTuner);
155*4d7e907cSAndroid Build Coastguard Worker     return Void();
156*4d7e907cSAndroid Build Coastguard Worker }
157*4d7e907cSAndroid Build Coastguard Worker 
getImage(int32_t id,getImage_cb _hidl_cb)158*4d7e907cSAndroid Build Coastguard Worker Return<void> BroadcastRadio::getImage(int32_t id, getImage_cb _hidl_cb) {
159*4d7e907cSAndroid Build Coastguard Worker     ALOGV("%s(%x)", __func__, id);
160*4d7e907cSAndroid Build Coastguard Worker 
161*4d7e907cSAndroid Build Coastguard Worker     if (id == resources::demoPngId) {
162*4d7e907cSAndroid Build Coastguard Worker         _hidl_cb(std::vector<uint8_t>(resources::demoPng, std::end(resources::demoPng)));
163*4d7e907cSAndroid Build Coastguard Worker         return {};
164*4d7e907cSAndroid Build Coastguard Worker     }
165*4d7e907cSAndroid Build Coastguard Worker 
166*4d7e907cSAndroid Build Coastguard Worker     ALOGI("Image %x doesn't exists", id);
167*4d7e907cSAndroid Build Coastguard Worker     _hidl_cb({});
168*4d7e907cSAndroid Build Coastguard Worker     return Void();
169*4d7e907cSAndroid Build Coastguard Worker }
170*4d7e907cSAndroid Build Coastguard Worker 
getAmFmBands() const171*4d7e907cSAndroid Build Coastguard Worker std::vector<V1_0::BandConfig> BroadcastRadio::getAmFmBands() const {
172*4d7e907cSAndroid Build Coastguard Worker     std::vector<V1_0::BandConfig> out;
173*4d7e907cSAndroid Build Coastguard Worker     for (auto&& src : mConfig.amFmBands) {
174*4d7e907cSAndroid Build Coastguard Worker         V1_0::BandConfig dst;
175*4d7e907cSAndroid Build Coastguard Worker 
176*4d7e907cSAndroid Build Coastguard Worker         dst.type = src.type;
177*4d7e907cSAndroid Build Coastguard Worker         dst.antennaConnected = true;
178*4d7e907cSAndroid Build Coastguard Worker         dst.lowerLimit = src.lowerLimit;
179*4d7e907cSAndroid Build Coastguard Worker         dst.upperLimit = src.upperLimit;
180*4d7e907cSAndroid Build Coastguard Worker         dst.spacings = src.spacings;
181*4d7e907cSAndroid Build Coastguard Worker 
182*4d7e907cSAndroid Build Coastguard Worker         if (utils::isAm(src.type)) {
183*4d7e907cSAndroid Build Coastguard Worker             dst.ext.am.stereo = true;
184*4d7e907cSAndroid Build Coastguard Worker         } else if (utils::isFm(src.type)) {
185*4d7e907cSAndroid Build Coastguard Worker             dst.ext.fm.deemphasis = static_cast<Deemphasis>(Deemphasis::D50 | Deemphasis::D75);
186*4d7e907cSAndroid Build Coastguard Worker             dst.ext.fm.stereo = true;
187*4d7e907cSAndroid Build Coastguard Worker             dst.ext.fm.rds = static_cast<Rds>(Rds::WORLD | Rds::US);
188*4d7e907cSAndroid Build Coastguard Worker             dst.ext.fm.ta = true;
189*4d7e907cSAndroid Build Coastguard Worker             dst.ext.fm.af = true;
190*4d7e907cSAndroid Build Coastguard Worker             dst.ext.fm.ea = true;
191*4d7e907cSAndroid Build Coastguard Worker         }
192*4d7e907cSAndroid Build Coastguard Worker 
193*4d7e907cSAndroid Build Coastguard Worker         out.push_back(dst);
194*4d7e907cSAndroid Build Coastguard Worker     }
195*4d7e907cSAndroid Build Coastguard Worker     return out;
196*4d7e907cSAndroid Build Coastguard Worker }
197*4d7e907cSAndroid Build Coastguard Worker 
198*4d7e907cSAndroid Build Coastguard Worker }  // namespace implementation
199*4d7e907cSAndroid Build Coastguard Worker }  // namespace V1_1
200*4d7e907cSAndroid Build Coastguard Worker }  // namespace broadcastradio
201*4d7e907cSAndroid Build Coastguard Worker }  // namespace hardware
202*4d7e907cSAndroid Build Coastguard Worker }  // namespace android
203