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 
     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