现在的位置: 首页 > 综合 > 正文

FM函数从上层到底层调用过程(回顾)

2013年07月16日 ⁄ 综合 ⁄ 共 11623字 ⁄ 字号 评论关闭

FM AIDL JNI 调用过程回顾

FMPlay.java
public class FMPlay extends Activity
                   implements ServiceConnection;
                   
private RadioServiceStub mService;
public void onCreate(Bundle savedInstanceState) {
mService = new RadioServiceStub(this, this);
//-----------------6
RadioServiceStub.java
private Context mContext;
  private ServiceConnection mCallback;
public RadioServiceStub(Context context, ServiceConnection callback) {
        mContext = context;
        mCallback = callback;
        mService = null;
        mBinder = null;
    }
//-----------------6
}

protected void onStart() {
if (!mService.bindToService()) {
//------------------------------5
RadioServiceStub.java
private ServiceConnection mBinder;
public boolean bindToService() {
        mContext.startService(new Intent(mContext, FMplayService.class));   //此时的mContext即为FMPlay.this,启动FMplayService这个Service
        mBinder = new BinderCallback(mCallback);    //mCallback为callback,即为从FMPlay传过来ServiceConnection
        //
public void onServiceConnected(ComponentName name, IBinder service) {
//        mReady = true;
//        Log.d(LOGTAG, "mReady = true");
//    }

//    public void onServiceDisconnected(ComponentName name) {
//        mReady = false;
//    }
//----------------------------5
RadioServiceStub.java

private class BinderCallback implements ServiceConnection {
       private ServiceConnection mCallback;

       public void onServiceDisconnected(ComponentName name) {
           if (mCallback != null) {
               mCallback.onServiceDisconnected(name);
           }
           mService = null;
       }
       public void onServiceConnected(ComponentName name, IBinder service) {
           mService = IRadioService.Stub.asInterface(service);
           if (mCallback != null) {
               mCallback.onServiceConnected(name, service);
           }
       }
       public BinderCallback(ServiceConnection callback) {
           mCallback = callback;
       }
    }
//----------------------------4
        return mContext.bindService((new Intent()).setClass(mContext, FMplayService.class), mBinder,Context.BIND_AUTO_CREATE);
        //当返回这句时,new Intent()).setClass(mContext, FMplayService.class) 等价于 new Intent(mContext, FMplayService.class),此时调用mBinder的onServiceConnected
        
        //----------------------------3
        正式进入关键调用AIDL:RadioServiceStub.java
        private IRadioService mService;
        public void onServiceConnected(ComponentName name, IBinder service) {  //ComponentName name, IBinder service这2个参数还有待研究==
           mService = IRadioService.Stub.asInterface(service);    //对IRadioService.aidl做个解释--->1.1,之后mService就可以调用此里面的方法,比如-->1.2
           //--------------------------1
          在out目录下会自动生成 IRadioService.java 部分内容如下 有待研究==
          public static com.thunderst.radio.IRadioService asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.thunderst.radio.IRadioService))) {
return ((com.thunderst.radio.IRadioService)iin);
}
return new com.thunderst.radio.IRadioService.Stub.Proxy(obj);
}

public boolean isFmOn() throws android.os.RemoteException;
           //--------------------------1
           if (mCallback != null) {   //mCallback = callback;一定不为null,即为从FMPlay传过来ServiceConnection,所以在FMPlay一定有对onServiceConnected的具体实现
               mCallback.onServiceConnected(name, service);
               
//------------------------------2
               
public void onServiceConnected(ComponentName name, IBinder service) {
       mReady = true;
       Log.d(LOGTAG, "mReady = true");
   }
               
//------------------------------2
           }
       }
        
        //----------------------------3
    }
//------------------------------4
            Log.d(LOGTAG, "fail to bindToService");
            mService = null;
            return;
        }
}

-----------------1.1-----------------------
package com.thunderst.radio;

