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