Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 306162c7 authored by Eric Laurent's avatar Eric Laurent Committed by Android (Google) Code Review
Browse files

Merge "broadcast radio: add wrapper over HAL implementation"

parents b3153c29 01d267e3
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -18,7 +18,8 @@ include $(CLEAR_VARS)


LOCAL_SRC_FILES:=               \
    RadioService.cpp
    RadioService.cpp \
    RadioHalLegacy.cpp

LOCAL_SHARED_LIBRARIES:= \
    libui \
+218 −0
Original line number Diff line number Diff line
/*
 * 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 "RadioHalLegacy"
//#define LOG_NDEBUG 0

#include <utils/Log.h>
#include <utils/misc.h>
#include "RadioHalLegacy.h"

namespace android {

const char *RadioHalLegacy::sClassModuleNames[] = {
    RADIO_HARDWARE_MODULE_ID_FM, /* corresponds to RADIO_CLASS_AM_FM */
    RADIO_HARDWARE_MODULE_ID_SAT,  /* corresponds to RADIO_CLASS_SAT */
    RADIO_HARDWARE_MODULE_ID_DT,   /* corresponds to RADIO_CLASS_DT */
};

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

RadioHalLegacy::RadioHalLegacy(radio_class_t classId)
    : RadioInterface(), mClassId(classId), mHwDevice(NULL)
{
}

void RadioHalLegacy::onFirstRef()
{
    const hw_module_t *mod;
    int rc;
    ALOGI("%s mClassId %d", __FUNCTION__, mClassId);

    mHwDevice = NULL;

    if ((mClassId < 0) ||
            (mClassId >= NELEM(sClassModuleNames))) {
        ALOGE("invalid class ID %d", mClassId);
        return;
    }

    ALOGI("%s RADIO_HARDWARE_MODULE_ID %s %s",
          __FUNCTION__, RADIO_HARDWARE_MODULE_ID, sClassModuleNames[mClassId]);

    rc = hw_get_module_by_class(RADIO_HARDWARE_MODULE_ID, sClassModuleNames[mClassId], &mod);
    if (rc != 0) {
        ALOGE("couldn't load radio module %s.%s (%s)",
              RADIO_HARDWARE_MODULE_ID, sClassModuleNames[mClassId], strerror(-rc));
        return;
    }
    rc = radio_hw_device_open(mod, &mHwDevice);
    if (rc != 0) {
        ALOGE("couldn't open radio hw device in %s.%s (%s)",
              RADIO_HARDWARE_MODULE_ID, "primary", strerror(-rc));
        mHwDevice = NULL;
        return;
    }
    if (mHwDevice->common.version != RADIO_DEVICE_API_VERSION_CURRENT) {
        ALOGE("wrong radio hw device version %04x", mHwDevice->common.version);
        radio_hw_device_close(mHwDevice);
        mHwDevice = NULL;
    }
}

RadioHalLegacy::~RadioHalLegacy()
{
    if (mHwDevice != NULL) {
        radio_hw_device_close(mHwDevice);
    }
}

int RadioHalLegacy::getProperties(radio_hal_properties_t *properties)
{
    if (mHwDevice == NULL) {
        return -ENODEV;
    }

    int rc = mHwDevice->get_properties(mHwDevice, properties);
    if (rc != 0) {
        ALOGE("could not read implementation properties");
    }

    return rc;
}

int RadioHalLegacy::openTuner(const radio_hal_band_config_t *config,
                bool audio,
                sp<TunerCallbackInterface> callback,
                sp<TunerInterface>& tuner)
{
    if (mHwDevice == NULL) {
        return -ENODEV;
    }
    sp<Tuner> tunerImpl = new Tuner(callback);

    const struct radio_tuner *halTuner;
    int rc = mHwDevice->open_tuner(mHwDevice, config, audio,
                                   RadioHalLegacy::Tuner::callback, tunerImpl.get(),
                                   &halTuner);
    if (rc == 0) {
        tunerImpl->setHalTuner(halTuner);
        tuner = tunerImpl;
    }
    return rc;
}

int RadioHalLegacy::closeTuner(sp<TunerInterface>& tuner)
{
    if (mHwDevice == NULL) {
        return -ENODEV;
    }
    if (tuner == 0) {
        return -EINVAL;
    }
    sp<Tuner> tunerImpl = (Tuner *)tuner.get();
    return mHwDevice->close_tuner(mHwDevice, tunerImpl->getHalTuner());
}

