FM打开fmOn()过程
FMPlay.java
private RadioServiceStub mService;
private Thread createOpenThread() {
return new Thread(new Runnable() {
public void run() {
Log.d(LOGTAG, "tring open fm");
mOver = false;
mHandler.sendMessage(mHandler.obtainMessage(MSG_PROGRESS));
mOpenResult = mService.fmOn();
Log.d(LOGTAG, "tring open fm result = " + mOpenResult);
mOver = true;
}
});
}
RadioServiceStub.java
private IRadioService mService;
public boolean fmOn() {
boolean value = false;
if (mService != null) {
try {
value = mService.fmOn();
} catch (RemoteException e) {
e.printStackTrace();
}
}
return value;
}
此处aidl实现,在IRadioService.java中
FMplayService.java
具体实现fmOn()的地方
static class ServiceStub extends IRadioService.Stub {
WeakReference<FMplayService> mService;
public ServiceStub(FMplayService service) {
mService = new WeakReference<FMplayService>(service);
}
public boolean fmOn() throws RemoteException {
if(mService != null){
if(mService.get() != null){
return mService.get().fmOn();
}
}
return false;
}
}
FMplayService.java
具体实现fmOn()的地方
private FmReceiver mReceiver = null;
private static final String RADIO_DEVICE = "/dev/radio0";
public boolean fmOn() {
mNeedShutdown = false;
mCanStopNotification = true;
boolean value = false;
if (mReceiver == null) {
try {
Log.d(LOGTAG, "create FmReceiver instance");
mReceiver = new FmReceiver(RADIO_DEVICE, null); -------------------- important1
} catch (InstantiationException e) {
Log.e(LOGTAG, "exception when creating FmReceiver instance");
e.printStackTrace();
}
if (mReceiver != null) {
Log.d(LOGTAG, "FmReceiver enable");
value = mReceiver.enable(null); -------------------- important2
if (!value) {
Log.i(LOGTAG, "mReceiver enable failed");
}
}
if (value) {
startNotification();
Log.d(LOGTAG, "turn on radio " + value);
// fix bug 126872 start
// no effective station is set after fm is enabled so noise comes out
setFreq(savedFreq);
// fix bug 126872 end
}
} else {
value = true;
if (mPausedByAudioFocus) {
mPausedByAudioFocus = false;
unMute();
}
}
if (value) {
value = routeAudio(mAudioDevice);
}
if (!value || mNeedShutdown) {
Log.d(LOGTAG, "close fm because mNeedShutdown = " + mNeedShutdown + " value "+value);
fmOff();
value = false;
}
return value;
}
=======================================AIDL upper==============================================
FmReceiver.java
public FmReceiver(String devicePath,
FmRxEvCallbacksAdaptor callback) throws InstantiationException {
mControl = new FmRxControls();
mRxEvents = new FmRxEventListener();
if ( !acquire(devicePath))
throw new InstantiationException("Unable to open device descriptor");
mDevice = devicePath;
registerClient(callback);
mRdsData = new FmRxRdsData(sFd);
}
FmRxControls.java
/*
* Turn on FM Rx/Tx. ---------------------1
* Rx = 1 and Tx = 2
*/ //fd = -1
public void fmOn(int fd, int device) { -------------------- important3
FmReceiverJNI.setControlNative(fd, V4L2_CID_PRIVATE_TAVARUA_STATE, 1);
}
FmRxEventListener.java
FmRxRdsData.java
FmTransceiver.java
protected static final int FM_RX =1; //com.android.music.musicservicecommand.pause
public boolean enable (FmConfig configSettings){
boolean status;
/* Enable the Transceiver common for both
receiver and transmitter
*/
status = super.enable(configSettings, FmTransceiver.FM_RX);
return status;
}
FmTransceiver.java
public boolean enable (FmConfig configSettings, int device){
Log.d(TAG, "turning on %d" + device);
mControl.fmOn(sFd, device);
Log.d(TAG, "Calling fmConfigure");
return FmConfig.fmConfigure (sFd, configSettings);
}
FmRxControls.java sFd=-1
mControl.fmOn(sFd, device); -> 1
FmReceiverJNI.java
public synchronized static native int setControlNative (int fd, int id, int value);
android_hardware_fm.cpp
/*
* JNI registration.
*/
static JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
................
{ "setControlNative", "(III)I",
(void*)android_hardware_fmradio_FmReceiverJNI_setControlNative},
................
}
static jint android_hardware_fmradio_FmReceiverJNI_setControlNative
(JNIEnv * env, jobject thiz, jint fd, jint id, jint value) //fd=-1 id=V4L2_CID_PRIVATE_TAVARUA_STATE value=1
{
fm_device_t* device = (fm_device_t *)fd;
int err = device->setControl(device,id,value); //device ?
LOGE("(setControl)operation=%x value=%d result=%d errno=%d", id, value, err, errno);
if (err < 0) {
return FM_JNI_FAILURE;
}
return FM_JNI_SUCCESS;
}
====================================JNI upper============================================
libfm-brcm_hw.cpp
static int
setControl(struct fm_device_t* dev,int id, int value)
{
int err = -1;
struct bcm4330_fm_device_t *device = (struct bcm4330_fm_device_t *)dev;
int status = FM_SUCCESS;
LOGD("%s, %d\n", __FUNCTION__, id );
switch(id) {
case V4L2_CID_PRIVATE_TAVARUA_STATE:
{
value ? enableNative(FUNC_REGION_NA): disableNative(false);
if(gMutex.wait(0, 3))
{
status = FM_FAILURE;
}
else
{
if(gfm_params.chnl_info.status == BTA_FM_OK)
{
status = FM_SUCCESS;
}
else
{
status = FM_FAILURE;
}
}
}
break;
case V4L2_CID_AUDIO_VOLUME:
{
if( value < 0 )
{
gVolume = 0;
}
else if( value > 15 )
{
gVolume = 256;
}
else
gVolume = volumeTbl[value];
LOGD("Set Volume : %d, %d\n", value, gVolume);
setFMVolumeNative( gVolume );
if(gMutex.wait(0, 3))
{
status = FM_FAILURE;
}
else
{
if(gfm_params.chnl_info.status == BTA_FM_OK)
{
status = FM_SUCCESS;
}
else
{
status = FM_FAILURE;
}
}
}
break;
case V4L2_CID_AUDIO_MUTE:
{
muteNative(value);
if(gMutex.wait(0, 3))
{
status = FM_FAILURE;
}
else
{
if(gfm_params.chnl_info.status == BTA_FM_OK)
{
status = FM_SUCCESS;
}
else
{
status = FM_FAILURE;
}
}
}
break;
}
LOGE("(setControl)operation=%x value=%d status=%d", id, value, status);
return status;
}
=================================others below============================
android_hardware_fm.cpp
int register_android_hardware_fm_fmradio(JNIEnv* env)
{
return AndroidRuntime::registerNativeMethods(env, "android/hardware/fmradio/FmReceiverJNI", gMethods, NELEM(gMethods));
}
AndroidRuntime.cpp
/*
* Register native methods using JNI.
*/
/*static*/ int AndroidRuntime::registerNativeMethods(JNIEnv* env,
const char* className, const JNINativeMethod* gMethods, int numMethods)
{
return jniRegisterNativeMethods(env, className, gMethods, numMethods);
}
static const RegJNIRec gRegJNI[] = {
.....................
REG_JNI(register_android_hardware_fm_fmradio),
.....................
}
/*
* Register android native functions with the VM.
*/
/*static*/ int AndroidRuntime::startReg(JNIEnv* env)
{
/*
* This hook causes all future threads created in this process to be
* attached to the JavaVM. (This needs to go away in favor of JNI
* Attach calls.)
*/
androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);
LOGV("--- registering native functions ---\n");
/*
* Every "register" function calls one or more things that return
* a local reference (e.g. FindClass). Because we haven't really
* started the VM yet, they're all getting stored in the base frame
* and never released. Use Push/Pop to manage the storage.
*/
env->PushLocalFrame(200);
if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
env->PopLocalFrame(NULL);
return -1;
}
env->PopLocalFrame(NULL);
//createJavaThread("fubar", quickTest, (void*) "hello");
return 0;
}
FMPlay.java
private RadioServiceStub mService;
private Thread createOpenThread() {
return new Thread(new Runnable() {
public void run() {
Log.d(LOGTAG, "tring open fm");
mOver = false;
mHandler.sendMessage(mHandler.obtainMessage(MSG_PROGRESS));
mOpenResult = mService.fmOn();
Log.d(LOGTAG, "tring open fm result = " + mOpenResult);
mOver = true;
}
});
}
RadioServiceStub.java
private IRadioService mService;
public boolean fmOn() {
boolean value = false;
if (mService != null) {
try {
value = mService.fmOn();
} catch (RemoteException e) {
e.printStackTrace();
}
}
return value;
}
此处aidl实现,在IRadioService.java中
FMplayService.java
具体实现fmOn()的地方
static class ServiceStub extends IRadioService.Stub {
WeakReference<FMplayService> mService;
public ServiceStub(FMplayService service) {
mService = new WeakReference<FMplayService>(service);
}
public boolean fmOn() throws RemoteException {
if(mService != null){
if(mService.get() != null){
return mService.get().fmOn();
}
}
return false;
}
}
FMplayService.java
具体实现fmOn()的地方
private FmReceiver mReceiver = null;
private static final String RADIO_DEVICE = "/dev/radio0";
public boolean fmOn() {
mNeedShutdown = false;
mCanStopNotification = true;
boolean value = false;
if (mReceiver == null) {
try {
Log.d(LOGTAG, "create FmReceiver instance");
mReceiver = new FmReceiver(RADIO_DEVICE, null); -------------------- important1
} catch (InstantiationException e) {
Log.e(LOGTAG, "exception when creating FmReceiver instance");
e.printStackTrace();
}
if (mReceiver != null) {
Log.d(LOGTAG, "FmReceiver enable");
value = mReceiver.enable(null); -------------------- important2
if (!value) {
Log.i(LOGTAG, "mReceiver enable failed");
}
}
if (value) {
startNotification();
Log.d(LOGTAG, "turn on radio " + value);
// fix bug 126872 start
// no effective station is set after fm is enabled so noise comes out
setFreq(savedFreq);
// fix bug 126872 end
}
} else {
value = true;
if (mPausedByAudioFocus) {
mPausedByAudioFocus = false;
unMute();
}
}
if (value) {
value = routeAudio(mAudioDevice);
}
if (!value || mNeedShutdown) {
Log.d(LOGTAG, "close fm because mNeedShutdown = " + mNeedShutdown + " value "+value);
fmOff();
value = false;
}
return value;
}
=======================================AIDL upper==============================================
FmReceiver.java
public FmReceiver(String devicePath,
FmRxEvCallbacksAdaptor callback) throws InstantiationException {
mControl = new FmRxControls();
mRxEvents = new FmRxEventListener();
if ( !acquire(devicePath))
throw new InstantiationException("Unable to open device descriptor");
mDevice = devicePath;
registerClient(callback);
mRdsData = new FmRxRdsData(sFd);
}
FmRxControls.java
/*
* Turn on FM Rx/Tx. ---------------------1
* Rx = 1 and Tx = 2
*/ //fd = -1
public void fmOn(int fd, int device) { -------------------- important3
FmReceiverJNI.setControlNative(fd, V4L2_CID_PRIVATE_TAVARUA_STATE, 1);
}
FmRxEventListener.java
FmRxRdsData.java
FmTransceiver.java
protected static final int FM_RX =1; //com.android.music.musicservicecommand.pause
public boolean enable (FmConfig configSettings){
boolean status;
/* Enable the Transceiver common for both
receiver and transmitter
*/
status = super.enable(configSettings, FmTransceiver.FM_RX);
return status;
}
FmTransceiver.java
public boolean enable (FmConfig configSettings, int device){
Log.d(TAG, "turning on %d" + device);
mControl.fmOn(sFd, device);
Log.d(TAG, "Calling fmConfigure");
return FmConfig.fmConfigure (sFd, configSettings);
}
FmRxControls.java sFd=-1
mControl.fmOn(sFd, device); -> 1
FmReceiverJNI.java
public synchronized static native int setControlNative (int fd, int id, int value);
android_hardware_fm.cpp
/*
* JNI registration.
*/
static JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
................
{ "setControlNative", "(III)I",
(void*)android_hardware_fmradio_FmReceiverJNI_setControlNative},
................
}
static jint android_hardware_fmradio_FmReceiverJNI_setControlNative
(JNIEnv * env, jobject thiz, jint fd, jint id, jint value) //fd=-1 id=V4L2_CID_PRIVATE_TAVARUA_STATE value=1
{
fm_device_t* device = (fm_device_t *)fd;
int err = device->setControl(device,id,value); //device ?
LOGE("(setControl)operation=%x value=%d result=%d errno=%d", id, value, err, errno);
if (err < 0) {
return FM_JNI_FAILURE;
}
return FM_JNI_SUCCESS;
}
====================================JNI upper============================================
libfm-brcm_hw.cpp
static int
setControl(struct fm_device_t* dev,int id, int value)
{
int err = -1;
struct bcm4330_fm_device_t *device = (struct bcm4330_fm_device_t *)dev;
int status = FM_SUCCESS;
LOGD("%s, %d\n", __FUNCTION__, id );
switch(id) {
case V4L2_CID_PRIVATE_TAVARUA_STATE:
{
value ? enableNative(FUNC_REGION_NA): disableNative(false);
if(gMutex.wait(0, 3))
{
status = FM_FAILURE;
}
else
{
if(gfm_params.chnl_info.status == BTA_FM_OK)
{
status = FM_SUCCESS;
}
else
{
status = FM_FAILURE;
}
}
}
break;
case V4L2_CID_AUDIO_VOLUME:
{
if( value < 0 )
{
gVolume = 0;
}
else if( value > 15 )
{
gVolume = 256;
}
else
gVolume = volumeTbl[value];
LOGD("Set Volume : %d, %d\n", value, gVolume);
setFMVolumeNative( gVolume );
if(gMutex.wait(0, 3))
{
status = FM_FAILURE;
}
else
{
if(gfm_params.chnl_info.status == BTA_FM_OK)
{
status = FM_SUCCESS;
}
else
{
status = FM_FAILURE;
}
}
}
break;
case V4L2_CID_AUDIO_MUTE:
{
muteNative(value);
if(gMutex.wait(0, 3))
{
status = FM_FAILURE;
}
else
{
if(gfm_params.chnl_info.status == BTA_FM_OK)
{
status = FM_SUCCESS;
}
else
{
status = FM_FAILURE;
}
}
}
break;
}
LOGE("(setControl)operation=%x value=%d status=%d", id, value, status);
return status;
}
=================================others below============================
android_hardware_fm.cpp
int register_android_hardware_fm_fmradio(JNIEnv* env)
{
return AndroidRuntime::registerNativeMethods(env, "android/hardware/fmradio/FmReceiverJNI", gMethods, NELEM(gMethods));
}
AndroidRuntime.cpp
/*
* Register native methods using JNI.
*/
/*static*/ int AndroidRuntime::registerNativeMethods(JNIEnv* env,
const char* className, const JNINativeMethod* gMethods, int numMethods)
{
return jniRegisterNativeMethods(env, className, gMethods, numMethods);
}
static const RegJNIRec gRegJNI[] = {
.....................
REG_JNI(register_android_hardware_fm_fmradio),
.....................
}
/*
* Register android native functions with the VM.
*/
/*static*/ int AndroidRuntime::startReg(JNIEnv* env)
{
/*
* This hook causes all future threads created in this process to be
* attached to the JavaVM. (This needs to go away in favor of JNI
* Attach calls.)
*/
androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);
LOGV("--- registering native functions ---\n");
/*
* Every "register" function calls one or more things that return
* a local reference (e.g. FindClass). Because we haven't really
* started the VM yet, they're all getting stored in the base frame
* and never released. Use Push/Pop to manage the storage.
*/
env->PushLocalFrame(200);
if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
env->PopLocalFrame(NULL);
return -1;
}
env->PopLocalFrame(NULL);
//createJavaThread("fubar", quickTest, (void*) "hello");
return 0;
}