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},
};
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},
};