int RadioHalLegacy::Tuner::setConfiguration(const radio_hal_band_config_t *config)
{
    if (mHalTuner == NULL) {
        return -ENODEV;
    }
    return mHalTuner->set_configuration(mHalTuner, config);
}

int RadioHalLegacy::Tuner::getConfiguration(radio_hal_band_config_t *config)
{
    if (mHalTuner == NULL) {
        return -ENODEV;
    }
    return mHalTuner->get_configuration(mHalTuner, config);
}

int RadioHalLegacy::Tuner::scan(radio_direction_t direction, bool skip_sub_channel)
{
    if (mHalTuner == NULL) {
        return -ENODEV;
    }
    return mHalTuner->scan(mHalTuner, direction, skip_sub_channel);
}

int RadioHalLegacy::Tuner::step(radio_direction_t direction, bool skip_sub_channel)
{
    if (mHalTuner == NULL) {
        return -ENODEV;
    }
    return mHalTuner->step(mHalTuner, direction, skip_sub_channel);
}

int RadioHalLegacy::Tuner::tune(unsigned int channel, unsigned int sub_channel)
{
    if (mHalTuner == NULL) {
        return -ENODEV;
    }
    return mHalTuner->tune(mHalTuner, channel, sub_channel);
}

int RadioHalLegacy::Tuner::cancel()
{
    if (mHalTuner == NULL) {
        return -ENODEV;
    }
    return mHalTuner->cancel(mHalTuner);
}

int RadioHalLegacy::Tuner::getProgramInformation(radio_program_info_t *info)
{
    if (mHalTuner == NULL) {
        return -ENODEV;
    }
    return mHalTuner->get_program_information(mHalTuner, info);
}

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

//static
void RadioHalLegacy::Tuner::callback(radio_hal_event_t *halEvent, void *cookie)
{
    wp<RadioHalLegacy::Tuner> weak = wp<RadioHalLegacy::Tuner>((RadioHalLegacy::Tuner *)cookie);
    sp<RadioHalLegacy::Tuner> tuner = weak.promote();
    if (tuner != 0) {
        tuner->onCallback(halEvent);
    }
}

RadioHalLegacy::Tuner::Tuner(sp<TunerCallbackInterface> callback)
    : TunerInterface(), mHalTuner(NULL), mCallback(callback)
{
}


RadioHalLegacy::Tuner::~Tuner()
{
}


} // namespace android
+82 −0
Original line number Diff line number Diff line
/*
 * 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.
 */

#ifndef ANDROID_HARDWARE_RADIO_HAL_LEGACY_H
#define ANDROID_HARDWARE_RADIO_HAL_LEGACY_H

#include <utils/RefBase.h>
#include <hardware/radio.h>
#include "RadioInterface.h"
#include "TunerInterface.h"
#include "TunerCallbackInterface.h"

namespace android {

class RadioHalLegacy : public RadioInterface
{
public:
        RadioHalLegacy(radio_class_t classId);

        // RadioInterface
        virtual int getProperties(radio_hal_properties_t *properties);
        virtual int openTuner(const radio_hal_band_config_t *config,
                        bool audio,
                        sp<TunerCallbackInterface> callback,
                        sp<TunerInterface>& tuner);
        virtual int closeTuner(sp<TunerInterface>& tuner);

        // RefBase
        virtual void onFirstRef();

        class Tuner  : public TunerInterface
        {
        public:
                        Tuner(sp<TunerCallbackInterface> callback);

            virtual int setConfiguration(const radio_hal_band_config_t *config);
            virtual int getConfiguration(radio_hal_band_config_t *config);
            virtual int scan(radio_direction_t direction, bool skip_sub_channel);
            virtual int step(radio_direction_t direction, bool skip_sub_channel);
            virtual int tune(unsigned int channel, unsigned int sub_channel);
            virtual int cancel();
            virtual int getProgramInformation(radio_program_info_t *info);

            static void callback(radio_hal_event_t *halEvent, void *cookie);
                   void onCallback(radio_hal_event_t *halEvent);

            void setHalTuner(const struct radio_tuner *halTuner) { mHalTuner = halTuner; }
            const struct radio_tuner *getHalTuner() { return mHalTuner; }

        private:
            virtual      ~Tuner();

            const struct radio_tuner    *mHalTuner;
            sp<TunerCallbackInterface>  mCallback;
        };

protected:
        virtual     ~RadioHalLegacy();

private:
        static const char * sClassModuleNames[];

