Android FM模块学习之一 FM启动流程

   最近在学习FM模块,FM是一个值得学习的模块,可以从上层看到底层。上层就是FM的按扭操作和界面显示,从而调用到FM底层驱动来实现广播收听的功能。

   看看Fm启动流程:如下图:

Android FM模块学习之一 FM启动流程_第1张图片


进入FMRadio.java类,onCreate初始化一些数据,画出FM界面,启动fm在onStart()方法里启动FMRadioService.java (调用bindToService(this, osc)方法)。

Android FM模块学习之一 FM启动流程_第2张图片

注册下fm设置(在设置后发送一个设置广播,更新FMRadio类的状态)。

加载初始化数据,获取频率地址

newPresetStation("",FmSharedPreferences.getTunedFrequency());


在bindToService(this,osc)方法中,先启动StartService(同一个Service只onCreate一次),再启动bindservice(这样有个好处按返回键service不会走onDestroy方法)bindservice通过onBind回传一个IBinder对象到FMRadio类的内部类ServiceConnection的onServiceConnected方法中,调用enableRadio()方法。

Android FM模块学习之一 FM启动流程_第3张图片

在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 {
          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()扬声器可用,用户设置扬声器

 

/*
   * Turn ON FM: Powers up FM hardware, and initializes the FM module
   *                                                                                 .
   * @return true if fm Enable api was invoked successfully, false if the api failed.
   */
   private boolean fmOn() {
      boolean bStatus=false;
      mWakeLock.acquire(10*1000);
      if ( TelephonyManager.CALL_STATE_IDLE != getCallState() ) {
         return bStatus;
      }
     if(mReceiver == null)
      {
         try {
            mReceiver = new FmReceiver(FMRADIO_DEVICE_FD_STRING, fmCallbacks);
         }
         catch (InstantiationException e)
         {
            throw new RuntimeException("FmReceiver service not available!");
         }
      }
     if (mReceiver != null)
      {
         if (isFmOn())
         {
            /* FM Is already on,*/
            bStatus = true;
            Log.d(LOGTAG, "mReceiver.already enabled");
         }
         else
         { // This sets up the FM radio device
            FmConfig config = FmSharedPreferences.getFMConfiguration();
            Log.d(LOGTAG, "fmOn: RadioBand   :"+ config.getRadioBand());
            Log.d(LOGTAG, "fmOn: Emphasis    :"+ config.getEmphasis());
            Log.d(LOGTAG, "fmOn: ChSpacing   :"+ config.getChSpacing());
            Log.d(LOGTAG, "fmOn: RdsStd      :"+ config.getRdsStd());
            Log.d(LOGTAG, "fmOn: LowerLimit  :"+ config.getLowerLimit());
            Log.d(LOGTAG, "fmOn: UpperLimit  :"+ config.getUpperLimit());
            bStatus = mReceiver.enable(FmSharedPreferences.getFMConfiguration());
            if (isSpeakerEnabled()) {
                setAudioPath(false);
            } else {setAudioPath(true);
            }
            Log.d(LOGTAG, "mReceiver.enable done, Status :" +  bStatus);
         }

         if (bStatus == true)
         {
            /* Put the hardware into normal mode */
            bStatus = setLowPowerMode(false);
            Log.d(LOGTAG, "setLowPowerMode done, Status :" +  bStatus);
             AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
            if( (audioManager != null) &&(false == mPlaybackInProgress) )
            {
               Log.d(LOGTAG, "mAudioManager.setFmRadioOn = true \n" );
               //audioManager.setParameters("FMRadioOn="+mAudioDevice);
               int state =  getCallState();
               if ( TelephonyManager.CALL_STATE_IDLE != getCallState() )
               {
                 fmActionOnCallState(state);
               } else {
                   startFM(); // enable FM Audio only when Call is IDLE
               }
               Log.d(LOGTAG, "mAudioManager.setFmRadioOn done \n" );
            }if (mReceiver != null) {//注册远程组的处理
              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);
                Log.d(LOGTAG, "registerRdsGroupProcessing done, Status :" +  bStatus);
            }
            bStatus = enableAutoAF(FmSharedPreferences.getAutoAFSwitch());//可用自动跳转到选着的频率
            Log.d(LOGTAG, "enableAutoAF done, Status :" +  bStatus);
            /* There is no internal Antenna*/
            bStatus = mReceiver.setInternalAntenna(false);//将内置天线设为0
            Log.d(LOGTAG, "setInternalAntenna done, Status :" +  bStatus);

            /* Read back to verify the internal Antenna mode*/
            readInternalAntennaAvailable();

            startNotification();
            bStatus = true;
         }
         else
         {mReceiver = null; // as enable failed no need to disable
                              // failure of enable can be because handle
                              // already open which gets effected if
                              // we disable
            stop();
         }
      }
      return(bStatus);
   }

