/*
 * Copyright (C) 2015 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 "RadioService"
//#define LOG_NDEBUG 0

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <pthread.h>

#include <system/audio.h>
#include <system/audio_policy.h>
#include <system/radio.h>
#include <system/radio_metadata.h>
#include <cutils/atomic.h>
#include <cutils/properties.h>
#include <hardware/hardware.h>
#include <utils/Errors.h>
#include <utils/Log.h>
#include <binder/IServiceManager.h>
#include <binder/MemoryBase.h>
#include <binder/MemoryHeapBase.h>
#include <hardware/radio.h>
#include <media/AudioSystem.h>
#include "RadioService.h"
#include "RadioRegions.h"

namespace android {

static const char kRadioTunerAudioDeviceName[] = "Radio tuner source";

RadioService::RadioService()
    : BnRadioService(), mNextUniqueId(1)
{
    ALOGI("%s", __FUNCTION__);
}

void RadioService::onFirstRef()
{
    ALOGI("%s", __FUNCTION__);

    sp<RadioInterface> dev = RadioInterface::connectModule(RADIO_CLASS_AM_FM);

    if (dev == 0) {
        return;
    }
    struct radio_hal_properties halProperties;
    int rc = dev->getProperties(&halProperties);
    if (rc != 0) {
        ALOGE("could not read implementation properties");
        return;
    }

    radio_properties_t properties;
    properties.handle =
            (radio_handle_t)android_atomic_inc(&mNextUniqueId);
    convertProperties(&properties, &halProperties);

    ALOGI("loaded default module %s, ver %s, handle %d", properties.product,
        properties.version, properties.handle);

    sp<Module> module = new Module(dev, properties);
    mModules.add(properties.handle, module);
}

RadioService::~RadioService()
{
}

status_t RadioService::listModules(struct radio_properties *properties,
                             uint32_t *numModules)
{
    ALOGV("listModules");

    AutoMutex lock(mServiceLock);
    if (numModules == NULL || (*numModules != 0 && properties == NULL)) {
        return BAD_VALUE;
    }
    uint32_t maxModules = *numModules;
    *numModules = mModules.size();
    for (size_t i = 0; i < mModules.size() && i < maxModules; i++) {
        properties[i] = mModules.valueAt(i)->properties();
    }
    return NO_ERROR;
}

status_t RadioService::attach(radio_handle_t handle,
                        const sp<IRadioClient>& client,
                        const struct radio_band_config *config,
                        bool withAudio,
                        sp<IRadio>& radio)
{
    ALOGV("%s %d config %p withAudio %d", __FUNCTION__, handle, config, withAudio);

    AutoMutex lock(mServiceLock);
    radio.clear();
    if (client == 0) {
        return BAD_VALUE;
    }
    ssize_t index = mModules.indexOfKey(handle);
    if (index < 0) {
        return BAD_VALUE;
    }
    sp<Module> module = mModules.valueAt(index);

    if (config == NULL) {
        config = module->getDefaultConfig();
        if (config == NULL) {
            return INVALID_OPERATION;
        }
    }
    ALOGV("%s region %d type %d", __FUNCTION__, config->region, config->band.type);

    radio = module->addClient(client, config, withAudio);

    if (radio == 0) {
        return NO_INIT;
    }
    return NO_ERROR;
}


static const int kDumpLockRetries = 50;
static const int kDumpLockSleep = 60000;

static bool tryLock(Mutex& mutex)
{
    bool locked = false;
    for (int i = 0; i < kDumpLockRetries; ++i) {
        if (mutex.tryLock() == NO_ERROR) {
            locked = true;
            break;
        }
        usleep(kDumpLockSleep);
    }
    return locked;
}

status_t RadioService::dump(int fd, const Vector<String16>& args __unused) {
    String8 result;
    if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
        result.appendFormat("Permission Denial: can't dump RadioService");
        write(fd, result.string(), result.size());
    } else {
        bool locked = tryLock(mServiceLock);
        // failed to lock - RadioService is probably deadlocked
        if (!locked) {
            result.append("RadioService may be deadlocked\n");
            write(fd, result.string(), result.size());
        }

        if (locked) mServiceLock.unlock();
    }
    return NO_ERROR;
}

status_t RadioService::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
    return BnRadioService::onTransact(code, data, reply, flags);
}


/* static */
void RadioService::convertProperties(radio_properties_t *properties,
                                     const radio_hal_properties_t *halProperties)
{
    memset(properties, 0, sizeof(struct radio_properties));
    properties->class_id = halProperties->class_id;
    strlcpy(properties->implementor, halProperties->implementor,
            RADIO_STRING_LEN_MAX);
    strlcpy(properties->product, halProperties->product,
            RADIO_STRING_LEN_MAX);
    strlcpy(properties->version, halProperties->version,
            RADIO_STRING_LEN_MAX);
    strlcpy(properties->serial, halProperties->serial,
            RADIO_STRING_LEN_MAX);
    properties->num_tuners = halProperties->num_tuners;
    properties->num_audio_sources = halProperties->num_audio_sources;
    properties->supports_capture = halProperties->supports_capture;

    for (size_t i = 0; i < ARRAY_SIZE(sKnownRegionConfigs); i++) {
        const radio_hal_band_config_t *band = &sKnownRegionConfigs[i].band;
        size_t j;
        for (j = 0; j < halProperties->num_bands; j++) {
            const radio_hal_band_config_t *halBand = &halProperties->bands[j];
            size_t k;
            if (band->type != halBand->type) continue;
            if (band->lower_limit < halBand->lower_limit) continue;
            if (band->upper_limit > halBand->upper_limit) continue;
            for (k = 0; k < halBand->num_spacings; k++) {
                if (band->spacings[0] == halBand->spacings[k]) break;
            }
            if (k == halBand->num_spacings) continue;
            if (band->type == RADIO_BAND_AM) break;
            if ((band->fm.deemphasis & halBand->fm.deemphasis) == 0) continue;
            if (halBand->fm.rds == 0) break;
            if ((band->fm.rds & halBand->fm.rds) != 0) break;
        }
        if (j == halProperties->num_bands) continue;

        ALOGI("convertProperties() Adding band type %d region %d",
              sKnownRegionConfigs[i].band.type , sKnownRegionConfigs[i].region);

        memcpy(&properties->bands[properties->num_bands++],
               &sKnownRegionConfigs[i],
               sizeof(radio_band_config_t));
    }
}

