zoukankan      html  css  js  c++  java
  • Android FM模块学习之二 FM搜索频率流程

    转自:http://blog.csdn.net/tfslovexizi/article/details/41315483

    上一篇大概分析了一下FM启动流程,若不了解Fm启动流程的,可以去打开前面的链接先了解FM启动流程,接下来我们简单分析一下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()

    1. private Dialog <strong>createProgressDialog</strong>(int id) {  
    2.       String msgStr = "";  
    3.       String titleStr = "";  
    4.       String []items;  
    5.       double frequency = mTunedStation.getFrequency() / 1000.0;  
    6.       boolean bSearchActive = false;  
    7.   
    8.       if (isSeekActive()) {  
    9.           msgStr = getString(R.string.msg_seeking);  
    10.           bSearchActive = true;  
    11.       }else if (isScanActive()) {  
    12.           if(FmSharedPreferences.isRBDSStd()) {<span style="font-family:KaiTi_GB2312;">//标准耳机</span>  
    13.                 items = getResources().  
    14.                          getStringArray(R.array.search_category_rbds_entries);  
    15.           }else { // if(FmSharedPreferences.isRDSStd())  
    16.                 items = getResources().  
    17.                          getStringArray(R.array.search_category_rds_entries);  
    18.           }String ptyStr = "";  
    19.           if (items.length > mScanPtyIndex)  
    20.               ptyStr = items[mScanPtyIndex];  
    21.           if (!TextUtils.isEmpty(ptyStr)) {  
    22.              msgStr = getString(R.string.msg_scanning_pty, ptyStr);  
    23.           }else {  
    24.              Log.d(LOGTAG, "pty is null ");  
    25.              msgStr = getString(R.string.msg_scanning);  
    26.           }  
    27.           titleStr = getString(R.string.msg_search_title, ("" + frequency));  
    28.           bSearchActive=true;  
    29.       }else if (isSearchActive()) {  
    30.          msgStr = getString(R.string.msg_searching);  
    31.          titleStr = getString(R.string.msg_searching_title);  
    32.          bSearchActive = true;  
    33.       }  
    34.       if (bSearchActive) {mProgressDialog = new ProgressDialog(FMRadio.this);  
    35.           if (mProgressDialog != null) {  
    36.               mProgressDialog.setTitle(titleStr);  
    37.               mProgressDialog.setMessage(msgStr);  
    38.               mProgressDialog.setIcon(R.drawable.ic_launcher_fmradio);  
    39.               mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);  
    40.               mProgressDialog.setCanceledOnTouchOutside(false);  
    41.               mProgressDialog.setButton(DialogInterface.BUTTON_POSITIVE,  
    42.                                    getText(R.string.button_text_stop),  
    43.                new DialogInterface.OnClickListener() {  
    44.                   public void onClick(DialogInterface dialog, int whichButton) {  
    45.                       <strong>cancelSearch();</strong>  
    46.                   }  
    47.               });  
    48.               mProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() { public void onCancel(DialogInterface dialog) {  
    49.                    cancelSearch();  
    50.                 }  
    51.               });  
    52.               mProgressDialog.setOnKeyListener(new OnKeyListener() {  
    53.                 public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {  
    54.                     Log.d(LOGTAG, "OnKeyListener event received in ProgressDialog" + keyCode);  
    55.                     switch (keyCode) {  
    56.                         case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:  
    57.                         case 126: //KeyEvent.KEYCODE_MEDIA_PLAY:  
    58.                         case 127: //KeyEvent.KEYCODE_MEDIA_PAUSE:  
    59.                         case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:  
    60.                         case KeyEvent.KEYCODE_MEDIA_NEXT:  
    61.                         case KeyEvent.KEYCODE_MEDIA_PREVIOUS:  
    62.                         case KeyEvent.KEYCODE_MEDIA_REWIND:  
    63.                         case KeyEvent.KEYCODE_MEDIA_STOP:  
    64.                             return true;  
    65.                     } return false;  
    66.                 }  
    67.             });  
    68.           }  
    69.           Message msg = new Message();  
    70.           msg.what = TIMEOUT_PROGRESS_DLG;  
    71.           mSearchProgressHandler.sendMessageDelayed(msg, SHOWBUSY_TIMEOUT);  
    72.       }  
    73.       return mProgressDialog;  
    74.    }  

    调用FMRadioService类中的Scan()方法扫描

    调用 FMReceiver的searchStations()方法进行扫描

    1. public boolean<strong> scan(int pty)</strong>  
    2.    {  
    3.       boolean bCommandSent=false;  
    4.       if (mReceiver != null)  
    5.       {  
    6.          Log.d(LOGTAG, "scan:  PTY: " + pty);  
    7.          if(FmSharedPreferences.isRBDSStd())  
    8.          {  
    9.             /* RBDS : Validate PTY value?? */  
    10.             if( ((pty  > 0) && (pty  <= 23)) || ((pty  >= 29) && (pty  <= 31)) )  
    11.             {bCommandSent = <strong>mReceiver.searchStations</strong>(FmReceiver.FM_RX_SRCHRDS_MODE_SCAN_PTY,  
    12.                                                        FmReceiver.FM_RX_DWELL_PERIOD_2S,  
    13.                                                        FmReceiver.FM_RX_SEARCHDIR_UP,  
    14.                                                        pty,  
    15.                                                        0);  
    16.             }  
    17.             else  
    18.             {  
    19.                bCommandSent = <strong>mReceiver.searchStations</strong>(FmReceiver.FM_RX_SRCH_MODE_SCAN,  
    20.                                                 FmReceiver.FM_RX_DWELL_PERIOD_2S,  
    21.                                                 FmReceiver.FM_RX_SEARCHDIR_UP);  
    22.             }}  
    23.          else  
    24.          {  
    25.             /* RDS : Validate PTY value?? */  
    26.             if( (pty  > 0) && (pty  <= 31) )  
    27.             {  
    28.                bCommandSent = <strong>mReceiver.searchStations</strong>(FmReceiver.FM_RX_SRCHRDS_MODE_SCAN_PTY,  
    29.                                                           FmReceiver.FM_RX_DWELL_PERIOD_2S,  
    30.                                                           FmReceiver.FM_RX_SEARCHDIR_UP,  
    31.                                                           pty,  
    32.                                                           0);  
    33.             }  
    34.             else{  
    35.                bCommandSent =<strong> mReceiver.searchStations</strong>(FmReceiver.FM_RX_SRCH_MODE_SCAN,  
    36.                                                 FmReceiver.FM_RX_DWELL_PERIOD_2S,  
    37.                                                 FmReceiver.FM_RX_SEARCHDIR_UP);  
    38.             }  
    39.          }  
    40.       }  
    41.       return bCommandSent;  
    42.    }  

    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);

    1. public boolean <strong>searchStations </strong>(int mode,  
    2.                                   int dwellPeriod,  
    3.                                   int direction){  
    4.   
    5.      <strong> int state = getFMState();</strong>//<span style="font-family:KaiTi_GB2312;font-size:18px;">获得FMState状态</span>  
    6.       boolean bStatus = true;  
    7.       int re;  
    8.   
    9.       /* Check current state of FM device */  
    10.       if (state == FMState_Turned_Off || state == FMState_Srch_InProg) {  
    11.           Log.d(TAG, "searchStations: Device currently busy in executing another command.");  
    12.           return false;  
    13.       }  
    14.   
    15.       Log.d (TAG, "Basic search...");  
    16.       /* Validate the arguments */  
    17.       if ( (mode != FM_RX_SRCH_MODE_SEEK) &&  
    18.            (mode != FM_RX_SRCH_MODE_SCAN))  
    19.       {  
    20.          Log.d (TAG, "Invalid search mode: " + mode );  
    21.          bStatus = false;  
    22.       }  
    23.       if ( (dwellPeriod < FM_RX_DWELL_PERIOD_0S ) ||  
    24.            (dwellPeriod > FM_RX_DWELL_PERIOD_7S))  
    25.       {  
    26.          Log.d (TAG, "Invalid dwelling time: " + dwellPeriod);  
    27.          bStatus = false;  
    28.       }  
    29.       if ( (direction != FM_RX_SEARCHDIR_DOWN) &&  
    30.            (direction != FM_RX_SEARCHDIR_UP))  
    31.       {  
    32.          Log.d (TAG, "Invalid search direction: " + direction);  
    33.          bStatus = false;  
    34.       }  
    35.       if (bStatus)  
    36.       {  
    37.          Log.d (TAG, "searchStations: mode " + mode + "direction:  " + direction);  
    38.   
    39.          if (mode == FM_RX_SRCH_MODE_SEEK)  
    40.              setSearchState(subSrchLevel_SeekInPrg);  
    41.          else if (mode == FM_RX_SRCH_MODE_SCAN)  
    42.              setSearchState(subSrchLevel_ScanInProg);  
    43.          Log.v(TAG, "searchStations: CURRENT-STATE : FMRxOn ---> NEW-STATE : SearchInProg");  
    44.   
    45.         <strong> re = mControl.searchStations(sFd, mode, dwellPeriod, direction, 0, 0);</strong>  
    46.          if (re != 0) {  
    47.              Log.e(TAG, "search station failed");  
    48.              if (getFMState() == FMState_Srch_InProg)  
    49.                  setSearchState(subSrchLevel_SrchComplete);  
    50.              return false;  
    51.          }         state = getFMState();  
    52.          if (state == FMState_Turned_Off) {  
    53.              Log.d(TAG, "searchStations: CURRENT-STATE : FMState_Off (unexpected)");  
    54.              return false;  
    55.          }  
    56.       }  
    57.       return bStatus;  
    58.    }  

    设置FM搜索电源状态

    1. static void <strong>setSearchState</strong>(int state)  
    2.    {  
    3.       mSearchState = state;  
    4.       switch(mSearchState) {  
    5.          case subSrchLevel_SeekInPrg:  
    6.          case subSrchLevel_ScanInProg:  
    7.          case subSrchLevel_SrchListInProg:  
    8.             setFMPowerState(FMState_Srch_InProg);  
    9.             break;  
    10.          case subSrchLevel_SrchComplete:  
    11.             /* Update the state of the FM device */  
    12.             mSearchState = subSrchLevel_NoSearch;  
    13.             setFMPowerState(FMState_Rx_Turned_On);  
    14.             break;  
    15.          case subSrchLevel_SrchAbort:  
    16.             break;  
    17.          default:  
    18.             mSearchState = subSrchLevel_NoSearch;  
    19.             break;  
    20.       }  
    21.    }  

    setFMPowerState(FMState_Rx_Turned_On); 是调用FmTransceiver类发射器类,FM电源状态

    1. /*============================================================== 
    2.    FUNCTION:  setFMPowerState 
    3.    ==============================================================*/  
    4.    /** 
    5.    *    Sets the FM power state 
    6.    * 
    7.    *    <p> 
    8.    *    This method sets the FM power state. 
    9.    * 
    10.    *    <p> 
    11.    */  
    12.    static void <strong>setFMPowerState(</strong>int state)  
    13.    {  
    14.       FMState = state;  
    15.    }  

    调用FMRxControls.java类的

    / * 配置各种搜索参数,开始搜索* /

     public int searchStations (int fd, int mode,int dwell, int dir, int pty, int pi)

    设置一些参数

    FmReceiverJNI.setControlNative();

    设置的搜索模式

    设置扫描居住的时间

    设置的企业

    设置PI

    1. /* configure various search parameters and start search */  
    2.    public int <strong>searchStations </strong>(int fd, int mode, int dwell,  
    3.                                int dir, int pty, int pi){  
    4.       int re = 0;  
    5.   
    6.   
    7.       Log.d(TAG, "Mode is " + mode + " Dwell is " + dwell);  
    8.       Log.d(TAG, "dir is "  + dir + " PTY is " + pty);  
    9.       Log.d(TAG, "pi is " + pi + " id " +  V4L2_CID_PRIVATE_TAVARUA_SRCHMODE);  
    10.   
    11.   
    12.   
    13.      <strong> re = FmReceiverJNI.setControlNative (fd, V4L2_CID_PRIVATE_TAVARUA_SRCHMODE, mode);</strong>  
    14.       if (re != 0) {  
    15.           Log.e(TAG, "setting of search mode failed");  
    16.           return re;  
    17.       }  
    18.       <strong>re = FmReceiverJNI.setControlNative (fd, V4L2_CID_PRIVATE_TAVARUA_SCANDWELL, dwell);</strong>  
    19.       if (re != 0) {  
    20.           Log.e(TAG, "setting of scan dwell time failed");  
    21.           return re;  
    22.       }  
    23.       if (pty != 0)  
    24.       {  re = FmReceiverJNI.setControlNative (fd, V4L2_CID_PRIVATE_TAVARUA_SRCH_PTY, pty);  
    25.          if (re != 0) {  
    26.              Log.e(TAG, "setting of PTY failed");  
    27.              return re;  
    28.          }  
    29.       }  
    30.   
    31.       if (pi != 0)  
    32.       {  
    33.         <strong> re = FmReceiverJNI.setControlNative (fd, V4L2_CID_PRIVATE_TAVARUA_SRCH_PI, pi);</strong>  
    34.          if (re != 0) {  
    35.              Log.e(TAG, "setting of PI failed");  
    36.              return re;  
    37.          }  
    38.       }  
    39.   
    40.       <strong>re = FmReceiverJNI.startSearchNative (fd, dir );</strong>  
    41.       return re;  
    42.    }  

    启动搜索 FmReceiverJNI.startSearchNative (fd, dir );

    关闭搜索

    FMRadio 调用 FMRadioService 的CancelSearch()方法

    public boolean cancelSearch()

    1. public boolean <strong>cancelSearch()</strong>  
    2.    {  
    3.       boolean bCommandSent=false;  
    4.       if (mReceiver != null)  
    5.       {  
    6.          Log.d(LOGTAG, "cancelSearch");  
    7.          bCommandSent = <strong>mReceiver.cancelSearch();</strong>  
    8.       }  
    9.       return bCommandSent;  
    10.    }  

    调用FRReceiver的cancelSearch()

    mReceiver.cancelSearch()

    更新搜索 FMRadio.java中

    updateSearchProgress();

    1. private void <strong>updateSearchProgress()</strong> {  
    2.       boolean searchActive = isScanActive() || isSeekActive() || isSearchActive();  
    3.       if (searchActive) {  
    4.          synchronized (this) {  
    5.             if(mProgressDialog == null) {  
    6.                showDialog(DIALOG_PROGRESS_PROGRESS);  
    7.             }else {  
    8.                Message msg = new Message();  
    9.                msg.what = UPDATE_PROGRESS_DLG;  
    10.                mSearchProgressHandler.sendMessage(msg);  
    11.             }  
    12.          }  
    13.       }else {  
    14.          Message msg = new Message();  
    15.          msg.what = END_PROGRESS_DLG;  
    16.          mSearchProgressHandler.sendMessage(msg);  
    17.       }  
    18.    }  


    初始化菜单  invalidateOptionsMenu();

    调用FMRxControls类的public void cancelSearch (int fd)方法

    最后调用FMReceiver类的cancelSearchNative()

    1. /* cancel search in progress */  
    2.    public void cancelSearch (int fd){  
    3.      <strong> FmReceiverJNI.cancelSearchNative(fd);</strong>  
    4.    }  

    最后发送一个mSearchProgressHandler

      msg.what = END_PROGRESS_DLG;

      mSearchProgressHandler.sendMessage(msg)

    删除handler发送消息关闭对话框

    1. private Handler mSearchProgressHandler = new Handler() {  
    2.        public void handleMessage(Message msg) {  
    3.            if (msg.what == UPDATE_PROGRESS_DLG) {  
    4.               if(mProgressDialog != null) {  
    5.                  double frequency = mTunedStation.getFrequency() / 1000.0;  
    6.                  String titleStr = getString(R.string.msg_search_title, ("" + frequency));  
    7.                  mProgressDialog.setTitle(titleStr);  
    8.               }  
    9.            }else if (msg.what == END_PROGRESS_DLG) {  
    10.               <strong>mSearchProgressHandler.removeMessages(END_PROGRESS_DLG);  
    11.               mSearchProgressHandler.removeMessages(UPDATE_PROGRESS_DLG);  
    12.               mSearchProgressHandler.removeMessages(TIMEOUT_PROGRESS_DLG);  
    13.               removeDialog(DIALOG_PROGRESS_PROGRESS);  
    14.               mProgressDialog = null;</strong>  
    15.            }else if (msg.what == TIMEOUT_PROGRESS_DLG) {  
    16.               cancelSearch();  
    17.            }  
    18.        }  
    19.    };  

    在搜索中更新FMRadioUI界面的监听类FmRxEventListner.java

    1. public void startListner (final int fd, final FmRxEvCallbacks cb) {  
    2.        /* start a thread and listen for messages */  
    3.        mThread = new Thread(){  
    4.            public void run(){  
    5.                byte [] buff = new byte[STD_BUF_SIZE];  
    6.                Log.d(TAG, "Starting listener " + fd);  
    7.   
    8.                while ((!Thread.currentThread().isInterrupted())) {  
    9.   
    10.                    try {  
    11.                        int index = 0;  
    12.                        int state = 0;  
    13.                        Arrays.fill(buff, (byte)0x00);  
    14.                        int freq = 0;  
    15.                        int eventCount = <strong>FmReceiverJNI.getBufferNative (fd, buff, EVENT_LISTEN);</strong>  
    16.   
    17.                        if (eventCount >= 0)  
    18.                            Log.d(TAG, "Received event. Count: " + eventCount);  
    19.   
    20.                        for (  index = 0; index < eventCount; index++ ) {  
    21.                            Log.d(TAG, "Received <" +buff[index]+ ">" );  
    22.   
    23.                            switch(buff[index]){  
    24.                            case 0:Log.d(TAG, "Got READY_EVENT");  
    25.                                if(FmTransceiver.getFMPowerState() == FmTransceiver.subPwrLevel_FMRx_Starting) {  
    26.                                    /*Set the state as FMRxOn */  
    27.                                    FmTransceiver.setFMPowerState(FmTransceiver.FMState_Rx_Turned_On);  
    28.                                    Log.v(TAG, "RxEvtList: CURRENT-STATE : FMRxStarting ---> NEW-STATE : FMRxOn");  
    29.                                    cb.FmRxEvEnableReceiver();  
    30.                                }  
    31.                                else if (FmTransceiver.getFMPowerState() == FmTransceiver.subPwrLevel_FMTurning_Off) {  
    32.                                    /*Set the state as FMOff */  
    33.                                    FmTransceiver.setFMPowerState(FmTransceiver.FMState_Turned_Off);  
    34.                                    Log.v(TAG, "RxEvtList: CURRENT-STATE : FMTurningOff ---> NEW-STATE : FMOff");  
    35.                                    FmTransceiver.release("/dev/radio0");  
    36.                                    cb.FmRxEvDisableReceiver();  
    37.                                    Thread.currentThread().interrupt();  
    38.                                }  
    39.                                break;case 1:  
    40.                                Log.d(TAG, "Got TUNE_EVENT");  
    41.                                <strong>freq = FmReceiverJNI.getFreqNative(fd);</strong>  
    42.                                state = FmReceiver.getSearchState();  
    43.                                switch(state) {  
    44.                                   case FmTransceiver.subSrchLevel_SeekInPrg :  
    45.                                        Log.v(TAG, "Current state is " + state);  
    46.                                        FmReceiver.setSearchState(FmTransceiver.subSrchLevel_SrchComplete);  
    47.                                        Log.v(TAG, "RxEvtList: CURRENT-STATE : Search ---> NEW-STATE : FMRxOn");  
    48.                                       <strong> cb.FmRxEvSearchComplete(freq);</strong>  
    49.                                        break;  
    50.                                   default:  
    51.                                        if (freq > 0)  
    52.                                            cb.FmRxEvRadioTuneStatus(freq);  
    53.                                        else  
    54.                                            Log.e(TAG, "get frequency command failed");  
    55.                                        break;  
    56.                                }  
    57.                                break;  
    58.                            case 2:Log.d(TAG, "Got SEEK_COMPLETE_EVENT");  
    59.                                state = FmReceiver.getSearchState();  
    60.                                switch(state) {  
    61.                                   case FmTransceiver.subSrchLevel_ScanInProg:  
    62.                                      Log.v(TAG, "Current state is " + state);  
    63.                                      FmReceiver.setSearchState(FmTransceiver.subSrchLevel_SrchComplete);  
    64.                                      Log.v(TAG, "RxEvtList: CURRENT-STATE : Search ---> NEW-STATE : FMRxOn");  
    65.                                      cb.FmRxEvSearchComplete(FmReceiverJNI.getFreqNative(fd));  
    66.                                      break;  
    67.                                   case FmTransceiver.subSrchLevel_SrchAbort:  
    68.                                      Log.v(TAG, "Current state is SRCH_ABORTED");  
    69.                                      Log.v(TAG, "Aborting on-going search command...");  
    70.                                      FmReceiver.setSearchState(FmTransceiver.subSrchLevel_SrchComplete);  
    71.                                      Log.v(TAG, "RxEvtList: CURRENT-STATE : Search ---> NEW-STATE : FMRxOn");  
    72.                                      cb.FmRxEvSearchComplete(FmReceiverJNI.getFreqNative(fd));  
    73.                                      break;  
    74.                                }  
    75.                                break;  
    76.                            case 3:Log.d(TAG, "Got SCAN_NEXT_EVENT");  
    77.                                cb.FmRxEvSearchInProgress();  
    78.                                break;  
    79.                            case 4:  
    80.                                Log.d(TAG, "Got RAW_RDS_EVENT");  
    81.                                cb.FmRxEvRdsGroupData();  
    82.                                break;  
    83.                            case 5:  
    84.                                Log.d(TAG, "Got RT_EVENT");  
    85.                                cb.FmRxEvRdsRtInfo();  
    86.                                break;  
    87.                            case 6:  
    88.                                Log.d(TAG, "Got PS_EVENT");  
    89.                                cb.FmRxEvRdsPsInfo();  
    90.                                break;  
    91.                            case 7:  
    92.                                Log.d(TAG, "Got ERROR_EVENT");  
    93.                                break;  
    94.                            case 8:  
    95.                                Log.d(TAG, "Got BELOW_TH_EVENT");  
    96.                                cb.FmRxEvServiceAvailable (false);  
    97.                                break;  
    98.                            case 9:Log.d(TAG, "Got ABOVE_TH_EVENT");  
    99.                                cb.FmRxEvServiceAvailable(true);  
    100.                                break;  
    101.                            case 10:  
    102.                                Log.d(TAG, "Got STEREO_EVENT");  
    103.                                cb.FmRxEvStereoStatus (true);  
    104.                                break;  
    105.                            case 11:  
    106.                                Log.d(TAG, "Got MONO_EVENT");  
    107.                                cb.FmRxEvStereoStatus (false);  
    108.                                break;  
    109.                            case 12:  
    110.                                Log.d(TAG, "Got RDS_AVAL_EVENT");  
    111.                                cb.FmRxEvRdsLockStatus (true);  
    112.                                break;  
    113.                            case 13:  
    114.                                Log.d(TAG, "Got RDS_NOT_AVAL_EVENT");  
    115.                                cb.FmRxEvRdsLockStatus (false);  
    116.                                break;  
    117.                            case 14:Log.d(TAG, "Got NEW_SRCH_LIST");  
    118.                                state = FmReceiver.getSearchState();  
    119.                                switch(state) {  
    120.                                   case FmTransceiver.subSrchLevel_SrchListInProg:  
    121.                                      Log.v(TAG, "FmRxEventListener: Current state is AUTO_PRESET_INPROGRESS");  
    122.                                      FmReceiver.setSearchState(FmTransceiver.subSrchLevel_SrchComplete);  
    123.                                      Log.v(TAG, "RxEvtList: CURRENT-STATE : Search ---> NEW-STATE : FMRxOn");  
    124.                                      cb.FmRxEvSearchListComplete ();  
    125.                                      break;  
    126.                                   case FmTransceiver.subSrchLevel_SrchAbort:  
    127.                                      Log.v(TAG, "Current state is SRCH_ABORTED");  
    128.                                      Log.v(TAG, "Aborting on-going SearchList command...");  
    129.                                      FmReceiver.setSearchState(FmTransceiver.subSrchLevel_SrchComplete);  
    130.                                      Log.v(TAG, "RxEvtList: CURRENT-STATE : Search ---> NEW-STATE : FMRxOn");  
    131.                                      cb.FmRxEvSearchCancelled();  
    132.                                      break;  
    133.                                }  
    134.                                break;  
    135.                            case 15:Log.d(TAG, "Got NEW_AF_LIST");  
    136.                                cb.FmRxEvRdsAfInfo();  
    137.                                break;  
    138.                            case 18:  
    139.                                Log.d(TAG, "Got RADIO_DISABLED");  
    140.                                if (FmTransceiver.getFMPowerState() == FmTransceiver.subPwrLevel_FMTurning_Off) {  
    141.                                    /*Set the state as FMOff */  
    142.                                    FmTransceiver.setFMPowerState(FmTransceiver.FMState_Turned_Off);  
    143.                                    Log.v(TAG, "RxEvtList: CURRENT-STATE : FMTurningOff ---> NEW-STATE : FMOff");  
    144.                                    FmTransceiver.release("/dev/radio0");  
    145.                                    cb.FmRxEvDisableReceiver();  
    146.                                    Thread.currentThread().interrupt();  
    147.                                } else {  
    148.                                    Log.d(TAG, "Unexpected RADIO_DISABLED recvd");  
    149.                                    cb.FmRxEvRadioReset();  
    150.                                }  
    151.                                break;  
    152.                            case 19:FmTransceiver.setRDSGrpMask(0);  
    153.                                break;  
    154.                            case 20:  
    155.                                Log.d(TAG, "got RT plus event");  
    156.                                cb.FmRxEvRTPlus();  
    157.                                break;  
    158.                            case 21:  
    159.                                Log.d(TAG, "got eRT event");  
    160.                                cb.FmRxEvERTInfo();  
    161.                                break;  
    162.                            default:  
    163.                                Log.d(TAG, "Unknown event");  
    164.                                break;  
    165.                            }  
    166.                        }//end of for  
    167.                    } catch ( Exception ex ) {  
    168.                        Log.d( TAG,  "RunningThread InterruptedException");  
    169.                        ex.printStackTrace();  
    170.                        Thread.currentThread().interrupt();  
    171.                    }  
    172.                }  
    173.            }  
    174.        };  
    175.        mThread.start();  
    176.    }  

    Switch case取1的时候就FMReceiverJNI类中获取频率,调FmRxEvRadioTuneStatus接收读取频率 

    freq= FmReceiverJNI.getFreqNative(fd);

     cb.FmRxEvRadioTuneStatus(freq);

    将频率保存起来

    FmSharedPreferences.setTunedFrequency(frequency);

               mPrefs.Save();

    清除状态信息 clearStationInfo();

    调用改变界面状态 mCallbacks.onTuneStatusChanged();

    可用存储,设置可用模拟器 enableStereo(FmSharedPreferences.getAudioOutputMode());

    1. public void <strong>FmRxEvRadioTuneStatus</strong>(int frequency)  
    2.       {  
    3.          Log.d(LOGTAG, "FmRxEvRadioTuneStatus: Tuned Frequency: " +frequency);  
    4.          try  
    5.          {  
    6.             <strong>FmSharedPreferences.setTunedFrequency(frequency);  
    7.             mPrefs.Save();</strong>  
    8.             //Log.d(LOGTAG, "Call mCallbacks.onTuneStatusChanged");  
    9.             /* Since the Tuned Status changed, clear out the RDSData cached */  
    10.             if(mReceiver != null) {  
    11.               <strong> clearStationInfo();</strong>  
    12.             }  
    13.             if(mCallbacks != null)  
    14.             {  
    15.               <strong> mCallbacks.onTuneStatusChanged();</strong>  
    16.             }  
    17.             /* Update the frequency in the StatusBar's Notification */  
    18.             startNotification();  
    19.             enableStereo(FmSharedPreferences.getAudioOutputMode());  
    20.          }  
    21.          catch (RemoteException e)  
    22.          {  
    23.             e.printStackTrace();  
    24.          }  
    25.       }  

    最后调到底层

    FmReceiverJNI.setMonoStereoNative (fd, 1)

    1. /* force mono/stereo mode */  
    2.    public int stereoControl(int fd, boolean stereo) {  
    3.   
    4.      if (stereo){  
    5.        return  FmReceiverJNI.setMonoStereoNative (fd, 1);  
    6.      }  
    7.      else {  
    8.        return  FmReceiverJNI.setMonoStereoNative (fd, 0);  
    9.      }  
    10.   
    11.    }  

     通过mCallbacks.onTuneStatusChanged();调用到FMRadio.java的内部存根类IFMRadioServiceCallbacks.stub类的public void onTuneStatusChanged()方法进行存入fm频率,数据最后调用FMRadio的resetFMStationInfoUI()刷新UI

    1. public void <strong>onTuneStatusChanged() </strong> {  
    2.         Log.d(LOGTAG, "mServiceCallbacks.onTuneStatusChanged: ");  
    3.         if (mIsScaning) {  
    4.             Log.d(LOGTAG, "isScanning....................");  
    5.             SharedPreferences sp = getSharedPreferences(SCAN_STATION_PREFS_NAME, 0);  
    6.             SharedPreferences.Editor editor = sp.edit();  
    7.             int station_number = sp.getInt(NUM_OF_STATIONS, 0);  
    8.             station_number++;  
    9.             editor.putInt(NUM_OF_STATIONS, station_number);  
    10.             editor.putString(STATION_NAME + station_number, station_number + "");  
    11.             editor.putInt(STATION_FREQUENCY + station_number,  
    12.                                   FmSharedPreferences.getTunedFrequency());  
    13.             editor.commit();  
    14.         }  
    15.         <strong>cleanupTimeoutHandler();  
    16.         mHandler.post(mUpdateStationInfo);  
    17.         mHandler.post(mOnStereo);</strong>  
    18.      }  


    发送一handler跟新UI,调用此回调方法Runnable mUpdateStationInfo = new Runnable()

    1. Runnable mUpdateStationInfo = new Runnable() {  
    2.      public void run() {  
    3.         cleanupTimeoutHandler();  
    4.         PresetStation station = new PresetStation("", FmSharedPreferences.getTunedFrequency());  
    5.         if (station != null) {  
    6.             mTunedStation.Copy(station);  
    7.         }  
    8.         <strong>updateSearchProgress();  
    9.         resetFMStationInfoUI();</strong>  
    10.      }  
    11.   };  

    updateStationInfoToUI();

    1. private void <strong>updateStationInfoToUI()</strong> {  
    2.       double frequency = mTunedStation.getFrequency() / 1000.0;  
    3.       mTuneStationFrequencyTV.setText("" + frequency + "MHz");  
    4.       if ((mPicker != null) && mUpdatePickerValue) {  
    5.           mPicker.setValue(((mTunedStation.getFrequency() - mPrefs.getLowerLimit())  
    6.                               / mPrefs.getFrequencyStepSize()));  
    7.       }  
    8.       mStationCallSignTV.setText(mTunedStation.getPIString());  
    9.       mProgramTypeTV.setText(mTunedStation.getPtyString());  
    10.       mRadioTextTV.setText("");  
    11.       mERadioTextTV.setText("");  
    12.       mRadioTextScroller.mOriginalString = "";  
    13.       mRadioTextScroller.mStringlength = 0;  
    14.       mRadioTextScroller.mIteration = 0;  
    15.       mERadioTextScroller.mOriginalString = "";  
    16.       mERadioTextScroller.mStringlength = 0;  
    17.       mERadioTextScroller.mIteration = 0;  
    18.       mProgramServiceTV.setText("");  
    19.       mStereoTV.setText("");  
    20.       setupPresetLayout();  
    21.    }  

    FM启动和关闭搜索都是通过JNI调到底层实现,代码路径是:vendorqcomopensourcefmjni

    android_hardware_fm.cpp 

    1. /* 
    2.  * JNI registration. 
    3.  */  
    4. static JNINativeMethod gMethods[] = {  
    5.         /* name, signature, funcPtr */  
    6.         { "acquireFdNative", "(Ljava/lang/String;)I",  
    7.             (void*)android_hardware_fmradio_FmReceiverJNI_acquireFdNative},  
    8.         { "closeFdNative", "(I)I",  
    9.             (void*)android_hardware_fmradio_FmReceiverJNI_closeFdNative},  
    10.         { "getFreqNative", "(I)I",  
    11.             (void*)android_hardware_fmradio_FmReceiverJNI_getFreqNative},  
    12.         { "setFreqNative", "(II)I",  
    13.             (void*)android_hardware_fmradio_FmReceiverJNI_setFreqNative},  
    14.         { "getControlNative", "(II)I",  
    15.             (void*)android_hardware_fmradio_FmReceiverJNI_getControlNative},  
    16.         { "setControlNative", "(III)I",  
    17.             (void*)android_hardware_fmradio_FmReceiverJNI_setControlNative},  
    18.         { "startSearchNative", "(II)I",  
    19.             (void*)android_hardware_fmradio_FmReceiverJNI_startSearchNative},  
    20.         { "cancelSearchNative", "(I)I",  
    21.             (void*)android_hardware_fmradio_FmReceiverJNI_cancelSearchNative}, { "getRSSINative", "(I)I",  
    22.             (void*)android_hardware_fmradio_FmReceiverJNI_getRSSINative},  
    23.         { "setBandNative", "(III)I",  
    24.             (void*)android_hardware_fmradio_FmReceiverJNI_setBandNative},  
    25.         { "getLowerBandNative", "(I)I",  
    26.             (void*)android_hardware_fmradio_FmReceiverJNI_getLowerBandNative},  
    27.         { "getUpperBandNative", "(I)I",  
    28.             (void*)android_hardware_fmradio_FmReceiverJNI_getUpperBandNative},  
    29.         { "getBufferNative", "(I[BI)I",  
    30.             (void*)android_hardware_fmradio_FmReceiverJNI_getBufferNative},  
    31.         { "setMonoStereoNative", "(II)I",  
    32.             (void*)android_hardware_fmradio_FmReceiverJNI_setMonoStereoNative},  
    33.         { "getRawRdsNative", "(I[BI)I",  
    34.             (void*)android_hardware_fmradio_FmReceiverJNI_getRawRdsNative},  
    35.        { "setNotchFilterNative", "(IIZ)I",  
    36.             (void*)android_hardware_fmradio_FmReceiverJNI_setNotchFilterNative},  
    37.         { "startRTNative", "(ILjava/lang/String;I)I",  
    38.             (void*)android_hardware_fmradio_FmReceiverJNI_startRTNative},  
    39.         { "stopRTNative", "(I)I",  
    40.             (void*)android_hardware_fmradio_FmReceiverJNI_stopRTNative},  
    41.         { "startPSNative", "(ILjava/lang/String;I)I",  
    42.             (void*)android_hardware_fmradio_FmReceiverJNI_startPSNative},  { "stopPSNative", "(I)I",  
    43.             (void*)android_hardware_fmradio_FmReceiverJNI_stopPSNative},  
    44.         { "setPTYNative", "(II)I",  
    45.             (void*)android_hardware_fmradio_FmReceiverJNI_setPTYNative},  
    46.         { "setPINative", "(II)I",  
    47.             (void*)android_hardware_fmradio_FmReceiverJNI_setPINative},  
    48.         { "setPSRepeatCountNative", "(II)I",  
    49.             (void*)android_hardware_fmradio_FmReceiverJNI_setPSRepeatCountNative},  
    50.         { "setTxPowerLevelNative", "(II)I",  
    51.             (void*)android_hardware_fmradio_FmReceiverJNI_setTxPowerLevelNative},  
    52.        { "setAnalogModeNative", "(Z)I",  
    53.             (void*)android_hardware_fmradio_FmReceiverJNI_setAnalogModeNative},  
    54.         { "SetCalibrationNative", "(I)I",  
    55.             (void*)android_hardware_fmradio_FmReceiverJNI_SetCalibrationNative},  
    56.         { "configureSpurTable", "(I)I",  
    57.             (void*)android_hardware_fmradio_FmReceiverJNI_configureSpurTable},  
    58.   
    59. };  

    上面写明了从jni的调用关系。具体的函数实现,请到Android_hardware_fm.cpp中去查看。我就不一一写出来了。以上就是FM搜索频率与取消搜索频率的操作与实现。搜索到频率后就可以听FM了。

  • 相关阅读:
    IL指令列表
    [译].Net中的内存-什么分配在了哪里
    C#中的可空类型
    深入C#并行编程(2) -- 使用线程
    C#自动内存分配
    在C#中使用Json.Net进行序列化和反序列化及定制化
    ASP.NET获取客户端、服务器端基础信息
    MongoDB随笔
    MongoDB.Driver 管道 Aggregate
    MongoDB centos安装问题 error while loading shared libraries: libnetsnmpmibs.so.31
  • 原文地址:https://www.cnblogs.com/mochaMM/p/5151838.html
Copyright © 2011-2022 走看看