/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "RadioHalHidl"
//#define LOG_NDEBUG 0

#include <media/audiohal/hidl/HalDeathHandler.h>
#include <utils/Log.h>
#include <utils/misc.h>
#include <system/radio_metadata.h>
#include <android/hardware/broadcastradio/1.0/IBroadcastRadioFactory.h>

#include "RadioHalHidl.h"
#include "HidlUtils.h"

namespace android {

using android::hardware::broadcastradio::V1_0::IBroadcastRadioFactory;
using android::hardware::broadcastradio::V1_0::Class;
using android::hardware::broadcastradio::V1_0::Direction;
using android::hardware::broadcastradio::V1_0::Properties;


/* static */
sp<RadioInterface> RadioInterface::connectModule(radio_class_t classId)
{
    return new RadioHalHidl(classId);
}

int RadioHalHidl::getProperties(radio_hal_properties_t *properties)
{
    ALOGV("%s IN", __FUNCTION__);
    sp<IBroadcastRadio> module = getService();
    if (module == 0) {
        return -ENODEV;
    }
    Properties halProperties;
    Result halResult = Result::NOT_INITIALIZED;
    Return<void> hidlReturn =
            module->getProperties([&](Result result, const Properties& properties) {
                    halResult = result;
                    if (result == Result::OK) {
                        halProperties = properties;
                    }
                });

    if (halResult == Result::OK) {
        HidlUtils::convertPropertiesFromHal(properties, &halProperties);
    }
    return HidlUtils::convertHalResult(halResult);
}

int RadioHalHidl::openTuner(const radio_hal_band_config_t *config,
                            bool audio,
                            sp<TunerCallbackInterface> callback,
                            sp<TunerInterface>& tuner)
{
    sp<IBroadcastRadio> module = getService();
    if (module == 0) {
        return -ENODEV;
    }
    sp<Tuner> tunerImpl = new Tuner(callback, this);

    BandConfig halConfig;
    Result halResult = Result::NOT_INITIALIZED;
    sp<ITuner> halTuner;

    HidlUtils::convertBandConfigToHal(&halConfig, config);
    Return<void> hidlReturn =
            module->openTuner(halConfig, audio, tunerImpl,
                              [&](Result result, const sp<ITuner>& tuner) {
                    halResult = result;
                    if (result == Result::OK) {
                        halTuner = tuner;
                    }
                });

    if (halResult == Result::OK) {
        tunerImpl->setHalTuner(halTuner);
        tuner = tunerImpl;
    }

    return HidlUtils::convertHalResult(halResult);
}

int RadioHalHidl::closeTuner(sp<TunerInterface>& tuner)
{
    sp<Tuner> tunerImpl = static_cast<Tuner *>(tuner.get());
    sp<ITuner> clearTuner;
    tunerImpl->setHalTuner(clearTuner);
    return 0;
}

RadioHalHidl::RadioHalHidl(radio_class_t classId)
    : mClassId(classId)
{
}

RadioHalHidl::~RadioHalHidl()
{
}

sp<IBroadcastRadio> RadioHalHidl::getService()
{
    if (mHalModule == 0) {
        sp<IBroadcastRadioFactory> factory = IBroadcastRadioFactory::getService("broadcastradio");
        if (factory != 0) {
            factory->connectModule(static_cast<Class>(mClassId),
                               [&](Result retval, const ::android::sp<IBroadcastRadio>& result) {
                if (retval == Result::OK) {
                    mHalModule = result;
                }
            });
        }
    }
    ALOGV("%s OUT module %p", __FUNCTION__, mHalModule.get());
    return mHalModule;
}

void RadioHalHidl::clearService()
{
    ALOGV("%s IN module %p", __FUNCTION__, mHalModule.get());
    mHalModule.clear();
}


int RadioHalHidl::Tuner::setConfiguration(const radio_hal_band_config_t *config)
{
    ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());

    if (mHalTuner == 0) {
        return -ENODEV;
    }
    BandConfig halConfig;
    HidlUtils::convertBandConfigToHal(&halConfig, config);