#undef LOG_TAG
#define LOG_TAG "RadioService::CallbackThread"

RadioService::CallbackThread::CallbackThread(const wp<ModuleClient>& moduleClient)
    : mModuleClient(moduleClient), mMemoryDealer(new MemoryDealer(1024 * 1024, "RadioService"))
{
}

RadioService::CallbackThread::~CallbackThread()
{
    mEventQueue.clear();
}

void RadioService::CallbackThread::onFirstRef()
{
    run("RadioService cbk", ANDROID_PRIORITY_URGENT_AUDIO);
}

bool RadioService::CallbackThread::threadLoop()
{
    while (!exitPending()) {
        sp<IMemory> eventMemory;
        sp<ModuleClient> moduleClient;
        {
            Mutex::Autolock _l(mCallbackLock);
            while (mEventQueue.isEmpty() && !exitPending()) {
                ALOGV("CallbackThread::threadLoop() sleep");
                mCallbackCond.wait(mCallbackLock);
                ALOGV("CallbackThread::threadLoop() wake up");
            }
            if (exitPending()) {
                break;
            }
            eventMemory = mEventQueue[0];
            mEventQueue.removeAt(0);
            moduleClient = mModuleClient.promote();
        }
        if (moduleClient != 0) {
            moduleClient->onCallbackEvent(eventMemory);
            eventMemory.clear();
        }
    }
    return false;
}

