14e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent/*
24e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent * Copyright (C) 2015 The Android Open Source Project
34e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent *
44e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent * Licensed under the Apache License, Version 2.0 (the "License");
54e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent * you may not use this file except in compliance with the License.
64e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent * You may obtain a copy of the License at
74e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent *
84e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent *      http://www.apache.org/licenses/LICENSE-2.0
94e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent *
104e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent * Unless required by applicable law or agreed to in writing, software
114e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent * distributed under the License is distributed on an "AS IS" BASIS,
124e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent * See the License for the specific language governing permissions and
144e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent * limitations under the License.
154e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent */
164e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
174e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent#define LOG_TAG "RadioService"
184e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent//#define LOG_NDEBUG 0
194e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
204e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent#include <stdio.h>
214e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent#include <string.h>
224e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent#include <sys/types.h>
234e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent#include <pthread.h>
244e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
2553810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent#include <system/audio.h>
2653810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent#include <system/audio_policy.h>
274e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent#include <system/radio.h>
284e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent#include <system/radio_metadata.h>
294e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent#include <cutils/atomic.h>
304e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent#include <cutils/properties.h>
314e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent#include <hardware/hardware.h>
324e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent#include <utils/Errors.h>
334e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent#include <utils/Log.h>
344e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent#include <binder/IServiceManager.h>
354e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent#include <binder/MemoryBase.h>
364e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent#include <binder/MemoryHeapBase.h>
370e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Park#include <binder/PermissionCache.h>
384e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent#include <hardware/radio.h>
3953810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent#include <media/AudioSystem.h>
404e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent#include "RadioService.h"
414e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent#include "RadioRegions.h"
424e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
434e09069a29fc18d0799808cc26f71e9b068e98adEric Laurentnamespace android {
444e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
4553810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurentstatic const char kRadioTunerAudioDeviceName[] = "Radio tuner source";
464e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
470e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Parkstatic const String16 RADIO_PERMISSION("android.permission.ACCESS_FM_RADIO");
480e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Park
494e09069a29fc18d0799808cc26f71e9b068e98adEric LaurentRadioService::RadioService()
504e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    : BnRadioService(), mNextUniqueId(1)
514e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent{
524e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    ALOGI("%s", __FUNCTION__);
534e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
544e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
554e09069a29fc18d0799808cc26f71e9b068e98adEric Laurentvoid RadioService::onFirstRef()
564e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent{
574e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    ALOGI("%s", __FUNCTION__);
584e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
5901d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent    sp<RadioInterface> dev = RadioInterface::connectModule(RADIO_CLASS_AM_FM);
6001d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent
6101d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent    if (dev == 0) {
624e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        return;
634e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
644e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    struct radio_hal_properties halProperties;
6501d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent    int rc = dev->getProperties(&halProperties);
664e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    if (rc != 0) {
674e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        ALOGE("could not read implementation properties");
684e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        return;
694e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
704e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
714e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    radio_properties_t properties;
724e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    properties.handle =
734e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            (radio_handle_t)android_atomic_inc(&mNextUniqueId);
74164f36815fe5ff8bb3d0f0da013eca8a6408eab2Tomasz Wasilczyk    convertProperties(&properties, &halProperties);
754e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
76164f36815fe5ff8bb3d0f0da013eca8a6408eab2Tomasz Wasilczyk    ALOGI("loaded default module %s, ver %s, handle %d", properties.product,
77164f36815fe5ff8bb3d0f0da013eca8a6408eab2Tomasz Wasilczyk        properties.version, properties.handle);
784e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
7953810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    sp<Module> module = new Module(dev, properties);
804e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    mModules.add(properties.handle, module);
814e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
824e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
834e09069a29fc18d0799808cc26f71e9b068e98adEric LaurentRadioService::~RadioService()
844e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent{
854e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
864e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
874e09069a29fc18d0799808cc26f71e9b068e98adEric Laurentstatus_t RadioService::listModules(struct radio_properties *properties,
884e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent                             uint32_t *numModules)
894e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent{
900e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Park    if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
910e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Park        return PERMISSION_DENIED;
920e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Park    }
934e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    ALOGV("listModules");
944e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
954e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    AutoMutex lock(mServiceLock);
964e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    if (numModules == NULL || (*numModules != 0 && properties == NULL)) {
974e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        return BAD_VALUE;
984e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
9901d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent    uint32_t maxModules = *numModules;
1004e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    *numModules = mModules.size();
1014e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    for (size_t i = 0; i < mModules.size() && i < maxModules; i++) {
1024e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        properties[i] = mModules.valueAt(i)->properties();
1034e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
1044e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    return NO_ERROR;
1054e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
1064e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
1074e09069a29fc18d0799808cc26f71e9b068e98adEric Laurentstatus_t RadioService::attach(radio_handle_t handle,
1084e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent                        const sp<IRadioClient>& client,
1094e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent                        const struct radio_band_config *config,
1104e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent                        bool withAudio,
1114e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent                        sp<IRadio>& radio)
1124e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent{
1130e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Park    if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
1140e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Park        return PERMISSION_DENIED;
1150e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Park    }
1164e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    ALOGV("%s %d config %p withAudio %d", __FUNCTION__, handle, config, withAudio);
1174e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
1184e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    AutoMutex lock(mServiceLock);
1194e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    radio.clear();
1204e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    if (client == 0) {
1214e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        return BAD_VALUE;
1224e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
1234e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    ssize_t index = mModules.indexOfKey(handle);
1244e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    if (index < 0) {
1254e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        return BAD_VALUE;
1264e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
1274e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    sp<Module> module = mModules.valueAt(index);
1284e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
1294e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    if (config == NULL) {
1304e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        config = module->getDefaultConfig();
1314e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        if (config == NULL) {
1324e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            return INVALID_OPERATION;
1334e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        }
1344e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
1354e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    ALOGV("%s region %d type %d", __FUNCTION__, config->region, config->band.type);
1364e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
1374e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    radio = module->addClient(client, config, withAudio);
1384e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
1394e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    if (radio == 0) {
140f2f79cfcdec89052f49b74f9aab48e58daf606c6Eric Laurent        return NO_INIT;
1414e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
1424e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    return NO_ERROR;
1434e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
1444e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
1454e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
1464e09069a29fc18d0799808cc26f71e9b068e98adEric Laurentstatic const int kDumpLockRetries = 50;
1474e09069a29fc18d0799808cc26f71e9b068e98adEric Laurentstatic const int kDumpLockSleep = 60000;
1484e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
1494e09069a29fc18d0799808cc26f71e9b068e98adEric Laurentstatic bool tryLock(Mutex& mutex)
1504e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent{
1514e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    bool locked = false;
1524e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    for (int i = 0; i < kDumpLockRetries; ++i) {
1534e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        if (mutex.tryLock() == NO_ERROR) {
1544e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            locked = true;
1554e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            break;
1564e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        }
1574e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        usleep(kDumpLockSleep);
1584e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
1594e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    return locked;
1604e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
1614e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
1624e09069a29fc18d0799808cc26f71e9b068e98adEric Laurentstatus_t RadioService::dump(int fd, const Vector<String16>& args __unused) {
1634e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    String8 result;
1644e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
1654e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        result.appendFormat("Permission Denial: can't dump RadioService");
1664e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        write(fd, result.string(), result.size());
1674e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    } else {
1684e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        bool locked = tryLock(mServiceLock);
1694e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        // failed to lock - RadioService is probably deadlocked
1704e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        if (!locked) {
1714e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            result.append("RadioService may be deadlocked\n");
1724e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            write(fd, result.string(), result.size());
1734e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        }
1744e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
1754e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        if (locked) mServiceLock.unlock();
1764e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
1774e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    return NO_ERROR;
1784e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
1794e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
1804e09069a29fc18d0799808cc26f71e9b068e98adEric Laurentstatus_t RadioService::onTransact(
1814e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
1824e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    return BnRadioService::onTransact(code, data, reply, flags);
1834e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
1844e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
1854e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
1864e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent/* static */
1874e09069a29fc18d0799808cc26f71e9b068e98adEric Laurentvoid RadioService::convertProperties(radio_properties_t *properties,
1884e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent                                     const radio_hal_properties_t *halProperties)
1894e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent{
1904e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    memset(properties, 0, sizeof(struct radio_properties));
1914e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    properties->class_id = halProperties->class_id;
1924e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    strlcpy(properties->implementor, halProperties->implementor,
1934e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            RADIO_STRING_LEN_MAX);
1944e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    strlcpy(properties->product, halProperties->product,
1954e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            RADIO_STRING_LEN_MAX);
1964e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    strlcpy(properties->version, halProperties->version,
1974e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            RADIO_STRING_LEN_MAX);
1984e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    strlcpy(properties->serial, halProperties->serial,
1994e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            RADIO_STRING_LEN_MAX);
2004e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    properties->num_tuners = halProperties->num_tuners;
2014e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    properties->num_audio_sources = halProperties->num_audio_sources;
2024e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    properties->supports_capture = halProperties->supports_capture;
2034e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
2044e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    for (size_t i = 0; i < ARRAY_SIZE(sKnownRegionConfigs); i++) {
2054e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        const radio_hal_band_config_t *band = &sKnownRegionConfigs[i].band;
2064e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        size_t j;
2074e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        for (j = 0; j < halProperties->num_bands; j++) {
2084e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            const radio_hal_band_config_t *halBand = &halProperties->bands[j];
2094e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            size_t k;
2104e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            if (band->type != halBand->type) continue;
2114e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            if (band->lower_limit < halBand->lower_limit) continue;
2124e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            if (band->upper_limit > halBand->upper_limit) continue;
2134e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            for (k = 0; k < halBand->num_spacings; k++) {
2144e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent                if (band->spacings[0] == halBand->spacings[k]) break;
2154e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            }
2164e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            if (k == halBand->num_spacings) continue;
2174e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            if (band->type == RADIO_BAND_AM) break;
2184e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            if ((band->fm.deemphasis & halBand->fm.deemphasis) == 0) continue;
2194e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            if (halBand->fm.rds == 0) break;
2204e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            if ((band->fm.rds & halBand->fm.rds) != 0) break;
2214e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        }
2224e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        if (j == halProperties->num_bands) continue;
2234e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
2244e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        ALOGI("convertProperties() Adding band type %d region %d",
2254e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent              sKnownRegionConfigs[i].band.type , sKnownRegionConfigs[i].region);
2264e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
2274e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        memcpy(&properties->bands[properties->num_bands++],
2284e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent               &sKnownRegionConfigs[i],
2294e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent               sizeof(radio_band_config_t));
2304e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
2314e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
2324e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
2334e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent#undef LOG_TAG
2344e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent#define LOG_TAG "RadioService::CallbackThread"
2354e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
2364e09069a29fc18d0799808cc26f71e9b068e98adEric LaurentRadioService::CallbackThread::CallbackThread(const wp<ModuleClient>& moduleClient)
2374e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    : mModuleClient(moduleClient), mMemoryDealer(new MemoryDealer(1024 * 1024, "RadioService"))
2384e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent{
2394e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
2404e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
2414e09069a29fc18d0799808cc26f71e9b068e98adEric LaurentRadioService::CallbackThread::~CallbackThread()
2424e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent{
2434e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    mEventQueue.clear();
2444e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
2454e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
2464e09069a29fc18d0799808cc26f71e9b068e98adEric Laurentvoid RadioService::CallbackThread::onFirstRef()
2474e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent{
2484e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    run("RadioService cbk", ANDROID_PRIORITY_URGENT_AUDIO);
2494e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
2504e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
2514e09069a29fc18d0799808cc26f71e9b068e98adEric Laurentbool RadioService::CallbackThread::threadLoop()
2524e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent{
2534e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    while (!exitPending()) {
2544e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        sp<IMemory> eventMemory;
2554e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        sp<ModuleClient> moduleClient;
2564e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        {
2574e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            Mutex::Autolock _l(mCallbackLock);
2584e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            while (mEventQueue.isEmpty() && !exitPending()) {
2594e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent                ALOGV("CallbackThread::threadLoop() sleep");
2604e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent                mCallbackCond.wait(mCallbackLock);
2614e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent                ALOGV("CallbackThread::threadLoop() wake up");
2624e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            }
2634e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            if (exitPending()) {
2644e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent                break;
2654e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            }
2664e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            eventMemory = mEventQueue[0];
2674e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            mEventQueue.removeAt(0);
2684e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            moduleClient = mModuleClient.promote();
2694e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        }
2704e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        if (moduleClient != 0) {
2714e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            moduleClient->onCallbackEvent(eventMemory);
2724e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            eventMemory.clear();
2734e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        }
2744e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
2754e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    return false;
2764e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
2774e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
2784e09069a29fc18d0799808cc26f71e9b068e98adEric Laurentvoid RadioService::CallbackThread::exit()
2794e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent{
2804e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    Mutex::Autolock _l(mCallbackLock);
2814e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    requestExit();
2824e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    mCallbackCond.broadcast();
2834e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
2844e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
2854e09069a29fc18d0799808cc26f71e9b068e98adEric Laurentsp<IMemory> RadioService::CallbackThread::prepareEvent(radio_hal_event_t *halEvent)
2864e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent{
2874e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    sp<IMemory> eventMemory;
2884e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
289aebf5fbc6978ba6791690696e22a277be7eefa9bEric Laurent    // The event layout in shared memory is:
290aebf5fbc6978ba6791690696e22a277be7eefa9bEric Laurent    // sizeof(struct radio_event) bytes : the event itself
291aebf5fbc6978ba6791690696e22a277be7eefa9bEric Laurent    // 4 bytes                          : metadata size or 0
292aebf5fbc6978ba6791690696e22a277be7eefa9bEric Laurent    // N bytes                          : metadata if present
293aebf5fbc6978ba6791690696e22a277be7eefa9bEric Laurent    uint32_t metadataOffset = sizeof(struct radio_event) + sizeof(uint32_t);
294aebf5fbc6978ba6791690696e22a277be7eefa9bEric Laurent    uint32_t metadataSize = 0;
295aebf5fbc6978ba6791690696e22a277be7eefa9bEric Laurent
2964e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    switch (halEvent->type) {
2974e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    case RADIO_EVENT_TUNED:
2984e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    case RADIO_EVENT_AF_SWITCH:
2994e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        if (radio_metadata_check(halEvent->info.metadata) == 0) {
300aebf5fbc6978ba6791690696e22a277be7eefa9bEric Laurent            metadataSize = (uint32_t)radio_metadata_get_size(halEvent->info.metadata);
3014e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        }
3024e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        break;
3034e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    case RADIO_EVENT_METADATA:
3044e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        if (radio_metadata_check(halEvent->metadata) != 0) {
3054e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            return eventMemory;
3064e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        }
307aebf5fbc6978ba6791690696e22a277be7eefa9bEric Laurent        metadataSize = (uint32_t)radio_metadata_get_size(halEvent->metadata);
3084e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        break;
3094e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    default:
3104e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        break;
3114e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
312aebf5fbc6978ba6791690696e22a277be7eefa9bEric Laurent
313aebf5fbc6978ba6791690696e22a277be7eefa9bEric Laurent    eventMemory = mMemoryDealer->allocate(metadataOffset + metadataSize);
3144e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
3154e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        eventMemory.clear();
3164e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        return eventMemory;
3174e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
318aebf5fbc6978ba6791690696e22a277be7eefa9bEric Laurent
3194e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    struct radio_event *event = (struct radio_event *)eventMemory->pointer();
320aebf5fbc6978ba6791690696e22a277be7eefa9bEric Laurent
321aebf5fbc6978ba6791690696e22a277be7eefa9bEric Laurent    *(uint32_t *)((uint8_t *)event + metadataOffset - sizeof(uint32_t)) = metadataSize;
322aebf5fbc6978ba6791690696e22a277be7eefa9bEric Laurent
3234e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    event->type = halEvent->type;
3244e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    event->status = halEvent->status;
3254e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
3264e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    switch (event->type) {
3274e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    case RADIO_EVENT_CONFIG:
3284e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        event->config.band = halEvent->config;
3294e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        break;
3304e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    case RADIO_EVENT_TUNED:
3314e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    case RADIO_EVENT_AF_SWITCH:
3324e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        event->info = halEvent->info;
3334e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        if (metadataSize != 0) {
334aebf5fbc6978ba6791690696e22a277be7eefa9bEric Laurent            memcpy((uint8_t *)event + metadataOffset, halEvent->info.metadata, metadataSize);
3354e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        }
3364e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        break;
3374e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    case RADIO_EVENT_TA:
338f639ba1fdd4fd51d7ab97d2d8891a510615645f3Sanket Agarwal    case RADIO_EVENT_EA:
3394e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    case RADIO_EVENT_ANTENNA:
3404e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    case RADIO_EVENT_CONTROL:
3414e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        event->on = halEvent->on;
3424e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        break;
3434e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    case RADIO_EVENT_METADATA:
344aebf5fbc6978ba6791690696e22a277be7eefa9bEric Laurent        if (metadataSize != 0) {
345aebf5fbc6978ba6791690696e22a277be7eefa9bEric Laurent            memcpy((uint8_t *)event + metadataOffset, halEvent->metadata, metadataSize);
346aebf5fbc6978ba6791690696e22a277be7eefa9bEric Laurent        }
3474e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        break;
3484e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    case RADIO_EVENT_HW_FAILURE:
3494e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    default:
3504e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        break;
3514e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
3524e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
3534e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    return eventMemory;
3544e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
3554e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
3564e09069a29fc18d0799808cc26f71e9b068e98adEric Laurentvoid RadioService::CallbackThread::sendEvent(radio_hal_event_t *event)
3574e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent {
3584e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent     sp<IMemory> eventMemory = prepareEvent(event);
3594e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent     if (eventMemory == 0) {
3604e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent         return;
3614e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent     }
3624e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
3634e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent     AutoMutex lock(mCallbackLock);
3644e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent     mEventQueue.add(eventMemory);
3654e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent     mCallbackCond.signal();
3664e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent     ALOGV("%s DONE", __FUNCTION__);
3674e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
3684e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
3694e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
3704e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent#undef LOG_TAG
3714e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent#define LOG_TAG "RadioService::Module"
3724e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
37301d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric LaurentRadioService::Module::Module(sp<RadioInterface> hwDevice, radio_properties properties)
37453810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent : mHwDevice(hwDevice), mProperties(properties), mMute(true)
3754e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent{
3764e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
3774e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
3784e09069a29fc18d0799808cc26f71e9b068e98adEric LaurentRadioService::Module::~Module() {
37901d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent    mHwDevice.clear();
3804e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    mModuleClients.clear();
3814e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
3824e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
3834e09069a29fc18d0799808cc26f71e9b068e98adEric Laurentstatus_t RadioService::Module::dump(int fd __unused, const Vector<String16>& args __unused) {
3844e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    String8 result;
3854e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    return NO_ERROR;
3864e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
3874e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
3884e09069a29fc18d0799808cc26f71e9b068e98adEric Laurentsp<RadioService::ModuleClient> RadioService::Module::addClient(const sp<IRadioClient>& client,
3894e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent                                    const struct radio_band_config *config,
3904e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent                                    bool audio)
3914e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent{
3924e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    ALOGV("addClient() %p config %p product %s", this, config, mProperties.product);
39301d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent
3944e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    AutoMutex lock(mLock);
3954e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    sp<ModuleClient> moduleClient;
3964e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    int ret;
3974e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
39801d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent    if (mHwDevice == 0) {
39901d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent        return moduleClient;
40001d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent    }
40101d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent
4024e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    for (size_t i = 0; i < mModuleClients.size(); i++) {
4034e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        if (mModuleClients[i]->client() == client) {
4044e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            // client already connected: reject
4054e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            return moduleClient;
4064e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        }
4074e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
4084e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    moduleClient = new ModuleClient(this, client, config, audio);
4094e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
4104e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    struct radio_hal_band_config halConfig;
4114e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    halConfig = config->band;
4124e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
41353810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    // Tuner preemption logic:
41453810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    // There is a limited amount of tuners and a limited amount of radio audio sources per module.
41553810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    // The minimum is one tuner and one audio source.
41653810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    // The numbers of tuners and sources are indicated in the module properties.
41753810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    // NOTE: current framework implementation only supports one radio audio source.
41853810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    // It is possible to open more than one tuner at a time but only one tuner can be connected
41953810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    // to the radio audio source (AUDIO_DEVICE_IN_FM_TUNER).
42053810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    // The base rule is that a newly connected tuner always wins, i.e. always gets a tuner
42153810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    // and can use the audio source if requested.
42253810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    // If another client is preempted, it is notified by a callback with RADIO_EVENT_CONTROL
42353810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    // indicating loss of control.
42453810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    // - If the newly connected client requests the audio source (audio == true):
42553810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    //    - if an audio source is available
42653810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    //          no problem
42753810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    //    - if not:
42853810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    //          the oldest client in the list using audio is preempted.
42953810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    // - If the newly connected client does not request the audio source (audio == false):
43053810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    //    - if a tuner is available
43153810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    //          no problem
43253810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    //    - if not:
43353810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    //          The oldest client not using audio is preempted first and if none is found the
43453810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    //          the oldest client using audio is preempted.
43553810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    // Each time a tuner using the audio source is opened or closed, the audio policy manager is
43653810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    // notified of the connection or disconnection of AUDIO_DEVICE_IN_FM_TUNER.
43753810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent
4384e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    sp<ModuleClient> oldestTuner;
4394e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    sp<ModuleClient> oldestAudio;
4404e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    size_t allocatedTuners = 0;
4414e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    size_t allocatedAudio = 0;
4424e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    for (size_t i = 0; i < mModuleClients.size(); i++) {
4434e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        if (mModuleClients[i]->getTuner() != NULL) {
4444e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            if (mModuleClients[i]->audio()) {
4454e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent                if (oldestAudio == 0) {
4464e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent                    oldestAudio = mModuleClients[i];
4474e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent                }
4484e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent                allocatedAudio++;
4494e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            } else {
4504e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent                if (oldestTuner == 0) {
4514e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent                    oldestTuner = mModuleClients[i];
4524e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent                }
4534e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent                allocatedTuners++;
4544e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            }
4554e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        }
4564e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
4574e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
45801d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent    sp<TunerInterface> halTuner;
45953810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    sp<ModuleClient> preemtedClient;
4604e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    if (audio) {
4614e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        if (allocatedAudio >= mProperties.num_audio_sources) {
4624e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            ALOG_ASSERT(oldestAudio != 0, "addClient() allocatedAudio/oldestAudio mismatch");
46353810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent            preemtedClient = oldestAudio;
4644e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        }
4654e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    } else {
4664e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        if (allocatedAudio + allocatedTuners >= mProperties.num_tuners) {
4674e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            if (allocatedTuners != 0) {
4684e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent                ALOG_ASSERT(oldestTuner != 0, "addClient() allocatedTuners/oldestTuner mismatch");
46953810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent                preemtedClient = oldestTuner;
4704e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            } else {
4714e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent                ALOG_ASSERT(oldestAudio != 0, "addClient() allocatedAudio/oldestAudio mismatch");
47253810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent                preemtedClient = oldestAudio;
4734e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            }
4744e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        }
4754e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
47653810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    if (preemtedClient != 0) {
47753810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent        halTuner = preemtedClient->getTuner();
47801d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent        sp<TunerInterface> clear;
47901d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent        preemtedClient->setTuner(clear);
48001d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent        mHwDevice->closeTuner(halTuner);
48153810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent        if (preemtedClient->audio()) {
48253810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent            notifyDeviceConnection(false, "");
48353810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent        }
48453810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    }
4854e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
48601d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent    ret = mHwDevice->openTuner(&halConfig, audio,
48701d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent                               moduleClient,
48801d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent                               halTuner);
4894e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    if (ret == 0) {
49001d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent        ALOGV("addClient() setTuner %p", halTuner.get());
4914e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        moduleClient->setTuner(halTuner);
4924e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        mModuleClients.add(moduleClient);
49353810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent        if (audio) {
49453810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent            notifyDeviceConnection(true, "");
49553810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent        }
496f2f79cfcdec89052f49b74f9aab48e58daf606c6Eric Laurent        ALOGV("addClient() DONE moduleClient %p", moduleClient.get());
4974e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    } else {
498f2f79cfcdec89052f49b74f9aab48e58daf606c6Eric Laurent        ALOGW("%s open_tuner failed with error %d", __FUNCTION__, ret);
4994e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        moduleClient.clear();
5004e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
5014e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
5024e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    return moduleClient;
5034e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
5044e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
5054e09069a29fc18d0799808cc26f71e9b068e98adEric Laurentvoid RadioService::Module::removeClient(const sp<ModuleClient>& moduleClient) {
5064e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    ALOGV("removeClient()");
5074e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    AutoMutex lock(mLock);
5084e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    int ret;
5094e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    ssize_t index = -1;
5104e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
5114e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    for (size_t i = 0; i < mModuleClients.size(); i++) {
5124e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        if (mModuleClients[i] == moduleClient) {
5134e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            index = i;
5144e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            break;
5154e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        }
5164e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
5174e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    if (index == -1) {
5184e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        return;
5194e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
5204e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
5214e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    mModuleClients.removeAt(index);
52201d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent    sp<TunerInterface> halTuner = moduleClient->getTuner();
5234e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    if (halTuner == NULL) {
5244e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        return;
5254e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
5264e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
52701d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent    if (mHwDevice != 0) {
52801d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent        mHwDevice->closeTuner(halTuner);
52901d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent    }
53001d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent
53153810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    if (moduleClient->audio()) {
53253810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent        notifyDeviceConnection(false, "");
53353810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    }
5344e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
5354e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    mMute = true;
5364e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
5374e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    if (mModuleClients.isEmpty()) {
5384e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        return;
5394e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
5404e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
54101d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent    if (mHwDevice == 0) {
54201d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent        return;
54301d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent    }
54401d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent
54553810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    // Tuner reallocation logic:
54653810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    // When a client is removed and was controlling a tuner, this tuner will be allocated to a
54753810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    // previously preempted client. This client will be notified by a callback with
54853810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    // RADIO_EVENT_CONTROL indicating gain of control.
54953810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    // - If a preempted client is waiting for an audio source and one becomes available:
55053810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    //    Allocate the tuner to the most recently added client waiting for an audio source
55153810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    // - If not:
55253810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    //    Allocate the tuner to the most recently added client.
55353810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    // Each time a tuner using the audio source is opened or closed, the audio policy manager is
55453810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    // notified of the connection or disconnection of AUDIO_DEVICE_IN_FM_TUNER.
55553810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent
5564e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    sp<ModuleClient> youngestClient;
5574e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    sp<ModuleClient> youngestClientAudio;
5584e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    size_t allocatedTuners = 0;
5594e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    size_t allocatedAudio = 0;
56053810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    for (ssize_t i = mModuleClients.size() - 1; i >= 0; i--) {
5614e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        if (mModuleClients[i]->getTuner() == NULL) {
5624e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            if (mModuleClients[i]->audio()) {
5634e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent                if (youngestClientAudio == 0) {
5644e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent                    youngestClientAudio = mModuleClients[i];
5654e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent                }
5664e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            } else {
5674e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent                if (youngestClient == 0) {
5684e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent                    youngestClient = mModuleClients[i];
5694e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent                }
5704e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            }
5714e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        } else {
5724e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            if (mModuleClients[i]->audio()) {
5734e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent                allocatedAudio++;
5744e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            } else {
5754e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent                allocatedTuners++;
5764e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            }
5774e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        }
5784e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
5794e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
5804e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    ALOG_ASSERT(allocatedTuners + allocatedAudio < mProperties.num_tuners,
5814e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent                "removeClient() removed client but no tuner available");
5824e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
5834e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    ALOG_ASSERT(!moduleClient->audio() || allocatedAudio < mProperties.num_audio_sources,
5844e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent                "removeClient() removed audio client but no tuner with audio available");
5854e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
5864e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    if (allocatedAudio < mProperties.num_audio_sources && youngestClientAudio != 0) {
5874e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        youngestClient = youngestClientAudio;
5884e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
5894e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
5904e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    ALOG_ASSERT(youngestClient != 0, "removeClient() removed client no candidate found for tuner");
5914e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
5924e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    struct radio_hal_band_config halConfig = youngestClient->halConfig();
59301d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent    ret = mHwDevice->openTuner(&halConfig, youngestClient->audio(),
59401d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent                                moduleClient,
59501d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent                                halTuner);
5964e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
5974e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    if (ret == 0) {
5984e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        youngestClient->setTuner(halTuner);
59953810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent        if (youngestClient->audio()) {
60053810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent            notifyDeviceConnection(true, "");
60153810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent        }
6024e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
6034e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
6044e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
6054e09069a29fc18d0799808cc26f71e9b068e98adEric Laurentstatus_t RadioService::Module::setMute(bool mute)
6064e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent{
6074e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    Mutex::Autolock _l(mLock);
6084e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    if (mute != mMute) {
6094e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        mMute = mute;
6104e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        //TODO notifify audio policy manager of media activity on radio audio device
6114e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
6124e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    return NO_ERROR;
6134e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
6144e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
6154e09069a29fc18d0799808cc26f71e9b068e98adEric Laurentstatus_t RadioService::Module::getMute(bool *mute)
6164e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent{
6174e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    Mutex::Autolock _l(mLock);
6184e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    *mute = mMute;
6194e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    return NO_ERROR;
6204e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
6214e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
6224e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
6234e09069a29fc18d0799808cc26f71e9b068e98adEric Laurentconst struct radio_band_config *RadioService::Module::getDefaultConfig() const
6244e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent{
6254e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    if (mProperties.num_bands == 0) {
6264e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        return NULL;
6274e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
6284e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    return &mProperties.bands[0];
6294e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
6304e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
63153810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurentvoid RadioService::Module::notifyDeviceConnection(bool connected,
63253810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent                                                  const char *address) {
63353810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    int64_t token = IPCThreadState::self()->clearCallingIdentity();
63453810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_IN_FM_TUNER,
63553810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent                                          connected ? AUDIO_POLICY_DEVICE_STATE_AVAILABLE :
63653810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent                                                  AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
63753810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent                                          address, kRadioTunerAudioDeviceName);
63853810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent    IPCThreadState::self()->restoreCallingIdentity(token);
63953810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent}
64053810823a6613f54fc0b3c3bc0de267dc1f4e1e5Eric Laurent
6414e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent#undef LOG_TAG
6424e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent#define LOG_TAG "RadioService::ModuleClient"
6434e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
6444e09069a29fc18d0799808cc26f71e9b068e98adEric LaurentRadioService::ModuleClient::ModuleClient(const sp<Module>& module,
6454e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent                                         const sp<IRadioClient>& client,
6464e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent                                         const struct radio_band_config *config,
6474e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent                                         bool audio)
64801d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent : mModule(module), mClient(client), mConfig(*config), mAudio(audio), mTuner(0)
6494e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent{
6504e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
6514e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
6524e09069a29fc18d0799808cc26f71e9b068e98adEric Laurentvoid RadioService::ModuleClient::onFirstRef()
6534e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent{
6544e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    mCallbackThread = new CallbackThread(this);
6554e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    IInterface::asBinder(mClient)->linkToDeath(this);
6564e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
6574e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
6584e09069a29fc18d0799808cc26f71e9b068e98adEric LaurentRadioService::ModuleClient::~ModuleClient() {
6594e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    if (mClient != 0) {
6604e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        IInterface::asBinder(mClient)->unlinkToDeath(this);
6614e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        mClient.clear();
6624e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
6634e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    if (mCallbackThread != 0) {
6644e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        mCallbackThread->exit();
6654e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
6664e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
6674e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
66801d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurentvoid RadioService::ModuleClient::onEvent(radio_hal_event_t *halEvent)
66901d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent{
67001d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent    mCallbackThread->sendEvent(halEvent);
67101d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent}
67201d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent
6734e09069a29fc18d0799808cc26f71e9b068e98adEric Laurentstatus_t RadioService::ModuleClient::dump(int fd __unused,
6744e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent                                             const Vector<String16>& args __unused) {
6754e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    String8 result;
6764e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    return NO_ERROR;
6774e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
6784e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
6794e09069a29fc18d0799808cc26f71e9b068e98adEric Laurentvoid RadioService::ModuleClient::detach() {
6804e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    ALOGV("%s", __FUNCTION__);
6814e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    sp<ModuleClient> strongMe = this;
6824e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    {
6834e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        AutoMutex lock(mLock);
6844e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        if (mClient != 0) {
6854e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            IInterface::asBinder(mClient)->unlinkToDeath(this);
6864e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            mClient.clear();
6874e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        }
6884e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
6894e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    sp<Module> module = mModule.promote();
6904e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    if (module == 0) {
6914e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        return;
6924e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
6934e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    module->removeClient(this);
6944e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
6954e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
6964e09069a29fc18d0799808cc26f71e9b068e98adEric Laurentradio_hal_band_config_t RadioService::ModuleClient::halConfig() const
6974e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent{
6984e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    AutoMutex lock(mLock);
6994e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    ALOGV("%s locked", __FUNCTION__);
7004e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    return mConfig.band;
7014e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
7024e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
70301d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurentsp<TunerInterface>& RadioService::ModuleClient::getTuner()
7044e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent{
7054e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    AutoMutex lock(mLock);
7064e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    ALOGV("%s locked", __FUNCTION__);
7074e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    return mTuner;
7084e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
7094e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
71001d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurentvoid RadioService::ModuleClient::setTuner(sp<TunerInterface>& tuner)
7114e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent{
7124e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    ALOGV("%s %p", __FUNCTION__, this);
7134e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
7144e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    AutoMutex lock(mLock);
7154e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    mTuner = tuner;
7164e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    ALOGV("%s locked", __FUNCTION__);
7174e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
7184e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    radio_hal_event_t event;
7194e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    event.type = RADIO_EVENT_CONTROL;
7204e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    event.status = 0;
72101d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent    event.on = mTuner != 0;
7224e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    mCallbackThread->sendEvent(&event);
7234e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    ALOGV("%s DONE", __FUNCTION__);
7244e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
7254e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
7264e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
7274e09069a29fc18d0799808cc26f71e9b068e98adEric Laurentstatus_t RadioService::ModuleClient::setConfiguration(const struct radio_band_config *config)
7284e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent{
7290e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Park    if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
7300e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Park        return PERMISSION_DENIED;
7310e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Park    }
7324e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    AutoMutex lock(mLock);
7334e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    status_t status = NO_ERROR;
7344e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    ALOGV("%s locked", __FUNCTION__);
7354e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
73601d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent    if (mTuner != 0) {
7374e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        struct radio_hal_band_config halConfig;
7384e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        halConfig = config->band;
73901d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent        status = (status_t)mTuner->setConfiguration(&halConfig);
7404e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        if (status == NO_ERROR) {
7414e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            mConfig = *config;
7424e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        }
7434e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    } else {
7444e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        mConfig = *config;
7451395874b91ddcd29e36d2bb6b86567f6f2319efcAurimas Liutikas        status = INVALID_OPERATION;
7464e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
7474e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
7484e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    return status;
7494e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
7504e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
7514e09069a29fc18d0799808cc26f71e9b068e98adEric Laurentstatus_t RadioService::ModuleClient::getConfiguration(struct radio_band_config *config)
7524e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent{
7530e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Park    if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
7540e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Park        return PERMISSION_DENIED;
7550e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Park    }
7564e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    AutoMutex lock(mLock);
7574e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    status_t status = NO_ERROR;
7584e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    ALOGV("%s locked", __FUNCTION__);
7594e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
76001d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent    if (mTuner != 0) {
7614e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        struct radio_hal_band_config halConfig;
76201d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent        status = (status_t)mTuner->getConfiguration(&halConfig);
7634e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        if (status == NO_ERROR) {
7644e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            mConfig.band = halConfig;
7654e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        }
7664e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
7674e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    *config = mConfig;
7684e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
7694e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    return status;
7704e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
7714e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
7724e09069a29fc18d0799808cc26f71e9b068e98adEric Laurentstatus_t RadioService::ModuleClient::setMute(bool mute)
7734e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent{
7740e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Park    if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
7750e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Park        return PERMISSION_DENIED;
7760e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Park    }
7774e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    sp<Module> module;
7784e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    {
7794e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        Mutex::Autolock _l(mLock);
7804e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        ALOGV("%s locked", __FUNCTION__);
78101d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent        if (mTuner == 0 || !mAudio) {
7824e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            return INVALID_OPERATION;
7834e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        }
7844e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        module = mModule.promote();
7854e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        if (module == 0) {
7864e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            return NO_INIT;
7874e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        }
7884e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
7894e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    module->setMute(mute);
7904e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    return NO_ERROR;
7914e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
7924e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
7934e09069a29fc18d0799808cc26f71e9b068e98adEric Laurentstatus_t RadioService::ModuleClient::getMute(bool *mute)
7944e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent{
7950e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Park    if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
7960e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Park        return PERMISSION_DENIED;
7970e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Park    }
7984e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    sp<Module> module;
7994e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    {
8004e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        Mutex::Autolock _l(mLock);
8014e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        ALOGV("%s locked", __FUNCTION__);
8024e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        module = mModule.promote();
8034e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        if (module == 0) {
8044e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            return NO_INIT;
8054e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        }
8064e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
8074e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    return module->getMute(mute);
8084e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
8094e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
8104e09069a29fc18d0799808cc26f71e9b068e98adEric Laurentstatus_t RadioService::ModuleClient::scan(radio_direction_t direction, bool skipSubChannel)
8114e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent{
8120e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Park    if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
8130e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Park        return PERMISSION_DENIED;
8140e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Park    }
8154e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    AutoMutex lock(mLock);
8164e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    ALOGV("%s locked", __FUNCTION__);
8174e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    status_t status;
81801d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent    if (mTuner != 0) {
81901d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent        status = (status_t)mTuner->scan(direction, skipSubChannel);
8204e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    } else {
8214e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        status = INVALID_OPERATION;
8224e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
8234e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    return status;
8244e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
8254e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
8264e09069a29fc18d0799808cc26f71e9b068e98adEric Laurentstatus_t RadioService::ModuleClient::step(radio_direction_t direction, bool skipSubChannel)
8274e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent{
8280e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Park    if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
8290e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Park        return PERMISSION_DENIED;
8300e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Park    }
8314e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    AutoMutex lock(mLock);
8324e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    ALOGV("%s locked", __FUNCTION__);
8334e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    status_t status;
83401d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent    if (mTuner != 0) {
83501d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent        status = (status_t)mTuner->step(direction, skipSubChannel);
8364e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    } else {
8374e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        status = INVALID_OPERATION;
8384e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
8394e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    return status;
8404e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
8414e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
84201d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurentstatus_t RadioService::ModuleClient::tune(uint32_t channel, uint32_t subChannel)
8434e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent{
8440e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Park    if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
8450e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Park        return PERMISSION_DENIED;
8460e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Park    }
8474e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    AutoMutex lock(mLock);
8484e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    ALOGV("%s locked", __FUNCTION__);
8494e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    status_t status;
85001d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent    if (mTuner != 0) {
85101d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent        status = (status_t)mTuner->tune(channel, subChannel);
8524e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    } else {
8534e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        status = INVALID_OPERATION;
8544e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
8554e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    return status;
8564e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
8574e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
8584e09069a29fc18d0799808cc26f71e9b068e98adEric Laurentstatus_t RadioService::ModuleClient::cancel()
8594e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent{
8600e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Park    if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
8610e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Park        return PERMISSION_DENIED;
8620e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Park    }
8634e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    AutoMutex lock(mLock);
8644e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    ALOGV("%s locked", __FUNCTION__);
8654e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    status_t status;
86601d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent    if (mTuner != 0) {
86701d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent        status = (status_t)mTuner->cancel();
8684e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    } else {
8694e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        status = INVALID_OPERATION;
8704e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
8714e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    return status;
8724e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
8734e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
8744e09069a29fc18d0799808cc26f71e9b068e98adEric Laurentstatus_t RadioService::ModuleClient::getProgramInformation(struct radio_program_info *info)
8754e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent{
8760e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Park    if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
8770e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Park        return PERMISSION_DENIED;
8780e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Park    }
8794e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    AutoMutex lock(mLock);
8804e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    ALOGV("%s locked", __FUNCTION__);
8814e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    status_t status;
8824e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    if (mTuner != NULL) {
88301d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent        status = (status_t)mTuner->getProgramInformation(info);
8844e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    } else {
8854e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        status = INVALID_OPERATION;
8864e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
887aebf5fbc6978ba6791690696e22a277be7eefa9bEric Laurent
8884e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    return status;
8894e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
8904e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
8914e09069a29fc18d0799808cc26f71e9b068e98adEric Laurentstatus_t RadioService::ModuleClient::hasControl(bool *hasControl)
8924e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent{
8930e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Park    if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
8940e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Park        return PERMISSION_DENIED;
8950e37854e54944892b15a72ed4633f0347dbc2cb8Keun-young Park    }
8964e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    Mutex::Autolock lock(mLock);
8974e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    ALOGV("%s locked", __FUNCTION__);
89801d267e3a78e1fa78d27f6d3e745914a5ac56ffaEric Laurent    *hasControl = mTuner != 0;
8994e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    return NO_ERROR;
9004e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
9014e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
9024e09069a29fc18d0799808cc26f71e9b068e98adEric Laurentvoid RadioService::ModuleClient::onCallbackEvent(const sp<IMemory>& eventMemory)
9034e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent{
9044e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
9054e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        return;
9064e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
9074e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
9084e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    sp<IRadioClient> client;
9094e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    {
9104e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        AutoMutex lock(mLock);
9114e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        ALOGV("%s locked", __FUNCTION__);
9124e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        radio_event_t *event = (radio_event_t *)eventMemory->pointer();
9134e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        switch (event->type) {
9144e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        case RADIO_EVENT_CONFIG:
9154e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            mConfig.band = event->config.band;
9164e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            event->config.region = mConfig.region;
9174e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            break;
9184e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        default:
9194e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent            break;
9204e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        }
9214e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
9224e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        client = mClient;
9234e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
9244e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    if (client != 0) {
9254e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent        client->onEvent(eventMemory);
9264e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    }
9274e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
9284e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
9294e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
9304e09069a29fc18d0799808cc26f71e9b068e98adEric Laurentvoid RadioService::ModuleClient::binderDied(
9314e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    const wp<IBinder> &who __unused) {
9324e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    ALOGW("client binder died for client %p", this);
9334e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent    detach();
9344e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}
9354e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent
9364e09069a29fc18d0799808cc26f71e9b068e98adEric Laurent}; // namespace android
937