interface IRadioService
{
    boolean isMuted();
    boolean setFreq(float freq);
    boolean startSeek(boolean up);
    boolean stopSeek();
    float getFreq();    
    float getFreq2(boolean issech);
    boolean routeAudio(int device); 
    boolean setVolume(int volume);
    int getAudioDevice();
    boolean fmOn();
    boolean fmOff();
    boolean isFmOn();
    boolean mute();
    boolean unMute();
}

----------------------1.2-----------------
FMPlay.java
public void onTuneWheelValueChanged(View v, float changedBy) {
        Message msg = mHandler.obtainMessage(MSG_TUNE);
        Bundle data = new Bundle();
        float freq = adjustFreq(WheelConfig.format(mService.getFreq() + changedBy)); -->到1.3    //学习的出发点从对mService.getFreq()疑惑开始!!!!!

        data.putFloat("freq", freq);
        msg.setData(data);
        mHandler.sendMessage(msg);
    }}
    
看看mService.getFreq()怎么被调用的。

从上面分析可知:mContext.startService(new Intent(mContext, FMplayService.class));启动了 FMplayService

//-----------------------1
RadioServiceStub.java
mContext.bindService((new Intent()).setClass(mContext, FMplayService.class), mBinder,Context.BIND_AUTO_CREATE);bindService时调用了 FMplayService
public IBinder onBind(Intent intent) {
    Log.d(LOGTAG,"onBind");
       mBinded = true;
       return mBinder;
       //--------------------------2
       private final IBinder mBinder = new ServiceStub(this);
       
//-----------------------------3
       
关键
       
static class ServiceStub extends IRadioService.Stub{
       WeakReference<FMplayService> mService;

       public ServiceStub(FMplayService service) {
           mService = new WeakReference<FMplayService>(service);
           //----------------------4
           mService = new WeakReference<FMplayService>(service);大概流程,最后得到是一个T类型类,即为 FMplayService

public WeakReference(T r) {
       super(r, null);
   }


Reference(T r, ReferenceQueue q) {
       referent = r;
       queue = q;
   }
           //----------------------4
       }

       public boolean fmOn() throws RemoteException {
           if(mService != null){
               if(mService.get() != null){
                   return mService.get().fmOn();
               }
           }
           return false;
       }

       public boolean fmOff() throws RemoteException {
           if(mService != null){
               if(mService.get() != null){
                   return mService.get().fmOff();
               }
           }
           return false;
       }

       public boolean isFmOn() throws RemoteException {
           if(mService != null){
               if(mService.get() != null){
                   return mService.get().isFmOn();
               }
           }
           return false;
       }

       public boolean mute() throws RemoteException {
           return mService.get().mute();
       }

       public boolean unMute() throws RemoteException {
           return mService.get().unMute();
       }

       public boolean isMuted() throws RemoteException {
           return mService.get().isMuted();
       }

       public boolean setFreq(float freq) throws RemoteException {
           if(mService != null){
               if (mService.get() != null) {
                   return mService.get().setFreq(freq);
               }
           }
           return false;
       }

       public boolean startSeek(boolean up) throws RemoteException {
           return mService.get().startSeek(up);
       }

       public boolean stopSeek() throws RemoteException {
           return mService.get().stopSeek();
       }

------------------1.3--------------------------
       public float getFreq() throws RemoteException {
           if(mService != null){
               if (mService.get() != null) {
               //----------------5
               public T get() {
       return referent; //还是一个FMplayService
   }
               //----------------5
                   return mService.get().getFreq(); //即调用FMplayService的getFreq()方法,到此调用结束! 
                   //------------------------6
                    public float getFreq() {
       float freq = -1.0f;

       synchronized(mReceiverLock) {
           if (mReceiver != null) {
               int iFreq = mReceiver.getTunedFrequency();  // -->continue
               Log.d(LOGTAG, "get frequency " + iFreq);
               if (iFreq > 0) {
                   freq = (float) iFreq / TRANS_MULT;
               }
           }
       }

       return freq;
   }
                   //------------------------6
               }
           }
           return FMPlaySharedPreferences.getTunedFreq();
       }

       public float getFreq2(boolean issech) throws RemoteException {
           if(mService != null){
               if(mService.get() != null){
                   return mService.get().getFreq2(issech);
               }
           }
           return FMPlaySharedPreferences.getTunedFreq();
       }

       public boolean routeAudio(int device) {
           return mService.get().routeAudio(device);
       }

       public boolean setVolume(int volume) {
           return mService.get().setVolume(volume);
       }

       public int getAudioDevice() {
           return mService.get().getAudioDevice();
       }
    }
       
//-----------------------------3
       //--------------------------2
    }
  //------------------------1

