FMRadio

目前android还没有有关FMRadio的application接口类,下面对目前存在的一个实现案例进行分析。
硬件: BCM4329 + CPCAP
        要求:BCM4327需要连接RX天线
             audio analog out与CPCAP相连
软件:
  FMRadio.apk   --> Java应用
  libfmradio_jni.so : frameworks/base/fmradio/jni  --> Jni
  libfmradioplayer.so  :             -->    HAL
  libfmradiostackservice.so  :       -->    HAL
  libFMRadio.so 这是实现FM的基本功能库 比如搜台 依赖于libbluetooth libutils 之所以跟蓝牙相关,是因为BCM4329是个蓝牙+WIFI+FM的合成芯片,FM与蓝牙共用电源,发命令共用一个HCI。
  libaudio.so
首先,在init.rc中,需要启动一个FM服务,这里叫fmradio,可执行文件叫fmradioserver
service fmradio /system/bin/fmradioserver
    group bluetooth
fmradioserver的代码示例:
int main(int argc, char** argv)
{
....
    FMRadioStackService::instantiate(); // start the fmradio.stack service
....
}
FMRadioStackService.cpp
void FMRadioStackService::instantiate() {
    defaultServiceManager()->addService(
            String16("fmradio.stack"), new FMRadioStackService());
}
通过这个FMRadioStackService类,FM的基本功能已经可用
class FMRadioStackService : public BnFMRadioStackService, protected Thread
{
public:
        static void instantiate();
。。。
        virtual bool powerOnDevice();
        virtual bool powerOffDevice();
        virtual void setFMRadioPlayerClient(const sp& client);
        virtual bool open();
        virtual bool getBand() const;
        virtual bool setBand(RADIO_BAND bind);
        virtual bool tune(unsigned int freq);
        virtual bool currentFreq() const;
        virtual bool setAudioMode(AUDIO_MODE mode);
        virtual bool getAudioMode() const;
        virtual bool seek(SEEK_DIRECTION direction);
        virtual bool stopSeek();
        virtual bool setVolume(unsigned int vol);
        virtual bool getVolume() const;
        virtual bool setEmphasisFilter(EMPHASIS_FILTER filter);
        virtual bool getEmphasisFilter() const;
        virtual bool setMute(MUTE_MODE mode);
        virtual bool isMute() const;
        virtual bool enableAudioTarget(AUDIO_TARGET val); // should be called after set band;
        virtual bool disableAudioTarget(AUDIO_TARGET val);
        virtual bool getRssiLevel();
        virtual int  getChipsetId();
        virtual bool close();

        static void fm_int_handler(FMRadio_Msgs_t, int, int, char*);
private:
        sp m_client;
。。。。
}
FMRadioStackService继承了BnFMRadioStackService, BnFMRadioStackService继承了BBinder与IFMRadioStackService,实现了onTransact()。如果把 整个FMRadio看作是Client/Server模式的话,Server端就算完成了。这里有一个私有成员变量m_client显得比较奇怪,其实它 是用来向上notify状态的,通过virtual void setFMRadioPlayerClient(const sp& client)赋值。
根据binder机制,我们知道一定会有一个BpFMRadioStackService,它继承BBinder与 IFMRadioStackService,通过remote()->transact()实现IFMRadioStackService接口,给 Client上层提供各种FMRadio功能的调用,当然remote()->transact()通过 BnFMRadioStackService调到了真正的底层服务。
通过JNI gMethods
static JNINativeMethod gMethods[] = {
    {"powerOnDevice",    "()Z",      (void*)fmradio_powerOn },
    {"powerOffDevice",   "()Z",      (void*)fmradio_powerOff },
    {"open",       "()Z",            (void*)fmradio_open },
    {"getBand",    "()Z",            (void*)fmradio_getBand },
    {"setBand",    "(I)Z",           (void*)fmradio_setBand },
    {"tune",       "(I)Z",           (void*)fmradio_tune },
    {"currentFreq", "()Z",           (void*)fmradio_currentFreq },
    {"setAudioMode", "(I)Z",         (void*)fmradio_setAudioMode },
    {"getAudioMode", "()Z",          (void*)fmradio_getAudioMode },
    {"seek",         "(I)Z",         (void*)fmradio_seek },
    {"stopSeek",     "()Z",          (void*)fmradio_stopSeek },
    {"setVolume",    "(I)Z",         (void*)fmradio_setVolume },
    {"getVolume",    "()Z",          (void*)fmradio_getVolume },
    {"setEmphasisFilter", "(I)Z",    (void*)fmradio_setEmphasisFilter },
    {"getEmphasisFilter", "()Z",     (void*)fmradio_getEmphasisFilter },
    {"setMute",     "(I)Z",          (void*)fmradio_setMute },
    {"isMute",      "()Z",           (void*)fmradio_isMute },
    {"enableAudioTarget", "(I)Z",    (void*)fmradio_enableAudioTarget },
    {"disableAudioTarget","(I)Z",    (void*)fmradio_disableAudioTarget },
    {"close",       "()Z",           (void*)fmradio_close },
    {"native_setup", "(Ljava/lang/Object;)V",          (void*)fmradio_native_setup },
    {"native_finalize", "()V",       (void*)fmradio_native_finalize }
};

加上registerNativeMethods
    if(AndroidRuntime::registerNativeMethods(env, "com/motorola/fmradio/FMRadioPlayer", gMethods, NELEM(gMethods))>= 0) {
        result = JNI_VERSION_1_4;
    }
我们把com.motorola.fmradio.FMRadioPlayer这个FM类提供给了application developer.
当然,你还需要写一个FMRadioPlayer.cpp 把这些native方法申明一下。
以下的故事应该从native_setup开始,因为它绑定了fmradio.stack服务,所以它被放在了FMRadioPlayer的构造函数中。
JNIEXPORT void JNICALL fmradio_native_setup(JNIEnv *env, jobject obj, jobject weak_this)
{
    LOGI("IN JNI fmradio_native_setup/n");
    sp fmstack = getFMRadioStackService();//这里会有binder = sm->getService(String16("fmradio.stack"));
。。。
}
以后的应用层内容(略)


猜你喜欢

转载自guojianhui0906.iteye.com/blog/1197422