void RadioService::CallbackThread::exit()
{
    Mutex::Autolock _l(mCallbackLock);
    requestExit();
    mCallbackCond.broadcast();
}

sp<IMemory> RadioService::CallbackThread::prepareEvent(radio_hal_event_t *halEvent)
{
    sp<IMemory> eventMemory;

    // The event layout in shared memory is:
    // sizeof(struct radio_event) bytes : the event itself
    // 4 bytes                          : metadata size or 0
    // N bytes                          : metadata if present
    uint32_t metadataOffset = sizeof(struct radio_event) + sizeof(uint32_t);
    uint32_t metadataSize = 0;

    switch (halEvent->type) {
    case RADIO_EVENT_TUNED:
    case RADIO_EVENT_AF_SWITCH:
        if (radio_metadata_check(halEvent->info.metadata) == 0) {
            metadataSize = (uint32_t)radio_metadata_get_size(halEvent->info.metadata);
        }
        break;
    case RADIO_EVENT_METADATA:
        if (radio_metadata_check(halEvent->metadata) != 0) {
            return eventMemory;
        }
        metadataSize = (uint32_t)radio_metadata_get_size(halEvent->metadata);
        break;
    default:
        break;
    }

    eventMemory = mMemoryDealer->allocate(metadataOffset + metadataSize);
    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
        eventMemory.clear();
        return eventMemory;
    }

    struct radio_event *event = (struct radio_event *)eventMemory->pointer();

    *(uint32_t *)((uint8_t *)event + metadataOffset - sizeof(uint32_t)) = metadataSize;

    event->type = halEvent->type;
    event->status = halEvent->status;

    switch (event->type) {
    case RADIO_EVENT_CONFIG:
        event->config.band = halEvent->config;
        break;
    case RADIO_EVENT_TUNED:
    case RADIO_EVENT_AF_SWITCH:
        event->info = halEvent->info;
        if (metadataSize != 0) {
            memcpy((uint8_t *)event + metadataOffset, halEvent->info.metadata, metadataSize);
        }
        break;
    case RADIO_EVENT_TA:
    case RADIO_EVENT_EA:
    case RADIO_EVENT_ANTENNA:
    case RADIO_EVENT_CONTROL:
        event->on = halEvent->on;
        break;
    case RADIO_EVENT_METADATA:
        if (metadataSize != 0) {
            memcpy((uint8_t *)event + metadataOffset, halEvent->metadata, metadataSize);
        }
        break;
    case RADIO_EVENT_HW_FAILURE:
    default:
        break;
    }

    return eventMemory;
}

void RadioService::CallbackThread::sendEvent(radio_hal_event_t *event)
 {
     sp<IMemory> eventMemory = prepareEvent(event);
     if (eventMemory == 0) {
         return;
     }

     AutoMutex lock(mCallbackLock);
     mEventQueue.add(eventMemory);
     mCallbackCond.signal();
     ALOGV("%s DONE", __FUNCTION__);
}


#undef LOG_TAG
#define LOG_TAG "RadioService::Module"

RadioService::Module::Module(sp<RadioInterface> hwDevice, radio_properties properties)
 : mHwDevice(hwDevice), mProperties(properties), mMute(true)
{
}

RadioService::Module::~Module() {
    mHwDevice.clear();
    mModuleClients.clear();
}

status_t RadioService::Module::dump(int fd __unused, const Vector<String16>& args __unused) {
    String8 result;
    return NO_ERROR;
}