    Return<Result> hidlResult = mHalTuner->setConfiguration(halConfig);
    return HidlUtils::convertHalResult(hidlResult);
}

int RadioHalHidl::Tuner::getConfiguration(radio_hal_band_config_t *config)
{
    ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
    if (mHalTuner == 0) {
        return -ENODEV;
    }
    BandConfig halConfig;
    Result halResult;
    Return<void> hidlReturn =
            mHalTuner->getConfiguration([&](Result result, const BandConfig& config) {
                    halResult = result;
                    if (result == Result::OK) {
                        halConfig = config;
                    }
                });
    if (hidlReturn.isOk() && halResult == Result::OK) {
        HidlUtils::convertBandConfigFromHal(config, &halConfig);
    }
    return HidlUtils::convertHalResult(halResult);
}

int RadioHalHidl::Tuner::scan(radio_direction_t direction, bool skip_sub_channel)
{
    ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
    if (mHalTuner == 0) {
        return -ENODEV;
    }
    Return<Result> hidlResult =
            mHalTuner->scan(static_cast<Direction>(direction), skip_sub_channel);
    return HidlUtils::convertHalResult(hidlResult);
}

int RadioHalHidl::Tuner::step(radio_direction_t direction, bool skip_sub_channel)
{
    ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
    if (mHalTuner == 0) {
        return -ENODEV;
    }
    Return<Result> hidlResult =
            mHalTuner->step(static_cast<Direction>(direction), skip_sub_channel);
    return HidlUtils::convertHalResult(hidlResult);
}

int RadioHalHidl::Tuner::tune(unsigned int channel, unsigned int sub_channel)
{
    ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
    if (mHalTuner == 0) {
        return -ENODEV;
    }
    Return<Result> hidlResult =
            mHalTuner->tune(channel, sub_channel);
    return HidlUtils::convertHalResult(hidlResult);
}

int RadioHalHidl::Tuner::cancel()
{
    ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
    if (mHalTuner == 0) {
        return -ENODEV;
    }
    Return<Result> hidlResult = mHalTuner->cancel();
    return HidlUtils::convertHalResult(hidlResult);
}

int RadioHalHidl::Tuner::getProgramInformation(radio_program_info_t *info)
{
    ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
    if (mHalTuner == 0) {
        return -ENODEV;
    }
    if (info == nullptr || info->metadata == nullptr) {
        return BAD_VALUE;
    }
    ProgramInfo halInfo;
    Result halResult;
    Return<void> hidlReturn = mHalTuner->getProgramInformation(
        [&](Result result, const ProgramInfo& info) {
            halResult = result;
            if (result == Result::OK) {
                halInfo = info;
            }
        });
    if (hidlReturn.isOk() && halResult == Result::OK) {
        HidlUtils::convertProgramInfoFromHal(info, &halInfo);
    }
    return HidlUtils::convertHalResult(halResult);
}

Return<void> RadioHalHidl::Tuner::hardwareFailure()
{
    ALOGV("%s IN", __FUNCTION__);
    handleHwFailure();
    return Return<void>();
}

Return<void> RadioHalHidl::Tuner::configChange(Result result, const BandConfig& config)
{
    ALOGV("%s IN", __FUNCTION__);
    radio_hal_event_t event;
    memset(&event, 0, sizeof(radio_hal_event_t));
    event.type = RADIO_EVENT_CONFIG;
    event.status = HidlUtils::convertHalResult(result);
    HidlUtils::convertBandConfigFromHal(&event.config, &config);
    onCallback(&event);
    return Return<void>();
}

Return<void> RadioHalHidl::Tuner::tuneComplete(Result result, const ProgramInfo& info)
{
    ALOGV("%s IN", __FUNCTION__);
    radio_hal_event_t event;
    memset(&event, 0, sizeof(radio_hal_event_t));
    event.type = RADIO_EVENT_TUNED;
    event.status = HidlUtils::convertHalResult(result);
    HidlUtils::convertProgramInfoFromHal(&event.info, &info);
    onCallback(&event);
    radio_metadata_deallocate(event.info.metadata);
    return Return<void>();
}

