简单分析一下FM的搜索频率流程。
在了解源码之前,我们先看一下流程图:
其实从图中可以看到,实现搜索频率的功能是在底层CPP文件,java层只操作和更新一些界面(GUI),Java调用JNI实现功能。Java app基本核心,通过方法回调实现a类和b类方法,b类调a类方法信息交互相互控制融为一体。App实现一些JNI接口最终实现核心功能是cpp文件,最后通过Service类(耗时操作)调用New一个线程循环不断的获取cpp里的信息,去更新UI界面活动状态。
搜索流程简单分析:点击搜索按钮,通过互调方法,最后调到FMReceiverJNI类中的方法实现功能。通过FMRxEventListner类不断获取cpp变频的频率,每获取一次频率(直到频率搜索完成停止调用)就回调FMRadioService内部FmRxEvCallbacksAdaptor的方法在回调到FMRadio类中方法,将频率存入FmSharedPreferences类xml文档中,发送Handler更新UI,即刻度盘,对话框,左右箭头中间显示的频率一致跳动。
接下来详细代码分析:
FMRadio中的菜单搜索功能,onOptionsItemSelected(MenuItem item)监听中走initiateSearch(mScanPtyIndex);方法。
调用FMRadioService的scan()方法(mService.scan(pty))进行扫描频率
updateSearchProgress()里加了同步方法对象锁
调用了private Dialog createProgressDialog(int id)对话框进行搜索信息
标准耳机FmSharedPreferences.isRBDSStd()
- private Dialog <strong>createProgressDialog</strong>(int id) {
- String msgStr = "";
- String titleStr = "";
- String []items;
- double frequency = mTunedStation.getFrequency() / 1000.0;
- boolean bSearchActive = false;
-
- if (isSeekActive()) {
- msgStr = getString(R.string.msg_seeking);
- bSearchActive = true;
- }else if (isScanActive()) {
- if(FmSharedPreferences.isRBDSStd()) {<span style="font-family:KaiTi_GB2312;">
- items = getResources().
- getStringArray(R.array.search_category_rbds_entries);
- }else {
- items = getResources().
- getStringArray(R.array.search_category_rds_entries);
- }String ptyStr = "";
- if (items.length > mScanPtyIndex)
- ptyStr = items[mScanPtyIndex];
- if (!TextUtils.isEmpty(ptyStr)) {
- msgStr = getString(R.string.msg_scanning_pty, ptyStr);
- }else {
- Log.d(LOGTAG, "pty is null\n");
- msgStr = getString(R.string.msg_scanning);
- }
- titleStr = getString(R.string.msg_search_title, ("" + frequency));
- bSearchActive=true;
- }else if (isSearchActive()) {
- msgStr = getString(R.string.msg_searching);
- titleStr = getString(R.string.msg_searching_title);
- bSearchActive = true;
- }
- if (bSearchActive) {mProgressDialog = new ProgressDialog(FMRadio.this);
- if (mProgressDialog != null) {
- mProgressDialog.setTitle(titleStr);
- mProgressDialog.setMessage(msgStr);
- mProgressDialog.setIcon(R.drawable.ic_launcher_fmradio);
- mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
- mProgressDialog.setCanceledOnTouchOutside(false);
- mProgressDialog.setButton(DialogInterface.BUTTON_POSITIVE,
- getText(R.string.button_text_stop),
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int whichButton) {
- <strong>cancelSearch();</strong>
- }
- });
- mProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() { public void onCancel(DialogInterface dialog) {
- cancelSearch();
- }
- });
- mProgressDialog.setOnKeyListener(new OnKeyListener() {
- public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
- Log.d(LOGTAG, "OnKeyListener event received in ProgressDialog" + keyCode);
- switch (keyCode) {
- case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
- case 126:
- case 127:
- case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
- case KeyEvent.KEYCODE_MEDIA_NEXT:
- case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
- case KeyEvent.KEYCODE_MEDIA_REWIND:
- case KeyEvent.KEYCODE_MEDIA_STOP:
- return true;
- } return false;
- }
- });
- }
- Message msg = new Message();
- msg.what = TIMEOUT_PROGRESS_DLG;
- mSearchProgressHandler.sendMessageDelayed(msg, SHOWBUSY_TIMEOUT);
- }
- return mProgressDialog;
- }
调用FMRadioService类中的Scan()方法扫描
调用 FMReceiver的searchStations()方法进行扫描
- public boolean<strong> scan(int pty)</strong>
- {
- boolean bCommandSent=false;
- if (mReceiver != null)
- {
- Log.d(LOGTAG, "scan: PTY: " + pty);
- if(FmSharedPreferences.isRBDSStd())
- {
-
- if( ((pty > 0) && (pty <= 23)) || ((pty >= 29) && (pty <= 31)) )
- {bCommandSent = <strong>mReceiver.searchStations</strong>(FmReceiver.FM_RX_SRCHRDS_MODE_SCAN_PTY,
- FmReceiver.FM_RX_DWELL_PERIOD_2S,
- FmReceiver.FM_RX_SEARCHDIR_UP,
- pty,
- 0);
- }
- else
- {
- bCommandSent = <strong>mReceiver.searchStations</strong>(FmReceiver.FM_RX_SRCH_MODE_SCAN,
- FmReceiver.FM_RX_DWELL_PERIOD_2S,
- FmReceiver.FM_RX_SEARCHDIR_UP);
- }}
- else
- {
-
- if( (pty > 0) && (pty <= 31) )
- {
- bCommandSent = <strong>mReceiver.searchStations</strong>(FmReceiver.FM_RX_SRCHRDS_MODE_SCAN_PTY,
- FmReceiver.FM_RX_DWELL_PERIOD_2S,
- FmReceiver.FM_RX_SEARCHDIR_UP,
- pty,
- 0);
- }
- else{
- bCommandSent =<strong> mReceiver.searchStations</strong>(FmReceiver.FM_RX_SRCH_MODE_SCAN,
- FmReceiver.FM_RX_DWELL_PERIOD_2S,
- FmReceiver.FM_RX_SEARCHDIR_UP);
- }
- }
- }
- return bCommandSent;
- }
FmReceiver类的public boolean searchStations (int mode,int dwellPeriod,intdirection,int pty,Int pi) 方法
获得FMState状态
int state = getFMState();
/ * 验证参数* /
调用setSearchState(subSrchLevel_ScanInProg);
re = mControl.searchStations(sFd, mode,dwellPeriod, direction, pty, pi);
- public boolean <strong>searchStations </strong>(int mode,
- int dwellPeriod,
- int direction){
-
- <strong> int state = getFMState();</strong>
- boolean bStatus = true;
- int re;
-
-
- if (state == FMState_Turned_Off || state == FMState_Srch_InProg) {
- Log.d(TAG, "searchStations: Device currently busy in executing another command.");
- return false;
- }
-
- Log.d (TAG, "Basic search...");
-
- if ( (mode != FM_RX_SRCH_MODE_SEEK) &&
- (mode != FM_RX_SRCH_MODE_SCAN))
- {
- Log.d (TAG, "Invalid search mode: " + mode );
- bStatus = false;
- }
- if ( (dwellPeriod < FM_RX_DWELL_PERIOD_0S ) ||
- (dwellPeriod > FM_RX_DWELL_PERIOD_7S))
- {
- Log.d (TAG, "Invalid dwelling time: " + dwellPeriod);
- bStatus = false;
- }
- if ( (direction != FM_RX_SEARCHDIR_DOWN) &&
- (direction != FM_RX_SEARCHDIR_UP))
- {
- Log.d (TAG, "Invalid search direction: " + direction);
- bStatus = false;
- }
- if (bStatus)
- {
- Log.d (TAG, "searchStations: mode " + mode + "direction: " + direction);
-
- if (mode == FM_RX_SRCH_MODE_SEEK)
- setSearchState(subSrchLevel_SeekInPrg);
- else if (mode == FM_RX_SRCH_MODE_SCAN)
- setSearchState(subSrchLevel_ScanInProg);
- Log.v(TAG, "searchStations: CURRENT-STATE : FMRxOn ---> NEW-STATE : SearchInProg");
-
- <strong> re = mControl.searchStations(sFd, mode, dwellPeriod, direction, 0, 0);</strong>
- if (re != 0) {
- Log.e(TAG, "search station failed");
- if (getFMState() == FMState_Srch_InProg)
- setSearchState(subSrchLevel_SrchComplete);
- return false;
- } state = getFMState();
- if (state == FMState_Turned_Off) {
- Log.d(TAG, "searchStations: CURRENT-STATE : FMState_Off (unexpected)");
- return false;
- }
- }
- return bStatus;
- }
设置FM搜索电源状态
- static void <strong>setSearchState</strong>(int state)
- {
- mSearchState = state;
- switch(mSearchState) {
- case subSrchLevel_SeekInPrg:
- case subSrchLevel_ScanInProg:
- case subSrchLevel_SrchListInProg:
- setFMPowerState(FMState_Srch_InProg);
- break;
- case subSrchLevel_SrchComplete:
-
- mSearchState = subSrchLevel_NoSearch;
- setFMPowerState(FMState_Rx_Turned_On);
- break;
- case subSrchLevel_SrchAbort:
- break;
- default:
- mSearchState = subSrchLevel_NoSearch;
- break;
- }
- }
setFMPowerState(FMState_Rx_Turned_On); 是调用FmTransceiver类发射器类,FM电源状态
-
-
-
-
-
-
-
-
-
-
-
- static void <strong>setFMPowerState(</strong>int state)
- {
- FMState = state;
- }
调用FMRxControls.java类的
/ * 配置各种搜索参数,开始搜索* /
public int searchStations (int fd, int mode,int dwell, int dir, int pty, int pi)
设置一些参数
FmReceiverJNI.setControlNative();
设置的搜索模式
设置扫描居住的时间
设置的企业
设置PI
-
- public int <strong>searchStations </strong>(int fd, int mode, int dwell,
- int dir, int pty, int pi){
- int re = 0;
-
-
- Log.d(TAG, "Mode is " + mode + " Dwell is " + dwell);
- Log.d(TAG, "dir is " + dir + " PTY is " + pty);
- Log.d(TAG, "pi is " + pi + " id " + V4L2_CID_PRIVATE_TAVARUA_SRCHMODE);
-
-
-
- <strong> re = FmReceiverJNI.setControlNative (fd, V4L2_CID_PRIVATE_TAVARUA_SRCHMODE, mode);</strong>
- if (re != 0) {
- Log.e(TAG, "setting of search mode failed");
- return re;
- }
- <strong>re = FmReceiverJNI.setControlNative (fd, V4L2_CID_PRIVATE_TAVARUA_SCANDWELL, dwell);</strong>
- if (re != 0) {
- Log.e(TAG, "setting of scan dwell time failed");
- return re;
- }
- if (pty != 0)
- { re = FmReceiverJNI.setControlNative (fd, V4L2_CID_PRIVATE_TAVARUA_SRCH_PTY, pty);
- if (re != 0) {
- Log.e(TAG, "setting of PTY failed");
- return re;
- }
- }
-
- if (pi != 0)
- {
- <strong> re = FmReceiverJNI.setControlNative (fd, V4L2_CID_PRIVATE_TAVARUA_SRCH_PI, pi);</strong>
- if (re != 0) {
- Log.e(TAG, "setting of PI failed");
- return re;
- }
- }
-
- <strong>re = FmReceiverJNI.startSearchNative (fd, dir );</strong>
- return re;
- }
启动搜索 FmReceiverJNI.startSearchNative (fd, dir );
关闭搜索
FMRadio 调用 FMRadioService 的CancelSearch()方法
public boolean cancelSearch()
- public boolean <strong>cancelSearch()</strong>
- {
- boolean bCommandSent=false;
- if (mReceiver != null)
- {
- Log.d(LOGTAG, "cancelSearch");
- bCommandSent = <strong>mReceiver.cancelSearch();</strong>
- }
- return bCommandSent;
- }
调用FRReceiver的cancelSearch()
mReceiver.cancelSearch()
更新搜索 FMRadio.java中
updateSearchProgress();
- private void <strong>updateSearchProgress()</strong> {
- boolean searchActive = isScanActive() || isSeekActive() || isSearchActive();
- if (searchActive) {
- synchronized (this) {
- if(mProgressDialog == null) {
- showDialog(DIALOG_PROGRESS_PROGRESS);
- }else {
- Message msg = new Message();
- msg.what = UPDATE_PROGRESS_DLG;
- mSearchProgressHandler.sendMessage(msg);
- }
- }
- }else {
- Message msg = new Message();
- msg.what = END_PROGRESS_DLG;
- mSearchProgressHandler.sendMessage(msg);
- }
- }
初始化菜单 invalidateOptionsMenu();
调用FMRxControls类的public void cancelSearch (int fd)方法
最后调用FMReceiver类的cancelSearchNative()
-
- public void cancelSearch (int fd){
- <strong> FmReceiverJNI.cancelSearchNative(fd);</strong>
- }
最后发送一个mSearchProgressHandler
msg.what = END_PROGRESS_DLG;
mSearchProgressHandler.sendMessage(msg)
删除handler发送消息关闭对话框
- private Handler mSearchProgressHandler = new Handler() {
- public void handleMessage(Message msg) {
- if (msg.what == UPDATE_PROGRESS_DLG) {
- if(mProgressDialog != null) {
- double frequency = mTunedStation.getFrequency() / 1000.0;
- String titleStr = getString(R.string.msg_search_title, ("" + frequency));
- mProgressDialog.setTitle(titleStr);
- }
- }else if (msg.what == END_PROGRESS_DLG) {
- <strong>mSearchProgressHandler.removeMessages(END_PROGRESS_DLG);
- mSearchProgressHandler.removeMessages(UPDATE_PROGRESS_DLG);
- mSearchProgressHandler.removeMessages(TIMEOUT_PROGRESS_DLG);
- removeDialog(DIALOG_PROGRESS_PROGRESS);
- mProgressDialog = null;</strong>
- }else if (msg.what == TIMEOUT_PROGRESS_DLG) {
- cancelSearch();
- }
- }
- };
在搜索中更新FMRadioUI界面的监听类FmRxEventListner.java
- public void startListner (final int fd, final FmRxEvCallbacks cb) {
-
- mThread = new Thread(){
- public void run(){
- byte [] buff = new byte[STD_BUF_SIZE];
- Log.d(TAG, "Starting listener " + fd);
-
- while ((!Thread.currentThread().isInterrupted())) {
-
- try {
- int index = 0;
- int state = 0;
- Arrays.fill(buff, (byte)0x00);
- int freq = 0;
- int eventCount = <strong>FmReceiverJNI.getBufferNative (fd, buff, EVENT_LISTEN);</strong>
-
- if (eventCount >= 0)
- Log.d(TAG, "Received event. Count: " + eventCount);
-
- for ( index = 0; index < eventCount; index++ ) {
- Log.d(TAG, "Received <" +buff[index]+ ">" );
-
- switch(buff[index]){
- case 0:Log.d(TAG, "Got READY_EVENT");
- if(FmTransceiver.getFMPowerState() == FmTransceiver.subPwrLevel_FMRx_Starting) {
-
- FmTransceiver.setFMPowerState(FmTransceiver.FMState_Rx_Turned_On);
- Log.v(TAG, "RxEvtList: CURRENT-STATE : FMRxStarting ---> NEW-STATE : FMRxOn");
- cb.FmRxEvEnableReceiver();
- }
- else if (FmTransceiver.getFMPowerState() == FmTransceiver.subPwrLevel_FMTurning_Off) {
-
- FmTransceiver.setFMPowerState(FmTransceiver.FMState_Turned_Off);
- Log.v(TAG, "RxEvtList: CURRENT-STATE : FMTurningOff ---> NEW-STATE : FMOff");
- FmTransceiver.release("/dev/radio0");
- cb.FmRxEvDisableReceiver();
- Thread.currentThread().interrupt();
- }
- break;case 1:
- Log.d(TAG, "Got TUNE_EVENT");
- <strong>freq = FmReceiverJNI.getFreqNative(fd);</strong>
- state = FmReceiver.getSearchState();
- switch(state) {
- case FmTransceiver.subSrchLevel_SeekInPrg :
- Log.v(TAG, "Current state is " + state);
- FmReceiver.setSearchState(FmTransceiver.subSrchLevel_SrchComplete);
- Log.v(TAG, "RxEvtList: CURRENT-STATE : Search ---> NEW-STATE : FMRxOn");
- <strong> cb.FmRxEvSearchComplete(freq);</strong>
- break;
- default:
- if (freq > 0)
- cb.FmRxEvRadioTuneStatus(freq);
- else
- Log.e(TAG, "get frequency command failed");
- break;
- }
- break;
- case 2:Log.d(TAG, "Got SEEK_COMPLETE_EVENT");
- state = FmReceiver.getSearchState();
- switch(state) {
- case FmTransceiver.subSrchLevel_ScanInProg:
- Log.v(TAG, "Current state is " + state);
- FmReceiver.setSearchState(FmTransceiver.subSrchLevel_SrchComplete);
- Log.v(TAG, "RxEvtList: CURRENT-STATE : Search ---> NEW-STATE : FMRxOn");
- cb.FmRxEvSearchComplete(FmReceiverJNI.getFreqNative(fd));
- break;
- case FmTransceiver.subSrchLevel_SrchAbort:
- Log.v(TAG, "Current state is SRCH_ABORTED");
- Log.v(TAG, "Aborting on-going search command...");
- FmReceiver.setSearchState(FmTransceiver.subSrchLevel_SrchComplete);
- Log.v(TAG, "RxEvtList: CURRENT-STATE : Search ---> NEW-STATE : FMRxOn");
- cb.FmRxEvSearchComplete(FmReceiverJNI.getFreqNative(fd));
- break;
- }
- break;
- case 3:Log.d(TAG, "Got SCAN_NEXT_EVENT");
- cb.FmRxEvSearchInProgress();
- break;
- case 4:
- Log.d(TAG, "Got RAW_RDS_EVENT");
- cb.FmRxEvRdsGroupData();
- break;
- case 5:
- Log.d(TAG, "Got RT_EVENT");
- cb.FmRxEvRdsRtInfo();
- break;
- case 6:
- Log.d(TAG, "Got PS_EVENT");
- cb.FmRxEvRdsPsInfo();
- break;
- case 7:
- Log.d(TAG, "Got ERROR_EVENT");
- break;
- case 8:
- Log.d(TAG, "Got BELOW_TH_EVENT");
- cb.FmRxEvServiceAvailable (false);
- break;
- case 9:Log.d(TAG, "Got ABOVE_TH_EVENT");
- cb.FmRxEvServiceAvailable(true);
- break;
- case 10:
- Log.d(TAG, "Got STEREO_EVENT");
- cb.FmRxEvStereoStatus (true);
- break;
- case 11:
- Log.d(TAG, "Got MONO_EVENT");
- cb.FmRxEvStereoStatus (false);
- break;
- case 12:
- Log.d(TAG, "Got RDS_AVAL_EVENT");
- cb.FmRxEvRdsLockStatus (true);
- break;
- case 13:
- Log.d(TAG, "Got RDS_NOT_AVAL_EVENT");
- cb.FmRxEvRdsLockStatus (false);
- break;
- case 14:Log.d(TAG, "Got NEW_SRCH_LIST");
- state = FmReceiver.getSearchState();
- switch(state) {
- case FmTransceiver.subSrchLevel_SrchListInProg:
- Log.v(TAG, "FmRxEventListener: Current state is AUTO_PRESET_INPROGRESS");
- FmReceiver.setSearchState(FmTransceiver.subSrchLevel_SrchComplete);
- Log.v(TAG, "RxEvtList: CURRENT-STATE : Search ---> NEW-STATE : FMRxOn");
- cb.FmRxEvSearchListComplete ();
- break;
- case FmTransceiver.subSrchLevel_SrchAbort:
- Log.v(TAG, "Current state is SRCH_ABORTED");
- Log.v(TAG, "Aborting on-going SearchList command...");
- FmReceiver.setSearchState(FmTransceiver.subSrchLevel_SrchComplete);
- Log.v(TAG, "RxEvtList: CURRENT-STATE : Search ---> NEW-STATE : FMRxOn");
- cb.FmRxEvSearchCancelled();
- break;
- }
- break;
- case 15:Log.d(TAG, "Got NEW_AF_LIST");
- cb.FmRxEvRdsAfInfo();
- break;
- case 18:
- Log.d(TAG, "Got RADIO_DISABLED");
- if (FmTransceiver.getFMPowerState() == FmTransceiver.subPwrLevel_FMTurning_Off) {
-
- FmTransceiver.setFMPowerState(FmTransceiver.FMState_Turned_Off);
- Log.v(TAG, "RxEvtList: CURRENT-STATE : FMTurningOff ---> NEW-STATE : FMOff");
- FmTransceiver.release("/dev/radio0");
- cb.FmRxEvDisableReceiver();
- Thread.currentThread().interrupt();
- } else {
- Log.d(TAG, "Unexpected RADIO_DISABLED recvd");
- cb.FmRxEvRadioReset();
- }
- break;
- case 19:FmTransceiver.setRDSGrpMask(0);
- break;
- case 20:
- Log.d(TAG, "got RT plus event");
- cb.FmRxEvRTPlus();
- break;
- case 21:
- Log.d(TAG, "got eRT event");
- cb.FmRxEvERTInfo();
- break;
- default:
- Log.d(TAG, "Unknown event");
- break;
- }
- }
- } catch ( Exception ex ) {
- Log.d( TAG, "RunningThread InterruptedException");
- ex.printStackTrace();
- Thread.currentThread().interrupt();
- }
- }
- }
- };
- mThread.start();
- }
Switch case取1的时候就FMReceiverJNI类中获取频率,调FmRxEvRadioTuneStatus接收读取频率
freq= FmReceiverJNI.getFreqNative(fd);
cb.FmRxEvRadioTuneStatus(freq);
将频率保存起来
FmSharedPreferences.setTunedFrequency(frequency);
mPrefs.Save();
清除状态信息 clearStationInfo();
调用改变界面状态 mCallbacks.onTuneStatusChanged();
可用存储,设置可用模拟器 enableStereo(FmSharedPreferences.getAudioOutputMode());
- public void <strong>FmRxEvRadioTuneStatus</strong>(int frequency)
- {
- Log.d(LOGTAG, "FmRxEvRadioTuneStatus: Tuned Frequency: " +frequency);
- try
- {
- <strong>FmSharedPreferences.setTunedFrequency(frequency);
- mPrefs.Save();</strong>
-
-
- if(mReceiver != null) {
- <strong> clearStationInfo();</strong>
- }
- if(mCallbacks != null)
- {
- <strong> mCallbacks.onTuneStatusChanged();</strong>
- }
-
- startNotification();
- enableStereo(FmSharedPreferences.getAudioOutputMode());
- }
- catch (RemoteException e)
- {
- e.printStackTrace();
- }
- }
最后调到底层
FmReceiverJNI.setMonoStereoNative (fd, 1)
-
- public int stereoControl(int fd, boolean stereo) {
-
- if (stereo){
- return FmReceiverJNI.setMonoStereoNative (fd, 1);
- }
- else {
- return FmReceiverJNI.setMonoStereoNative (fd, 0);
- }
-
- }
通过mCallbacks.onTuneStatusChanged();调用到FMRadio.java的内部存根类IFMRadioServiceCallbacks.stub类的public void onTuneStatusChanged()方法进行存入fm频率,数据最后调用FMRadio的resetFMStationInfoUI()刷新UI
- public void <strong>onTuneStatusChanged() </strong> {
- Log.d(LOGTAG, "mServiceCallbacks.onTuneStatusChanged: ");
- if (mIsScaning) {
- Log.d(LOGTAG, "isScanning....................");
- SharedPreferences sp = getSharedPreferences(SCAN_STATION_PREFS_NAME, 0);
- SharedPreferences.Editor editor = sp.edit();
- int station_number = sp.getInt(NUM_OF_STATIONS, 0);
- station_number++;
- editor.putInt(NUM_OF_STATIONS, station_number);
- editor.putString(STATION_NAME + station_number, station_number + "");
- editor.putInt(STATION_FREQUENCY + station_number,
- FmSharedPreferences.getTunedFrequency());
- editor.commit();
- }
- <strong>cleanupTimeoutHandler();
- mHandler.post(mUpdateStationInfo);
- mHandler.post(mOnStereo);</strong>
- }
发送一handler跟新UI,调用此回调方法Runnable mUpdateStationInfo = new Runnable()
- Runnable mUpdateStationInfo = new Runnable() {
- public void run() {
- cleanupTimeoutHandler();
- PresetStation station = new PresetStation("", FmSharedPreferences.getTunedFrequency());
- if (station != null) {
- mTunedStation.Copy(station);
- }
- <strong>updateSearchProgress();
- resetFMStationInfoUI();</strong>
- }
- };
updateStationInfoToUI();
- private void <strong>updateStationInfoToUI()</strong> {
- double frequency = mTunedStation.getFrequency() / 1000.0;
- mTuneStationFrequencyTV.setText("" + frequency + "MHz");
- if ((mPicker != null) && mUpdatePickerValue) {
- mPicker.setValue(((mTunedStation.getFrequency() - mPrefs.getLowerLimit())
- / mPrefs.getFrequencyStepSize()));
- }
- mStationCallSignTV.setText(mTunedStation.getPIString());
- mProgramTypeTV.setText(mTunedStation.getPtyString());
- mRadioTextTV.setText("");
- mERadioTextTV.setText("");
- mRadioTextScroller.mOriginalString = "";
- mRadioTextScroller.mStringlength = 0;
- mRadioTextScroller.mIteration = 0;
- mERadioTextScroller.mOriginalString = "";
- mERadioTextScroller.mStringlength = 0;
- mERadioTextScroller.mIteration = 0;
- mProgramServiceTV.setText("");
- mStereoTV.setText("");
- setupPresetLayout();
- }
FM启动和关闭搜索都是通过JNI调到底层实现,代码路径是:vendor\qcom\opensource\fm\jni
android_hardware_fm.cpp
-
-
-
- static JNINativeMethod gMethods[] = {
-
- { "acquireFdNative", "(Ljava/lang/String;)I",
- (void*)android_hardware_fmradio_FmReceiverJNI_acquireFdNative},
- { "closeFdNative", "(I)I",
- (void*)android_hardware_fmradio_FmReceiverJNI_closeFdNative},
- { "getFreqNative", "(I)I",
- (void*)android_hardware_fmradio_FmReceiverJNI_getFreqNative},
- { "setFreqNative", "(II)I",
- (void*)android_hardware_fmradio_FmReceiverJNI_setFreqNative},
- { "getControlNative", "(II)I",
- (void*)android_hardware_fmradio_FmReceiverJNI_getControlNative},
- { "setControlNative", "(III)I",
- (void*)android_hardware_fmradio_FmReceiverJNI_setControlNative},
- { "startSearchNative", "(II)I",
- (void*)android_hardware_fmradio_FmReceiverJNI_startSearchNative},
- { "cancelSearchNative", "(I)I",
- (void*)android_hardware_fmradio_FmReceiverJNI_cancelSearchNative}, { "getRSSINative", "(I)I",
- (void*)android_hardware_fmradio_FmReceiverJNI_getRSSINative},
- { "setBandNative", "(III)I",
- (void*)android_hardware_fmradio_FmReceiverJNI_setBandNative},
- { "getLowerBandNative", "(I)I",
- (void*)android_hardware_fmradio_FmReceiverJNI_getLowerBandNative},
- { "getUpperBandNative", "(I)I",
- (void*)android_hardware_fmradio_FmReceiverJNI_getUpperBandNative},
- { "getBufferNative", "(I[BI)I",
- (void*)android_hardware_fmradio_FmReceiverJNI_getBufferNative},
- { "setMonoStereoNative", "(II)I",
- (void*)android_hardware_fmradio_FmReceiverJNI_setMonoStereoNative},
- { "getRawRdsNative", "(I[BI)I",
- (void*)android_hardware_fmradio_FmReceiverJNI_getRawRdsNative},
- { "setNotchFilterNative", "(IIZ)I",
- (void*)android_hardware_fmradio_FmReceiverJNI_setNotchFilterNative},
- { "startRTNative", "(ILjava/lang/String;I)I",
- (void*)android_hardware_fmradio_FmReceiverJNI_startRTNative},
- { "stopRTNative", "(I)I",
- (void*)android_hardware_fmradio_FmReceiverJNI_stopRTNative},
- { "startPSNative", "(ILjava/lang/String;I)I",
- (void*)android_hardware_fmradio_FmReceiverJNI_startPSNative}, { "stopPSNative", "(I)I",
- (void*)android_hardware_fmradio_FmReceiverJNI_stopPSNative},
- { "setPTYNative", "(II)I",
- (void*)android_hardware_fmradio_FmReceiverJNI_setPTYNative},
- { "setPINative", "(II)I",
- (void*)android_hardware_fmradio_FmReceiverJNI_setPINative},
- { "setPSRepeatCountNative", "(II)I",
- (void*)android_hardware_fmradio_FmReceiverJNI_setPSRepeatCountNative},
- { "setTxPowerLevelNative", "(II)I",
- (void*)android_hardware_fmradio_FmReceiverJNI_setTxPowerLevelNative},
- { "setAnalogModeNative", "(Z)I",
- (void*)android_hardware_fmradio_FmReceiverJNI_setAnalogModeNative},
- { "SetCalibrationNative", "(I)I",
- (void*)android_hardware_fmradio_FmReceiverJNI_SetCalibrationNative},
- { "configureSpurTable", "(I)I",
- (void*)android_hardware_fmradio_FmReceiverJNI_configureSpurTable},
-
- };
上面写明了从jni的调用关系。具体的函数实现,请到Android_hardware_fm.cpp中去查看