標籤:
最近在學習FM模組,FM是一個值得學習的模組,可以從上層看到底層。
上層就是FM的按扭操作和介面顯示,從而調用到FM底層驅動來實現廣播收聽的功能。
FM啟動流程:如:
先進入FMRadio.java類,onCreate初始化一些資料,畫出FM介面,啟動fm在onStart()方法裡啟動FMRadioService.java (調用bindToService(this, osc)方法)。
註冊下fm設定(在設定後發送一個設定廣播,更新FMRadio類的狀態)。
載入初始化資料,擷取頻率地址
newPresetStation("",FmSharedPreferences.getTunedFrequency());
在bindToService(this,osc)方法中,先啟動StartService(同一個Service只onCreate一次),再啟動bindservice(這樣有個好處按返回鍵service不會走onDestroy方法)bindservice通過onBind回傳一個IBinder對象到FMRadio類的內部類ServiceConnection的onServiceConnected方法中,調用enableRadio()方法。
在enableRaido方法中調用FMRadio.java的isAntennaAvailable()方法進行耳機判斷,天線判斷是否可用,通過一個插入拔出廣播接收來控制的(FMRadio中的registerHeadsetListener()方法)action(Intent.ACTION_HEADSET_PLUG)
mHeadsetPlugged =(intent.getIntExtra("state", 0) == 1); 等於1說明耳機可用,等於0可用。
調用FmRadio方法FmOn (mService.fmOn())
介面可用enableRadioOnOffUI()
private void enableRadio() { mIsScaning = false; mIsSeeking = false; mIsSearching = false; boolean bStatus = false; if (isHdmiOn()) { showDialog(DIALOG_CMD_FAILED_HDMI_ON); }else { <span style="font-family:KaiTi_GB2312;"> </span>if (mService != null) { try { if((false == mService.isFmOn()) && isAntennaAvailable()) { bStatus = mService.fmOn(); if(bStatus) { tuneRadio(FmSharedPreferences.getTunedFrequency()); enableRadioOnOffUI(); }else {Log.e(LOGTAG, "mService.fmOn failed"); mCommandFailed = CMD_FMON; if(isCallActive()) { enableRadioOnOffUI(); showDialog(DIALOG_CMD_FAILED_CALL_ON); }else { showDialog(DIALOG_CMD_FAILED); } } }else {enableRadioOnOffUI(); } }catch (RemoteException e) { e.printStackTrace(); } } } }
在FMRadioService.java的fmOn()方法中初始化FmReceiver的引用mReceiver = newFmReceiver(FMRADIO_DEVICE_FD_STRING, fmCallbacks);
取出設定儲存的地區頻率的屬性
FmConfig config =FmSharedPreferences.getFMConfiguration();
真正接受fm聲音在
bStatus =mReceiver.enable(FmSharedPreferences.getFMConfiguration());
isSpeakerEnabled()擴音器可用,使用者佈建擴音器
設定鈴聲路徑
boolean state =mReceiver.setAnalogMode(analogMode); analogMode類比設定低功率
bStatus = setLowPowerMode(false);
電話不在閑置狀太下
int state = getCallState();
fmActionOnCallState(state);
啟動FM startFM();設定耳機等可以接受fm聲音
AudioSystem.setForceUse(AudioSystem.FOR_MEDIA,AudioSystem.FORCE_NONE);
Fm裝置可用
AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_FM,
AudioSystem.DEVICE_STATE_AVAILABLE, "");
註冊遠程組的處理
bStatus = mReceiver.registerRdsGroupProcessing(FmReceiver.FM_RX_RDS_GRP_RT_EBL|
FmReceiver.FM_RX_RDS_GRP_PS_EBL|
FmReceiver.FM_RX_RDS_GRP_AF_EBL|
FmReceiver.FM_RX_RDS_GRP_PS_SIMPLE_EBL);
可用自動跳轉到選著的頻率
bStatus =enableAutoAF(FmSharedPreferences.getAutoAFSwitch());
將內建天線設為0
FmTransceiver.java
FmReceiverJNI.setControlNative (sFd, V4L2_CID_PRIVATE_TAVARUA_ANTENNA,iAntenna)
mReceiver.setInternalAntenna(false)
總結:
1.由於Android版本不同,各大廠商對FM做了不同的定製,代碼均有差異,但是總體架構沒有變;
2.FM為Google完全開原始碼,代碼路徑在vendor/qcom裡面;
3.FM不同於其他應用,待續....
vendor 目錄 (廠家定製內容)
|-- aosp (android open source project)
| `-- products (一些板級規則)
|-- htc (HTC公司)
| |-- common-open (通用部分)
| | `-- akmd (解壓img用的工具)
| |-- dream-open (G1開放部分)
| |-- prebuilt-open (先行編譯開放部分)
| `-- sapphire-open (sapphire這款型號開放內容)
|-- pv-open (沒東西)
|-- qcom (裡面基本是空的)
`-- sample (google提供的範例)
|-- apps (應用)
| |-- client (使用者)
| `-- upgrade (升級)
|-- frameworks (架構)
| `-- PlatformLibrary (平台庫)
|-- products (產品)
|-- sdk_addon (sdk添加部分)
`-- skins (皮膚)
`-- WVGAMedDpi (WVGA適用的圖片)
Android FM模組學習之一 FM啟動流程