Return<void> RadioHalHidl::Tuner::afSwitch(const ProgramInfo& info)
{
    ALOGV("%s IN", __FUNCTION__);
    radio_hal_event_t event;
    memset(&event, 0, sizeof(radio_hal_event_t));
    event.type = RADIO_EVENT_AF_SWITCH;
    HidlUtils::convertProgramInfoFromHal(&event.info, &info);
    onCallback(&event);
    if (event.info.metadata != NULL) {
        radio_metadata_deallocate(event.info.metadata);
    }
    return Return<void>();
}

Return<void> RadioHalHidl::Tuner::antennaStateChange(bool connected)
{
    ALOGV("%s IN", __FUNCTION__);
    radio_hal_event_t event;
    memset(&event, 0, sizeof(radio_hal_event_t));
    event.type = RADIO_EVENT_ANTENNA;
    event.on = connected;
    onCallback(&event);
    return Return<void>();
}
Return<void> RadioHalHidl::Tuner::trafficAnnouncement(bool active)
{
    ALOGV("%s IN", __FUNCTION__);
    radio_hal_event_t event;
    memset(&event, 0, sizeof(radio_hal_event_t));
    event.type = RADIO_EVENT_TA;
    event.on = active;
    onCallback(&event);
    return Return<void>();
}
Return<void> RadioHalHidl::Tuner::emergencyAnnouncement(bool active)
{
    ALOGV("%s IN", __FUNCTION__);
    radio_hal_event_t event;
    memset(&event, 0, sizeof(radio_hal_event_t));
    event.type = RADIO_EVENT_EA;
    event.on = active;
    onCallback(&event);
    return Return<void>();
}
Return<void> RadioHalHidl::Tuner::newMetadata(uint32_t channel, uint32_t subChannel,
                                          const ::android::hardware::hidl_vec<MetaData>& metadata)
{
    ALOGV("%s IN", __FUNCTION__);
    radio_hal_event_t event;
    memset(&event, 0, sizeof(radio_hal_event_t));
    event.type = RADIO_EVENT_METADATA;
    HidlUtils::convertMetaDataFromHal(&event.metadata, metadata, channel, subChannel);
    onCallback(&event);
    if (event.metadata != NULL) {
        radio_metadata_deallocate(event.info.metadata);
    }
    return Return<void>();
}


RadioHalHidl::Tuner::Tuner(sp<TunerCallbackInterface> callback, sp<RadioHalHidl> module)
    : TunerInterface(), mHalTuner(NULL), mCallback(callback), mParentModule(module)
{
    // Make sure the handler we are passing in only deals with const members,
    // as it can be called on an arbitrary thread.
    const auto& self = this;
    HalDeathHandler::getInstance()->registerAtExitHandler(
            this, [&self]() { self->sendHwFailureEvent(); });
}


RadioHalHidl::Tuner::~Tuner()
{
    HalDeathHandler::getInstance()->unregisterAtExitHandler(this);
}

void RadioHalHidl::Tuner::setHalTuner(sp<ITuner>& halTuner) {
    if (mHalTuner != 0) {
        mHalTuner->unlinkToDeath(HalDeathHandler::getInstance());
    }
    mHalTuner = halTuner;
    if (mHalTuner != 0) {
        mHalTuner->linkToDeath(HalDeathHandler::getInstance(), 0 /*cookie*/);
    }
}

void RadioHalHidl::Tuner::handleHwFailure()
{
    ALOGV("%s IN", __FUNCTION__);
    sp<RadioHalHidl> parentModule = mParentModule.promote();
    if (parentModule != 0) {
        parentModule->clearService();
    }
    sendHwFailureEvent();
    mHalTuner.clear();
}

void RadioHalHidl::Tuner::sendHwFailureEvent() const
{
    radio_hal_event_t event;
    memset(&event, 0, sizeof(radio_hal_event_t));
    event.type = RADIO_EVENT_HW_FAILURE;
    onCallback(&event);
}

void RadioHalHidl::Tuner::onCallback(radio_hal_event_t *halEvent) const
{
    if (mCallback != 0) {
        mCallback->onEvent(halEvent);
    }
}

} // namespace android