==========================continue=============================
 public float getFreq() {
        float freq = -1.0f;

        synchronized(mReceiverLock) {
            if (mReceiver != null) {
//----------------------1
在getFreq()时已经有
public boolean fmOn() {
mReceiver = new FmReceiver(RADIO_DEVICE, null);  //所以mReceiver != null
}
//----------------------1
                int iFreq = mReceiver.getTunedFrequency();
                //------------------------2
                 FmReceiver.java
                 public int getTunedFrequency () {
     int frequency = FmReceiverJNI.getFreqNative(sFd);
     //----------------------------3
     FmReceiverJNI.java
     static synchronized native int getFreqNative(int fd); //native JNI调用 --->1.4
     //----------------------------3
     Log.d(TAG, "getFrequency: "+frequency);

     return frequency;
  }
                //------------------------2
                Log.d(LOGTAG, "get frequency " + iFreq);
                if (iFreq > 0) {
                    freq = (float) iFreq / TRANS_MULT;
                }
            }
        }

        return freq;
    }

------------------------1.4--------------------------
android_hardware_fm.cpp
static JNINativeMethod gMethods[] = {
        /* name, signature, funcPtr */
        { "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},        //函数映射
            //-------------------------------1
            /* native interface */
static jint android_hardware_fmradio_FmReceiverJNI_getFreqNative(JNIEnv * env, jobject thiz, jint fd)
{
   int freq = -1;
   fm_device_t* device = (fm_device_t *)fd;
   //---------------------------2
   fm.h
   struct fm_device_t {
   struct hw_device_t common;

   /**
    * Set the provided lights to the provided values.
    *
    * Returns: 0 on succes, error code on failure.
    */
   int (*getFreq)(struct fm_device_t* dev, int* freq);
   int (*setFreq)(struct fm_device_t* dev, int freq);
   int (*setControl)(struct fm_device_t* dev,int id, int value);
   int (*startSearch)(struct fm_device_t* dev,int freq, int dir, int timeout, int reserve);
   int (*cancelSearch)(struct fm_device_t*dev);
};
   //---------------------------2
   int err = device->getFreq(device,&freq);
   //------------------------------3
   具体到FM厂商,比如 博通
   libfm-brcm_hw.cpp
   static int
getFreq(struct fm_device_t* dev,int* freq)
{
   struct bcm4330_fm_device_t *device = (struct bcm4330_fm_device_t *)dev;
   LOGD("%s, %d\n", __FUNCTION__, gfm_params.chnl_info.freq );

   //*freq = gfm_params.chnl_info.freq/10;
   *freq = gfm_context.cur_freq/10;

   return FM_SUCCESS;                    ---->结束!
}
   //------------------------------3
   LOGE("(getFreq)result=%d freq=%d\n", err, freq);
   if(err < 0){
     return FM_JNI_FAILURE;
   }
   return freq;
}
            //-------------------------------1
        { "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", "(IIIII)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},
        { "setRegionNative", "(II)I",
            (void*)android_hardware_fmradio_FmReceiverJNI_setRegionNative},
        { "getLowerBandNative", "(I)I",
            (void*)android_hardware_fmradio_FmReceiverJNI_getLowerBandNative},
        { "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},
};

抱歉!评论已关闭.