sp<RadioService::ModuleClient> RadioService::Module::addClient(const sp<IRadioClient>& client,
                                    const struct radio_band_config *config,
                                    bool audio)
{
    ALOGV("addClient() %p config %p product %s", this, config, mProperties.product);

    AutoMutex lock(mLock);
    sp<ModuleClient> moduleClient;
    int ret;

    if (mHwDevice == 0) {
        return moduleClient;
    }

    for (size_t i = 0; i < mModuleClients.size(); i++) {
        if (mModuleClients[i]->client() == client) {
            // client already connected: reject
            return moduleClient;
        }
    }
    moduleClient = new ModuleClient(this, client, config, audio);

    struct radio_hal_band_config halConfig;
    halConfig = config->band;

    // Tuner preemption logic:
    // There is a limited amount of tuners and a limited amount of radio audio sources per module.
    // The minimum is one tuner and one audio source.
    // The numbers of tuners and sources are indicated in the module properties.
    // NOTE: current framework implementation only supports one radio audio source.
    // It is possible to open more than one tuner at a time but only one tuner can be connected
    // to the radio audio source (AUDIO_DEVICE_IN_FM_TUNER).
    // The base rule is that a newly connected tuner always wins, i.e. always gets a tuner
    // and can use the audio source if requested.
    // If another client is preempted, it is notified by a callback with RADIO_EVENT_CONTROL
    // indicating loss of control.
    // - If the newly connected client requests the audio source (audio == true):
    //    - if an audio source is available
    //          no problem
    //    - if not:
    //          the oldest client in the list using audio is preempted.
    // - If the newly connected client does not request the audio source (audio == false):
    //    - if a tuner is available
    //          no problem
    //    - if not:
    //          The oldest client not using audio is preempted first and if none is found the
    //          the oldest client using audio is preempted.
    // Each time a tuner using the audio source is opened or closed, the audio policy manager is
    // notified of the connection or disconnection of AUDIO_DEVICE_IN_FM_TUNER.

    sp<ModuleClient> oldestTuner;
    sp<ModuleClient> oldestAudio;
    size_t allocatedTuners = 0;
    size_t allocatedAudio = 0;
    for (size_t i = 0; i < mModuleClients.size(); i++) {
        if (mModuleClients[i]->getTuner() != NULL) {
            if (mModuleClients[i]->audio()) {
                if (oldestAudio == 0) {
                    oldestAudio = mModuleClients[i];
                }
                allocatedAudio++;
            } else {
                if (oldestTuner == 0) {
                    oldestTuner = mModuleClients[i];
                }
                allocatedTuners++;
            }
        }
    }

    sp<TunerInterface> halTuner;
    sp<ModuleClient> preemtedClient;
    if (audio) {
        if (allocatedAudio >= mProperties.num_audio_sources) {
            ALOG_ASSERT(oldestAudio != 0, "addClient() allocatedAudio/oldestAudio mismatch");
            preemtedClient = oldestAudio;
        }
    } else {
        if (allocatedAudio + allocatedTuners >= mProperties.num_tuners) {
            if (allocatedTuners != 0) {
                ALOG_ASSERT(oldestTuner != 0, "addClient() allocatedTuners/oldestTuner mismatch");
                preemtedClient = oldestTuner;
            } else {
                ALOG_ASSERT(oldestAudio != 0, "addClient() allocatedAudio/oldestAudio mismatch");
                preemtedClient = oldestAudio;
            }
        }
    }
    if (preemtedClient != 0) {
        halTuner = preemtedClient->getTuner();
        sp<TunerInterface> clear;
        preemtedClient->setTuner(clear);
        mHwDevice->closeTuner(halTuner);
        if (preemtedClient->audio()) {
            notifyDeviceConnection(false, "");
        }
    }

    ret = mHwDevice->openTuner(&halConfig, audio,
                               moduleClient,
                               halTuner);
    if (ret == 0) {
        ALOGV("addClient() setTuner %p", halTuner.get());
        moduleClient->setTuner(halTuner);
        mModuleClients.add(moduleClient);
        if (audio) {
            notifyDeviceConnection(true, "");
        }
        ALOGV("addClient() DONE moduleClient %p", moduleClient.get());
    } else {
        ALOGW("%s open_tuner failed with error %d", __FUNCTION__, ret);
        moduleClient.clear();
    }

    return moduleClient;
}