        radio_class_t mClassId;
        struct radio_hw_device  *mHwDevice;
};

} // namespace android

#endif // ANDROID_HARDWARE_RADIO_HAL_LEGACY_H
+91 −0
Original line number Diff line number Diff line
/*
 * 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.
 */

#ifndef ANDROID_HARDWARE_RADIO_INTERFACE_H
#define ANDROID_HARDWARE_RADIO_INTERFACE_H

#include <utils/RefBase.h>
#include <system/radio.h>
#include "TunerInterface.h"
#include "TunerCallbackInterface.h"

namespace android {

class RadioInterface : public virtual RefBase
{
public:
        /* get a sound trigger HAL instance */
        static sp<RadioInterface> connectModule(radio_class_t classId);

        /*
         * Retrieve implementation properties.
         *
         * arguments:
         * - properties: where to return the module properties
         *
         * returns:
         *  0 if no error
         *  -EINVAL if invalid arguments are passed
         */
        virtual int getProperties(radio_hal_properties_t *properties) = 0;

        /*
         * Open a tuner interface for the requested configuration.
         * If no other tuner is opened, this will activate the radio module.
         *
         * arguments:
         * - config: the band configuration to apply
         * - audio: this tuner will be used for live radio listening and should be connected to
         * the radio audio source.
         * - callback: the event callback
         * - cookie: the cookie to pass when calling the callback
         * - tuner: where to return the tuner interface
         *
         * returns:
         *  0 if HW was powered up and configuration could be applied
         *  -EINVAL if configuration requested is invalid
         *  -ENOSYS if called out of sequence
         *
         * Callback function with event RADIO_EVENT_CONFIG MUST be called once the
         * configuration is applied or a failure occurs or after a time out.
         */
        virtual int openTuner(const radio_hal_band_config_t *config,
                        bool audio,
                        sp<TunerCallbackInterface> callback,
                        sp<TunerInterface>& tuner) = 0;

        /*
         * Close a tuner interface.
         * If the last tuner is closed, the radio module is deactivated.
         *
         * arguments:
         * - tuner: the tuner interface to close
         *
         * returns:
         *  0 if powered down successfully.
         *  -EINVAL if an invalid argument is passed
         *  -ENOSYS if called out of sequence
         */
        virtual int closeTuner(sp<TunerInterface>& tuner) = 0;

protected:
        RadioInterface() {}
        virtual     ~RadioInterface() {}
};

} // namespace android

#endif // ANDROID_HARDWARE_RADIO_INTERFACE_H
+57 −67
Original line number Diff line number Diff line
@@ -51,31 +51,15 @@ RadioService::RadioService()