设置铃声路径  boolean state =mReceiver.setAnalogMode(analogMode);

   private boolean setAudioPath(boolean analogMode) {

        if (mReceiver == null) {
              return false;
        }
        if (isAnalogModeEnabled() == analogMode) {
                Log.d(LOGTAG,"Analog Path already is set to "+analogMode);
                return false;
        }
        if (!isAnalogModeSupported()) {
                Log.d(LOGTAG,"Analog Path is not supported ");
                return false;
        }
        if (SystemProperties.getBoolean("hw.fm.digitalpath",false)) {
                return false;
        }

        boolean state = mReceiver.setAnalogMode(analogMode);
        if (false == state) {
            Log.d(LOGTAG, "Error in toggling analog/digital path " + analogMode);
            return false;
        }
        misAnalogPathEnabled = analogMode;
        return true;
   }

analogMode模拟设置低功率  bStatus = setLowPowerMode(false);

电话不在闲置状太下 int state = getCallState();

                  fmActionOnCallState(state);


启动FM  startFM();

private void startFM(){
       Log.d(LOGTAG, "In startFM");
       if(true == mAppShutdown) { // not to send intent to AudioManager in Shutdown
           return;
       }
       if (isCallActive()) { // when Call is active never let audio playback
           mResumeAfterCall = true;
           return;
       }
       mResumeAfterCall = false;
       if ( true == mPlaybackInProgress ) // no need to resend event
           return;
       AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
       int granted = audioManager.requestAudioFocus(mAudioFocusListener, AudioManager.STREAM_MUSIC,
              AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
       if(granted != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
          Log.d(LOGTAG, "audio focuss couldnot be granted");
          return;
       }
       
       Log.d(LOGTAG,"FM registering for registerMediaButtonEventReceiver");
       mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
       ComponentName fmRadio = new ComponentName(this.getPackageName(),
                                  FMMediaButtonIntentReceiver.class.getName());
       mAudioManager.registerMediaButtonEventReceiver(fmRadio);
       mStoppedOnFocusLoss = false;

       if (!isSpeakerEnabled() && !mA2dpDeviceSupportInHal &&  (true == mA2dpDeviceState.isDeviceAvailable()) &&
           !isAnalogModeEnabled()
            && (true == startA2dpPlayback())) {
            mOverA2DP=true;
            Log.d(LOGTAG, "Audio source set it as A2DP");
            AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, AudioSystem.FORCE_BT_A2DP);
       } else {
           Log.d(LOGTAG, "FMRadio: Requesting to start FM");
           //reason for resending the Speaker option is we are sending
           //ACTION_FM=1 to AudioManager, the previous state of Speaker we set
           //need not be retained by the Audio Manager.
           AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_FM,
                               AudioSystem.DEVICE_STATE_AVAILABLE, "");//Fm设备
           if (isSpeakerEnabled()) {
               mSpeakerPhoneOn = true;
               Log.d(LOGTAG, "Audio source set it as speaker");
               AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, AudioSystem.FORCE_SPEAKER);
           } else {
               Log.d(LOGTAG, "Audio source set it as headset");
               AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, AudioSystem.FORCE_NONE);
           }

       }
       sendRecordServiceIntent(RECORD_START);
       mPlaybackInProgress = true;
   }

设置耳机等可以接受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  

mReceiver.setInternalAntenna(false)
FmReceiverJNI.setControlNative (sFd, V4L2_CID_PRIVATE_TAVARUA_ANTENNA,iAntenna)

 /*==============================================================
   FUNCTION:  setInternalAntenna
   ==============================================================*/
   /**
   *    Returns true if successful, false otherwise
   *
   *    

* This method sets internal antenna type to true/false * * @param intAntenna true is Internal antenna is present * *

* @return true/false */ public boolean setInternalAntenna(boolean intAnt) { int iAntenna ; if (intAnt) iAntenna = 1; else iAntenna = 0; int re = FmReceiverJNI.setControlNative (sFd, V4L2_CID_PRIVATE_TAVARUA_ANTENNA, iAntenna); if (re == 0) return true; return false; }


好,到此为止,FM的启动工作基本上就完成了。接下来就需要去搜索频道了,后续会继续分析FM搜索。



你可能感兴趣的:(移动,开发,Android,FM)