void RadioService::Module::removeClient(const sp<ModuleClient>& moduleClient) {
    ALOGV("removeClient()");
    AutoMutex lock(mLock);
    int ret;
    ssize_t index = -1;

    for (size_t i = 0; i < mModuleClients.size(); i++) {
        if (mModuleClients[i] == moduleClient) {
            index = i;
            break;
        }
    }
    if (index == -1) {
        return;
    }

    mModuleClients.removeAt(index);
    sp<TunerInterface> halTuner = moduleClient->getTuner();
    if (halTuner == NULL) {
        return;
    }

    if (mHwDevice != 0) {
        mHwDevice->closeTuner(halTuner);
    }

    if (moduleClient->audio()) {
        notifyDeviceConnection(false, "");
    }

    mMute = true;

    if (mModuleClients.isEmpty()) {
        return;
    }

    if (mHwDevice == 0) {
        return;
    }

    // Tuner reallocation logic:
    // When a client is removed and was controlling a tuner, this tuner will be allocated to a
    // previously preempted client. This client will be notified by a callback with
    // RADIO_EVENT_CONTROL indicating gain of control.
    // - If a preempted client is waiting for an audio source and one becomes available:
    //    Allocate the tuner to the most recently added client waiting for an audio source
    // - If not:
    //    Allocate the tuner to the most recently added client.
    // Each time a tuner using the audio source is opened or closed, the audio policy manager is
    // notified of the connection or disconnection of AUDIO_DEVICE_IN_FM_TUNER.

    sp<ModuleClient> youngestClient;
    sp<ModuleClient> youngestClientAudio;
    size_t allocatedTuners = 0;
    size_t allocatedAudio = 0;
    for (ssize_t i = mModuleClients.size() - 1; i >= 0; i--) {
        if (mModuleClients[i]->getTuner() == NULL) {
            if (mModuleClients[i]->audio()) {
                if (youngestClientAudio == 0) {
                    youngestClientAudio = mModuleClients[i];
                }
            } else {
                if (youngestClient == 0) {
                    youngestClient = mModuleClients[i];
                }
            }
        } else {
            if (mModuleClients[i]->audio()) {
                allocatedAudio++;
            } else {
                allocatedTuners++;
            }
        }
    }

    ALOG_ASSERT(allocatedTuners + allocatedAudio < mProperties.num_tuners,
                "removeClient() removed client but no tuner available");

    ALOG_ASSERT(!moduleClient->audio() || allocatedAudio < mProperties.num_audio_sources,
                "removeClient() removed audio client but no tuner with audio available");

    if (allocatedAudio < mProperties.num_audio_sources && youngestClientAudio != 0) {
        youngestClient = youngestClientAudio;
    }

    ALOG_ASSERT(youngestClient != 0, "removeClient() removed client no candidate found for tuner");

    struct radio_hal_band_config halConfig = youngestClient->halConfig();
    ret = mHwDevice->openTuner(&halConfig, youngestClient->audio(),
                                moduleClient,
                                halTuner);

    if (ret == 0) {
        youngestClient->setTuner(halTuner);
        if (youngestClient->audio()) {
            notifyDeviceConnection(true, "");
        }
    }
}

status_t RadioService::Module::setMute(bool mute)
{
    Mutex::Autolock _l(mLock);
    if (mute != mMute) {
        mMute = mute;
        //TODO notifify audio policy manager of media activity on radio audio device
    }
    return NO_ERROR;
}

status_t RadioService::Module::getMute(bool *mute)
{
    Mutex::Autolock _l(mLock);
    *mute = mMute;
    return NO_ERROR;
}


const struct radio_band_config *RadioService::Module::getDefaultConfig() const
{
    if (mProperties.num_bands == 0) {
        return NULL;
    }
    return &mProperties.bands[0];
}

