转自:http://qiuzhenqing.blog.edu.cn/2010/576669.html。作者:qiuzhenqing
目前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"));
。。。
}
以后的应用层内容(略)