1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #define LOG_TAG "BroadcastRadioDefault.module" 17 #define LOG_NDEBUG 0 18 19 #include "BroadcastRadio.h" 20 21 #include <log/log.h> 22 23 #include "resources.h" 24 25 namespace android { 26 namespace hardware { 27 namespace broadcastradio { 28 namespace V1_1 { 29 namespace implementation { 30 31 using V1_0::Band; 32 using V1_0::BandConfig; 33 using V1_0::Class; 34 using V1_0::Deemphasis; 35 using V1_0::Rds; 36 37 using std::lock_guard; 38 using std::map; 39 using std::mutex; 40 using std::vector; 41 42 // clang-format off 43 static const map<Class, ModuleConfig> gModuleConfigs{ 44 {Class::AM_FM, ModuleConfig({ 45 "Digital radio mock", 46 { // amFmBands 47 AmFmBandConfig({ 48 Band::AM, 49 153, // lowerLimit 50 26100, // upperLimit 51 {5, 9, 10}, // spacings 52 }), 53 AmFmBandConfig({ 54 Band::FM, 55 65800, // lowerLimit 56 108000, // upperLimit 57 {10, 100, 200}, // spacings 58 }), 59 AmFmBandConfig({ 60 Band::AM_HD, 61 153, // lowerLimit 62 26100, // upperLimit 63 {5, 9, 10}, // spacings 64 }), 65 AmFmBandConfig({ 66 Band::FM_HD, 67 87700, // lowerLimit 68 107900, // upperLimit 69 {200}, // spacings 70 }), 71 }, 72 })}, 73 74 {Class::SAT, ModuleConfig({ 75 "Satellite radio mock", 76 {}, // amFmBands 77 })}, 78 }; 79 // clang-format on 80 81 BroadcastRadio::BroadcastRadio(Class classId) 82 : mClassId(classId), mConfig(gModuleConfigs.at(classId)) {} 83 84 bool BroadcastRadio::isSupported(Class classId) { 85 return gModuleConfigs.find(classId) != gModuleConfigs.end(); 86 } 87 88 Return<void> BroadcastRadio::getProperties(getProperties_cb _hidl_cb) { 89 ALOGV("%s", __func__); 90 return getProperties_1_1( 91 [&](const Properties& properties) { _hidl_cb(Result::OK, properties.base); }); 92 } 93 94 Return<void> BroadcastRadio::getProperties_1_1(getProperties_1_1_cb _hidl_cb) { 95 ALOGV("%s", __func__); 96 Properties prop11 = {}; 97 auto& prop10 = prop11.base; 98 99 prop10.classId = mClassId; 100 prop10.implementor = "Google"; 101 prop10.product = mConfig.productName; 102 prop10.numTuners = 1; 103 prop10.numAudioSources = 1; 104 prop10.supportsCapture = false; 105 prop11.supportsBackgroundScanning = false; 106 prop11.supportedProgramTypes = hidl_vec<uint32_t>({ 107 static_cast<uint32_t>(ProgramType::AM), static_cast<uint32_t>(ProgramType::FM), 108 static_cast<uint32_t>(ProgramType::AM_HD), static_cast<uint32_t>(ProgramType::FM_HD), 109 }); 110 prop11.supportedIdentifierTypes = hidl_vec<uint32_t>({ 111 static_cast<uint32_t>(IdentifierType::AMFM_FREQUENCY), 112 static_cast<uint32_t>(IdentifierType::RDS_PI), 113 static_cast<uint32_t>(IdentifierType::HD_STATION_ID_EXT), 114 static_cast<uint32_t>(IdentifierType::HD_SUBCHANNEL), 115 }); 116 prop11.vendorInfo = hidl_vec<VendorKeyValue>({ 117 {"com.google.dummy", "dummy"}, 118 }); 119 120 prop10.bands.resize(mConfig.amFmBands.size()); 121 for (size_t i = 0; i < mConfig.amFmBands.size(); i++) { 122 auto& src = mConfig.amFmBands[i]; 123 auto& dst = prop10.bands[i]; 124 125 dst.type = src.type; 126 dst.antennaConnected = true; 127 dst.lowerLimit = src.lowerLimit; 128 dst.upperLimit = src.upperLimit; 129 dst.spacings = src.spacings; 130 131 if (utils::isAm(src.type)) { 132 dst.ext.am.stereo = true; 133 } else if (utils::isFm(src.type)) { 134 dst.ext.fm.deemphasis = static_cast<Deemphasis>(Deemphasis::D50 | Deemphasis::D75); 135 dst.ext.fm.stereo = true; 136 dst.ext.fm.rds = static_cast<Rds>(Rds::WORLD | Rds::US); 137 dst.ext.fm.ta = true; 138 dst.ext.fm.af = true; 139 dst.ext.fm.ea = true; 140 } 141 } 142 143 _hidl_cb(prop11); 144 return Void(); 145 } 146 147 Return<void> BroadcastRadio::openTuner(const BandConfig& config, bool audio __unused, 148 const sp<V1_0::ITunerCallback>& callback, 149 openTuner_cb _hidl_cb) { 150 ALOGV("%s(%s)", __func__, toString(config.type).c_str()); 151 lock_guard<mutex> lk(mMut); 152 153 auto oldTuner = mTuner.promote(); 154 if (oldTuner != nullptr) { 155 ALOGI("Force-closing previously opened tuner"); 156 oldTuner->forceClose(); 157 mTuner = nullptr; 158 } 159 160 sp<Tuner> newTuner = new Tuner(mClassId, callback); 161 mTuner = newTuner; 162 if (mClassId == Class::AM_FM) { 163 auto ret = newTuner->setConfiguration(config); 164 if (ret != Result::OK) { 165 _hidl_cb(Result::INVALID_ARGUMENTS, {}); 166 return Void(); 167 } 168 } 169 170 _hidl_cb(Result::OK, newTuner); 171 return Void(); 172 } 173 174 Return<void> BroadcastRadio::getImage(int32_t id, getImage_cb _hidl_cb) { 175 ALOGV("%s(%x)", __func__, id); 176 177 if (id == resources::demoPngId) { 178 _hidl_cb(std::vector<uint8_t>(resources::demoPng, std::end(resources::demoPng))); 179 return {}; 180 } 181 182 ALOGI("Image %x doesn't exists", id); 183 _hidl_cb({}); 184 return Void(); 185 } 186 187 } // namespace implementation 188 } // namespace V1_1 189 } // namespace broadcastradio 190 } // namespace hardware 191 } // namespace android 192