void RadioService::Module::notifyDeviceConnection(bool connected,
                                                  const char *address) {
    int64_t token = IPCThreadState::self()->clearCallingIdentity();
    AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_IN_FM_TUNER,
                                          connected ? AUDIO_POLICY_DEVICE_STATE_AVAILABLE :
                                                  AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
                                          address, kRadioTunerAudioDeviceName);
    IPCThreadState::self()->restoreCallingIdentity(token);
}

#undef LOG_TAG
#define LOG_TAG "RadioService::ModuleClient"

RadioService::ModuleClient::ModuleClient(const sp<Module>& module,
                                         const sp<IRadioClient>& client,
                                         const struct radio_band_config *config,
                                         bool audio)
 : mModule(module), mClient(client), mConfig(*config), mAudio(audio), mTuner(0)
{
}

void RadioService::ModuleClient::onFirstRef()
{
    mCallbackThread = new CallbackThread(this);
    IInterface::asBinder(mClient)->linkToDeath(this);
}

RadioService::ModuleClient::~ModuleClient() {
    if (mClient != 0) {
        IInterface::asBinder(mClient)->unlinkToDeath(this);
        mClient.clear();
    }
    if (mCallbackThread != 0) {
        mCallbackThread->exit();
    }
}

void RadioService::ModuleClient::onEvent(radio_hal_event_t *halEvent)
{
    mCallbackThread->sendEvent(halEvent);
}

status_t RadioService::ModuleClient::dump(int fd __unused,
                                             const Vector<String16>& args __unused) {
    String8 result;
    return NO_ERROR;
}

void RadioService::ModuleClient::detach() {
    ALOGV("%s", __FUNCTION__);
    sp<ModuleClient> strongMe = this;
    {
        AutoMutex lock(mLock);
        if (mClient != 0) {
            IInterface::asBinder(mClient)->unlinkToDeath(this);
            mClient.clear();
        }
    }
    sp<Module> module = mModule.promote();
    if (module == 0) {
        return;
    }
    module->removeClient(this);
}

radio_hal_band_config_t RadioService::ModuleClient::halConfig() const
{
    AutoMutex lock(mLock);
    ALOGV("%s locked", __FUNCTION__);
    return mConfig.band;
}

sp<TunerInterface>& RadioService::ModuleClient::getTuner()
{
    AutoMutex lock(mLock);
    ALOGV("%s locked", __FUNCTION__);
    return mTuner;
}

void RadioService::ModuleClient::setTuner(sp<TunerInterface>& tuner)
{
    ALOGV("%s %p", __FUNCTION__, this);

    AutoMutex lock(mLock);
    mTuner = tuner;
    ALOGV("%s locked", __FUNCTION__);

    radio_hal_event_t event;
    event.type = RADIO_EVENT_CONTROL;
    event.status = 0;
    event.on = mTuner != 0;
    mCallbackThread->sendEvent(&event);
    ALOGV("%s DONE", __FUNCTION__);

}

status_t RadioService::ModuleClient::setConfiguration(const struct radio_band_config *config)
{
    AutoMutex lock(mLock);
    status_t status = NO_ERROR;
    ALOGV("%s locked", __FUNCTION__);

    if (mTuner != 0) {
        struct radio_hal_band_config halConfig;
        halConfig = config->band;
        status = (status_t)mTuner->setConfiguration(&halConfig);
        if (status == NO_ERROR) {
            mConfig = *config;
        }
    } else {
        mConfig = *config;
        status = INVALID_OPERATION;
    }

    return status;
}

status_t RadioService::ModuleClient::getConfiguration(struct radio_band_config *config)
{
    AutoMutex lock(mLock);
    status_t status = NO_ERROR;
    ALOGV("%s locked", __FUNCTION__);

    if (mTuner != 0) {
        struct radio_hal_band_config halConfig;
        status = (status_t)mTuner->getConfiguration(&halConfig);
        if (status == NO_ERROR) {
            mConfig.band = halConfig;
        }
    }
    *config = mConfig;

    return status;
}