void RadioService::onFirstRef()
{
    const hw_module_t *mod;
    int rc;
    struct radio_hw_device *dev;

    ALOGI("%s", __FUNCTION__);

    rc = hw_get_module_by_class(RADIO_HARDWARE_MODULE_ID, RADIO_HARDWARE_MODULE_ID_FM, &mod);
    if (rc != 0) {
        ALOGE("couldn't load radio module %s.%s (%s)",
              RADIO_HARDWARE_MODULE_ID, "primary", strerror(-rc));
        return;
    }
    rc = radio_hw_device_open(mod, &dev);
    if (rc != 0) {
        ALOGE("couldn't open radio hw device in %s.%s (%s)",
              RADIO_HARDWARE_MODULE_ID, "primary", strerror(-rc));
        return;
    }
    if (dev->common.version != RADIO_DEVICE_API_VERSION_CURRENT) {
        ALOGE("wrong radio hw device version %04x", dev->common.version);
    sp<RadioInterface> dev = RadioInterface::connectModule(RADIO_CLASS_AM_FM);

    if (dev == 0) {
        return;
    }

    struct radio_hal_properties halProperties;
    rc = dev->get_properties(dev, &halProperties);
    int rc = dev->getProperties(&halProperties);
    if (rc != 0) {
        ALOGE("could not read implementation properties");
        return;
@@ -94,9 +78,6 @@ void RadioService::onFirstRef()

RadioService::~RadioService()
{
    for (size_t i = 0; i < mModules.size(); i++) {
        radio_hw_device_close(mModules.valueAt(i)->hwDevice());
    }
}

status_t RadioService::listModules(struct radio_properties *properties,
@@ -108,7 +89,7 @@ status_t RadioService::listModules(struct radio_properties *properties,
    if (numModules == NULL || (*numModules != 0 && properties == NULL)) {
        return BAD_VALUE;
    }
    size_t maxModules = *numModules;
    uint32_t maxModules = *numModules;
    *numModules = mModules.size();
    for (size_t i = 0; i < mModules.size() && i < maxModules; i++) {
        properties[i] = mModules.valueAt(i)->properties();
@@ -192,16 +173,6 @@ status_t RadioService::onTransact(
}


// static
void RadioService::callback(radio_hal_event_t *halEvent, void *cookie)
{
    CallbackThread *callbackThread = (CallbackThread *)cookie;
    if (callbackThread == NULL) {
        return;
    }
    callbackThread->sendEvent(halEvent);
}

/* static */
void RadioService::convertProperties(radio_properties_t *properties,
                                     const radio_hal_properties_t *halProperties)
@@ -389,12 +360,13 @@ void RadioService::CallbackThread::sendEvent(radio_hal_event_t *event)
#undef LOG_TAG
#define LOG_TAG "RadioService::Module"

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

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

@@ -408,10 +380,15 @@ sp<RadioService::ModuleClient> RadioService::Module::addClient(const sp<IRadioCl
                                    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
@@ -468,7 +445,7 @@ sp<RadioService::ModuleClient> RadioService::Module::addClient(const sp<IRadioCl
        }
    }

    const struct radio_tuner *halTuner;
    sp<TunerInterface> halTuner;
    sp<ModuleClient> preemtedClient;
    if (audio) {
        if (allocatedAudio >= mProperties.num_audio_sources) {
@@ -488,18 +465,19 @@ sp<RadioService::ModuleClient> RadioService::Module::addClient(const sp<IRadioCl
    }
    if (preemtedClient != 0) {
        halTuner = preemtedClient->getTuner();
        preemtedClient->setTuner(NULL);
        mHwDevice->close_tuner(mHwDevice, halTuner);
        sp<TunerInterface> clear;
        preemtedClient->setTuner(clear);
        mHwDevice->closeTuner(halTuner);
        if (preemtedClient->audio()) {
            notifyDeviceConnection(false, "");
        }
    }

    ret = mHwDevice->open_tuner(mHwDevice, &halConfig, audio,
                                RadioService::callback, moduleClient->callbackThread().get(),
                                &halTuner);
    ret = mHwDevice->openTuner(&halConfig, audio,
                               moduleClient,
                               halTuner);
    if (ret == 0) {
        ALOGV("addClient() setTuner %p", halTuner);
        ALOGV("addClient() setTuner %p", halTuner.get());
        moduleClient->setTuner(halTuner);
        mModuleClients.add(moduleClient);
        if (audio) {
@@ -531,12 +509,15 @@ void RadioService::Module::removeClient(const sp<ModuleClient>& moduleClient) {
    }

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

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

    if (moduleClient->audio()) {
        notifyDeviceConnection(false, "");
    }
@@ -547,6 +528,10 @@ void RadioService::Module::removeClient(const sp<ModuleClient>& moduleClient) {
        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
@@ -595,9 +580,9 @@ void RadioService::Module::removeClient(const sp<ModuleClient>& moduleClient) {
    ALOG_ASSERT(youngestClient != 0, "removeClient() removed client no candidate found for tuner");

    struct radio_hal_band_config halConfig = youngestClient->halConfig();
    ret = mHwDevice->open_tuner(mHwDevice, &halConfig, youngestClient->audio(),
                                RadioService::callback, moduleClient->callbackThread().get(),
                                &halTuner);
    ret = mHwDevice->openTuner(&halConfig, youngestClient->audio(),
                                moduleClient,
                                halTuner);

    if (ret == 0) {
        youngestClient->setTuner(halTuner);
@@ -650,7 +635,7 @@ 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(NULL)
 : mModule(module), mClient(client), mConfig(*config), mAudio(audio), mTuner(0)
{
}

@@ -670,6 +655,11 @@ RadioService::ModuleClient::~ModuleClient() {
    }
}

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;
@@ -700,14 +690,14 @@ radio_hal_band_config_t RadioService::ModuleClient::halConfig() const
    return mConfig.band;
}

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

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

@@ -718,7 +708,7 @@ void RadioService::ModuleClient::setTuner(const struct radio_tuner *tuner)
    radio_hal_event_t event;
    event.type = RADIO_EVENT_CONTROL;
    event.status = 0;
    event.on = mTuner != NULL;
    event.on = mTuner != 0;
    mCallbackThread->sendEvent(&event);
    ALOGV("%s DONE", __FUNCTION__);

@@ -730,10 +720,10 @@ status_t RadioService::ModuleClient::setConfiguration(const struct radio_band_co
    status_t status = NO_ERROR;
    ALOGV("%s locked", __FUNCTION__);

    if (mTuner != NULL) {
    if (mTuner != 0) {
        struct radio_hal_band_config halConfig;
        halConfig = config->band;
        status = (status_t)mTuner->set_configuration(mTuner, &halConfig);
        status = (status_t)mTuner->setConfiguration(&halConfig);
        if (status == NO_ERROR) {
            mConfig = *config;
        }
@@ -751,9 +741,9 @@ status_t RadioService::ModuleClient::getConfiguration(struct radio_band_config *
    status_t status = NO_ERROR;
    ALOGV("%s locked", __FUNCTION__);

    if (mTuner != NULL) {
    if (mTuner != 0) {
        struct radio_hal_band_config halConfig;
        status = (status_t)mTuner->get_configuration(mTuner, &halConfig);
        status = (status_t)mTuner->getConfiguration(&halConfig);
        if (status == NO_ERROR) {
            mConfig.band = halConfig;
        }
@@ -769,7 +759,7 @@ status_t RadioService::ModuleClient::setMute(bool mute)
    {
        Mutex::Autolock _l(mLock);
        ALOGV("%s locked", __FUNCTION__);
        if (mTuner == NULL || !mAudio) {
        if (mTuner == 0 || !mAudio) {
            return INVALID_OPERATION;
        }
        module = mModule.promote();
@@ -800,8 +790,8 @@ status_t RadioService::ModuleClient::scan(radio_direction_t direction, bool skip
    AutoMutex lock(mLock);
    ALOGV("%s locked", __FUNCTION__);
    status_t status;
    if (mTuner != NULL) {
        status = (status_t)mTuner->scan(mTuner, direction, skipSubChannel);
    if (mTuner != 0) {
        status = (status_t)mTuner->scan(direction, skipSubChannel);
    } else {
        status = INVALID_OPERATION;
    }
@@ -813,21 +803,21 @@ status_t RadioService::ModuleClient::step(radio_direction_t direction, bool skip
    AutoMutex lock(mLock);
    ALOGV("%s locked", __FUNCTION__);
    status_t status;
    if (mTuner != NULL) {
        status = (status_t)mTuner->step(mTuner, direction, skipSubChannel);
    if (mTuner != 0) {
        status = (status_t)mTuner->step(direction, skipSubChannel);
    } else {
        status = INVALID_OPERATION;
    }
    return status;
}

status_t RadioService::ModuleClient::tune(unsigned int channel, unsigned int subChannel)
status_t RadioService::ModuleClient::tune(uint32_t channel, uint32_t subChannel)
{
    AutoMutex lock(mLock);
    ALOGV("%s locked", __FUNCTION__);
    status_t status;
    if (mTuner != NULL) {
        status = (status_t)mTuner->tune(mTuner, channel, subChannel);
    if (mTuner != 0) {
        status = (status_t)mTuner->tune(channel, subChannel);
    } else {
        status = INVALID_OPERATION;
    }
@@ -839,8 +829,8 @@ status_t RadioService::ModuleClient::cancel()
    AutoMutex lock(mLock);
    ALOGV("%s locked", __FUNCTION__);
    status_t status;
    if (mTuner != NULL) {
        status = (status_t)mTuner->cancel(mTuner);
    if (mTuner != 0) {
        status = (status_t)mTuner->cancel();
    } else {
        status = INVALID_OPERATION;
    }
@@ -853,7 +843,7 @@ status_t RadioService::ModuleClient::getProgramInformation(struct radio_program_
    ALOGV("%s locked", __FUNCTION__);
    status_t status;
    if (mTuner != NULL) {
        status = (status_t)mTuner->get_program_information(mTuner, info);
        status = (status_t)mTuner->getProgramInformation(info);
    } else {
        status = INVALID_OPERATION;
    }
@@ -865,7 +855,7 @@ status_t RadioService::ModuleClient::hasControl(bool *hasControl)
{
    Mutex::Autolock lock(mLock);
    ALOGV("%s locked", __FUNCTION__);
    *hasControl = mTuner != NULL;
    *hasControl = mTuner != 0;
    return NO_ERROR;
}

Loading