Home | History | Annotate | Download | only in radio
      1 /*
      2  * Copyright (C) 2016 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 
     17 #define LOG_TAG "RadioHalHidl"
     18 //#define LOG_NDEBUG 0
     19 
     20 #include <media/audiohal/hidl/HalDeathHandler.h>
     21 #include <utils/Log.h>
     22 #include <utils/misc.h>
     23 #include <system/RadioMetadataWrapper.h>
     24 #include <android/hardware/broadcastradio/1.0/IBroadcastRadioFactory.h>
     25 
     26 #include "RadioHalHidl.h"
     27 #include "HidlUtils.h"
     28 
     29 namespace android {
     30 
     31 using android::hardware::broadcastradio::V1_0::IBroadcastRadioFactory;
     32 using android::hardware::broadcastradio::V1_0::Class;
     33 using android::hardware::broadcastradio::V1_0::Direction;
     34 using android::hardware::broadcastradio::V1_0::Properties;
     35 
     36 
     37 /* static */
     38 sp<RadioInterface> RadioInterface::connectModule(radio_class_t classId)
     39 {
     40     return new RadioHalHidl(classId);
     41 }
     42 
     43 int RadioHalHidl::getProperties(radio_hal_properties_t *properties)
     44 {
     45     ALOGV("%s IN", __FUNCTION__);
     46     sp<IBroadcastRadio> module = getService();
     47     if (module == 0) {
     48         return -ENODEV;
     49     }
     50     Properties halProperties;
     51     Result halResult = Result::NOT_INITIALIZED;
     52     Return<void> hidlReturn =
     53             module->getProperties([&](Result result, const Properties& properties) {
     54                     halResult = result;
     55                     if (result == Result::OK) {
     56                         halProperties = properties;
     57                     }
     58                 });
     59 
     60     if (halResult == Result::OK) {
     61         HidlUtils::convertPropertiesFromHal(properties, &halProperties);
     62     }
     63     return HidlUtils::convertHalResult(halResult);
     64 }
     65 
     66 int RadioHalHidl::openTuner(const radio_hal_band_config_t *config,
     67                             bool audio,
     68                             sp<TunerCallbackInterface> callback,
     69                             sp<TunerInterface>& tuner)
     70 {
     71     sp<IBroadcastRadio> module = getService();
     72     if (module == 0) {
     73         return -ENODEV;
     74     }
     75     sp<Tuner> tunerImpl = new Tuner(callback, this);
     76 
     77     BandConfig halConfig;
     78     Result halResult = Result::NOT_INITIALIZED;
     79     sp<ITuner> halTuner;
     80 
     81     HidlUtils::convertBandConfigToHal(&halConfig, config);
     82     Return<void> hidlReturn =
     83             module->openTuner(halConfig, audio, tunerImpl,
     84                               [&](Result result, const sp<ITuner>& tuner) {
     85                     halResult = result;
     86                     if (result == Result::OK) {
     87                         halTuner = tuner;
     88                     }
     89                 });
     90 
     91     if (halResult == Result::OK) {
     92         tunerImpl->setHalTuner(halTuner);
     93         tuner = tunerImpl;
     94     }
     95 
     96     return HidlUtils::convertHalResult(halResult);
     97 }
     98 
     99 int RadioHalHidl::closeTuner(sp<TunerInterface>& tuner)
    100 {
    101     sp<Tuner> tunerImpl = static_cast<Tuner *>(tuner.get());
    102     sp<ITuner> clearTuner;
    103     tunerImpl->setHalTuner(clearTuner);
    104     return 0;
    105 }
    106 
    107 RadioHalHidl::RadioHalHidl(radio_class_t classId)
    108     : mClassId(classId)
    109 {
    110 }
    111 
    112 RadioHalHidl::~RadioHalHidl()
    113 {
    114 }
    115 
    116 sp<IBroadcastRadio> RadioHalHidl::getService()
    117 {
    118     if (mHalModule == 0) {
    119         sp<IBroadcastRadioFactory> factory = IBroadcastRadioFactory::getService();
    120         if (factory != 0) {
    121             factory->connectModule(static_cast<Class>(mClassId),
    122                                [&](Result retval, const ::android::sp<IBroadcastRadio>& result) {
    123                 if (retval == Result::OK) {
    124                     mHalModule = result;
    125                 }
    126             });
    127         }
    128     }
    129     ALOGV("%s OUT module %p", __FUNCTION__, mHalModule.get());
    130     return mHalModule;
    131 }
    132 
    133 void RadioHalHidl::clearService()
    134 {
    135     ALOGV("%s IN module %p", __FUNCTION__, mHalModule.get());
    136     mHalModule.clear();
    137 }
    138 
    139 
    140 int RadioHalHidl::Tuner::setConfiguration(const radio_hal_band_config_t *config)
    141 {
    142     ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
    143 
    144     if (mHalTuner == 0) {
    145         return -ENODEV;
    146     }
    147     BandConfig halConfig;
    148     HidlUtils::convertBandConfigToHal(&halConfig, config);
    149 
    150     Return<Result> hidlResult = mHalTuner->setConfiguration(halConfig);
    151     return HidlUtils::convertHalResult(hidlResult);
    152 }
    153 
    154 int RadioHalHidl::Tuner::getConfiguration(radio_hal_band_config_t *config)
    155 {
    156     ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
    157     if (mHalTuner == 0) {
    158         return -ENODEV;
    159     }
    160     BandConfig halConfig;
    161     Result halResult;
    162     Return<void> hidlReturn =
    163             mHalTuner->getConfiguration([&](Result result, const BandConfig& config) {
    164                     halResult = result;
    165                     if (result == Result::OK) {
    166                         halConfig = config;
    167                     }
    168                 });
    169     if (hidlReturn.isOk() && halResult == Result::OK) {
    170         HidlUtils::convertBandConfigFromHal(config, &halConfig);
    171     }
    172     return HidlUtils::convertHalResult(halResult);
    173 }
    174 
    175 int RadioHalHidl::Tuner::scan(radio_direction_t direction, bool skip_sub_channel)
    176 {
    177     ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
    178     if (mHalTuner == 0) {
    179         return -ENODEV;
    180     }
    181     Return<Result> hidlResult =
    182             mHalTuner->scan(static_cast<Direction>(direction), skip_sub_channel);
    183     return HidlUtils::convertHalResult(hidlResult);
    184 }
    185 
    186 int RadioHalHidl::Tuner::step(radio_direction_t direction, bool skip_sub_channel)
    187 {
    188     ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
    189     if (mHalTuner == 0) {
    190         return -ENODEV;
    191     }
    192     Return<Result> hidlResult =
    193             mHalTuner->step(static_cast<Direction>(direction), skip_sub_channel);
    194     return HidlUtils::convertHalResult(hidlResult);
    195 }
    196 
    197 int RadioHalHidl::Tuner::tune(unsigned int channel, unsigned int sub_channel)
    198 {
    199     ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
    200     if (mHalTuner == 0) {
    201         return -ENODEV;
    202     }
    203     Return<Result> hidlResult =
    204             mHalTuner->tune(channel, sub_channel);
    205     return HidlUtils::convertHalResult(hidlResult);
    206 }
    207 
    208 int RadioHalHidl::Tuner::cancel()
    209 {
    210     ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
    211     if (mHalTuner == 0) {
    212         return -ENODEV;
    213     }
    214     Return<Result> hidlResult = mHalTuner->cancel();
    215     return HidlUtils::convertHalResult(hidlResult);
    216 }
    217 
    218 int RadioHalHidl::Tuner::getProgramInformation(radio_program_info_t *info)
    219 {
    220     ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
    221     if (mHalTuner == 0) {
    222         return -ENODEV;
    223     }
    224     if (info == nullptr || info->metadata == nullptr) {
    225         return BAD_VALUE;
    226     }
    227     ProgramInfo halInfo;
    228     Result halResult;
    229     Return<void> hidlReturn = mHalTuner->getProgramInformation(
    230         [&](Result result, const ProgramInfo& info) {
    231             halResult = result;
    232             if (result == Result::OK) {
    233                 halInfo = info;
    234             }
    235         });
    236     if (hidlReturn.isOk() && halResult == Result::OK) {
    237         HidlUtils::convertProgramInfoFromHal(info, &halInfo);
    238     }
    239     return HidlUtils::convertHalResult(halResult);
    240 }
    241 
    242 Return<void> RadioHalHidl::Tuner::hardwareFailure()
    243 {
    244     ALOGV("%s IN", __FUNCTION__);
    245     handleHwFailure();
    246     return Return<void>();
    247 }
    248 
    249 Return<void> RadioHalHidl::Tuner::configChange(Result result, const BandConfig& config)
    250 {
    251     ALOGV("%s IN", __FUNCTION__);
    252     radio_hal_event_t event;
    253     memset(&event, 0, sizeof(radio_hal_event_t));
    254     event.type = RADIO_EVENT_CONFIG;
    255     event.status = HidlUtils::convertHalResult(result);
    256     HidlUtils::convertBandConfigFromHal(&event.config, &config);
    257     onCallback(&event);
    258     return Return<void>();
    259 }
    260 
    261 Return<void> RadioHalHidl::Tuner::tuneComplete(Result result, const ProgramInfo& info)
    262 {
    263     ALOGV("%s IN", __FUNCTION__);
    264     radio_hal_event_t event = {};
    265     RadioMetadataWrapper metadataWrapper(&event.info.metadata);
    266 
    267     event.type = RADIO_EVENT_TUNED;
    268     event.status = HidlUtils::convertHalResult(result);
    269     HidlUtils::convertProgramInfoFromHal(&event.info, &info);
    270     onCallback(&event);
    271     return Return<void>();
    272 }
    273 
    274 Return<void> RadioHalHidl::Tuner::afSwitch(const ProgramInfo& info)
    275 {
    276     ALOGV("%s IN", __FUNCTION__);
    277     radio_hal_event_t event = {};
    278     RadioMetadataWrapper metadataWrapper(&event.info.metadata);
    279 
    280     event.type = RADIO_EVENT_AF_SWITCH;
    281     HidlUtils::convertProgramInfoFromHal(&event.info, &info);
    282     onCallback(&event);
    283     return Return<void>();
    284 }
    285 
    286 Return<void> RadioHalHidl::Tuner::antennaStateChange(bool connected)
    287 {
    288     ALOGV("%s IN", __FUNCTION__);
    289     radio_hal_event_t event;
    290     memset(&event, 0, sizeof(radio_hal_event_t));
    291     event.type = RADIO_EVENT_ANTENNA;
    292     event.on = connected;
    293     onCallback(&event);
    294     return Return<void>();
    295 }
    296 Return<void> RadioHalHidl::Tuner::trafficAnnouncement(bool active)
    297 {
    298     ALOGV("%s IN", __FUNCTION__);
    299     radio_hal_event_t event;
    300     memset(&event, 0, sizeof(radio_hal_event_t));
    301     event.type = RADIO_EVENT_TA;
    302     event.on = active;
    303     onCallback(&event);
    304     return Return<void>();
    305 }
    306 Return<void> RadioHalHidl::Tuner::emergencyAnnouncement(bool active)
    307 {
    308     ALOGV("%s IN", __FUNCTION__);
    309     radio_hal_event_t event;
    310     memset(&event, 0, sizeof(radio_hal_event_t));
    311     event.type = RADIO_EVENT_EA;
    312     event.on = active;
    313     onCallback(&event);
    314     return Return<void>();
    315 }
    316 Return<void> RadioHalHidl::Tuner::newMetadata(uint32_t channel, uint32_t subChannel,
    317                                           const ::android::hardware::hidl_vec<MetaData>& metadata)
    318 {
    319     ALOGV("%s IN", __FUNCTION__);
    320     radio_hal_event_t event = {};
    321     RadioMetadataWrapper metadataWrapper(&event.metadata);
    322 
    323     event.type = RADIO_EVENT_METADATA;
    324     HidlUtils::convertMetaDataFromHal(&event.metadata, metadata, channel, subChannel);
    325     onCallback(&event);
    326     return Return<void>();
    327 }
    328 
    329 
    330 RadioHalHidl::Tuner::Tuner(sp<TunerCallbackInterface> callback, sp<RadioHalHidl> module)
    331     : TunerInterface(), mHalTuner(NULL), mCallback(callback), mParentModule(module)
    332 {
    333     // Make sure the handler we are passing in only deals with const members,
    334     // as it can be called on an arbitrary thread.
    335     const auto& self = this;
    336     HalDeathHandler::getInstance()->registerAtExitHandler(
    337             this, [&self]() { self->sendHwFailureEvent(); });
    338 }
    339 
    340 
    341 RadioHalHidl::Tuner::~Tuner()
    342 {
    343     HalDeathHandler::getInstance()->unregisterAtExitHandler(this);
    344 }
    345 
    346 void RadioHalHidl::Tuner::setHalTuner(sp<ITuner>& halTuner) {
    347     if (mHalTuner != 0) {
    348         mHalTuner->unlinkToDeath(HalDeathHandler::getInstance());
    349     }
    350     mHalTuner = halTuner;
    351     if (mHalTuner != 0) {
    352         mHalTuner->linkToDeath(HalDeathHandler::getInstance(), 0 /*cookie*/);
    353     }
    354 }
    355 
    356 void RadioHalHidl::Tuner::handleHwFailure()
    357 {
    358     ALOGV("%s IN", __FUNCTION__);
    359     sp<RadioHalHidl> parentModule = mParentModule.promote();
    360     if (parentModule != 0) {
    361         parentModule->clearService();
    362     }
    363     sendHwFailureEvent();
    364     mHalTuner.clear();
    365 }
    366 
    367 void RadioHalHidl::Tuner::sendHwFailureEvent() const
    368 {
    369     radio_hal_event_t event;
    370     memset(&event, 0, sizeof(radio_hal_event_t));
    371     event.type = RADIO_EVENT_HW_FAILURE;
    372     onCallback(&event);
    373 }
    374 
    375 void RadioHalHidl::Tuner::onCallback(radio_hal_event_t *halEvent) const
    376 {
    377     if (mCallback != 0) {
    378         mCallback->onEvent(halEvent);
    379     }
    380 }
    381 
    382 } // namespace android
    383