status_t RadioService::ModuleClient::setMute(bool mute)
{
    sp<Module> module;
    {
        Mutex::Autolock _l(mLock);
        ALOGV("%s locked", __FUNCTION__);
        if (mTuner == 0 || !mAudio) {
            return INVALID_OPERATION;
        }
        module = mModule.promote();
        if (module == 0) {
            return NO_INIT;
        }
    }
    module->setMute(mute);
    return NO_ERROR;
}

status_t RadioService::ModuleClient::getMute(bool *mute)
{
    sp<Module> module;
    {
        Mutex::Autolock _l(mLock);
        ALOGV("%s locked", __FUNCTION__);
        module = mModule.promote();
        if (module == 0) {
            return NO_INIT;
        }
    }
    return module->getMute(mute);
}

status_t RadioService::ModuleClient::scan(radio_direction_t direction, bool skipSubChannel)
{
    AutoMutex lock(mLock);
    ALOGV("%s locked", __FUNCTION__);
    status_t status;
    if (mTuner != 0) {
        status = (status_t)mTuner->scan(direction, skipSubChannel);
    } else {
        status = INVALID_OPERATION;
    }
    return status;
}

status_t RadioService::ModuleClient::step(radio_direction_t direction, bool skipSubChannel)
{
    AutoMutex lock(mLock);
    ALOGV("%s locked", __FUNCTION__);
    status_t status;
    if (mTuner != 0) {
        status = (status_t)mTuner->step(direction, skipSubChannel);
    } else {
        status = INVALID_OPERATION;
    }
    return status;
}

status_t RadioService::ModuleClient::tune(uint32_t channel, uint32_t subChannel)
{
    AutoMutex lock(mLock);
    ALOGV("%s locked", __FUNCTION__);
    status_t status;
    if (mTuner != 0) {
        status = (status_t)mTuner->tune(channel, subChannel);
    } else {
        status = INVALID_OPERATION;
    }
    return status;
}

status_t RadioService::ModuleClient::cancel()
{
    AutoMutex lock(mLock);
    ALOGV("%s locked", __FUNCTION__);
    status_t status;
    if (mTuner != 0) {
        status = (status_t)mTuner->cancel();
    } else {
        status = INVALID_OPERATION;
    }
    return status;
}

status_t RadioService::ModuleClient::getProgramInformation(struct radio_program_info *info)
{
    AutoMutex lock(mLock);
    ALOGV("%s locked", __FUNCTION__);
    status_t status;
    if (mTuner != NULL) {
        status = (status_t)mTuner->getProgramInformation(info);
    } else {
        status = INVALID_OPERATION;
    }

    return status;
}

status_t RadioService::ModuleClient::hasControl(bool *hasControl)
{
    Mutex::Autolock lock(mLock);
    ALOGV("%s locked", __FUNCTION__);
    *hasControl = mTuner != 0;
    return NO_ERROR;
}

void RadioService::ModuleClient::onCallbackEvent(const sp<IMemory>& eventMemory)
{
    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
        return;
    }

    sp<IRadioClient> client;
    {
        AutoMutex lock(mLock);
        ALOGV("%s locked", __FUNCTION__);
        radio_event_t *event = (radio_event_t *)eventMemory->pointer();
        switch (event->type) {
        case RADIO_EVENT_CONFIG:
            mConfig.band = event->config.band;
            event->config.region = mConfig.region;
            break;
        default:
            break;
        }

        client = mClient;
    }
    if (client != 0) {
        client->onEvent(eventMemory);
    }
}


void RadioService::ModuleClient::binderDied(
    const wp<IBinder> &who __unused) {
    ALOGW("client binder died for client %p", this);
    detach();
}

}; // namespace android
