FM点击关机按钮的时候:
FMplay.java :
public boolean onCheckedChanged(View view, boolean checked) {
switch(view.getId()) {
case R.id.power_toggle:
Log.d("yzy","onCheckedChanged");
if (checked) {
ismPhoneStateListener = false;
mPhone = true;
mHandler.sendEmptyMessage(MSG_OPEN);
} else if (mService.isFmOn()){
ismPhoneStateListener = true;
mHandler.removeMessages(MSG_ABLED);
mHandler.sendEmptyMessage(MSG_CLOSE);
closeAudioPipe();
}
break;
Handler:
case MSG_CLOSE:
Log.d("yzy", "FMplay:fmOff");
removeMessages(MSG_CLOSE);
if (mReady) {
if(StationSearch.isSearching()){
StationSearch.mSearcher.stopSearching();
try {
StationSearch.mSearcher.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (mService.isFmOn()) {
mService.fmOff();
}
if(msg.getData().containsKey(KEY_CLOSE_REASON)){
Toast.makeText(FMPlay.this, msg.getData()
.getString(KEY_CLOSE_REASON), Toast.LENGTH_LONG).show();
}
if(routeDevices == 1){
audiodevices = true;
}
setUiPower(false, false);
} else {
Message message = mHandler.obtainMessage(MSG_CLOSE);
sendMessageDelayed(message, CHECK_DELAY);
}
break;
FMplayService.java
public boolean fmOff() {
Log.d(LOGTAG, "fmOff");
Log.d("yzy", "FMplayService:fmOff");
mNeedShutdown = false;
if (mReceiver != null) {
mReceiver.disable();
mReceiver.release();
}
stopNotification();
AudioManager am = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
am.abandonAudioFocus(mAudioFocusListener);
return true;
}
framework/base/core/java/android/hardware/fmradio/FmRxControls.java
/*
* Turn off FM Rx/Tx
*/
public void fmOff(int fd){
FmReceiverJNI.setControlNative(fd, V4L2_CID_PRIVATE_TAVARUA_STATE, 0 );
}
frameworks/base/core/jni/android_hardware_fm.cpp
static jint android_hardware_fmradio_FmReceiverJNI_setControlNative
(JNIEnv * env, jobject thiz, jint fd, jint id, jint value)
{
int err = -1;
switch(id) {
case V4L2_CID_PRIVATE_TAVARUA_STATE:
{
err = ioctl(fd, FM_IOCTL_ENABLE, &value);
}
break;
case V4L2_CID_AUDIO_VOLUME:
{
gVolume = value;
err = ioctl(fd, FM_IOCTL_SET_VOLUME, &value);
}
break;
case V4L2_CID_AUDIO_MUTE:
{
if (value == 0) {
err = ioctl(fd, FM_IOCTL_SET_VOLUME, &gVolume);
} else {
int volume = -1;
err = ioctl(fd, FM_IOCTL_GET_VOLUME, &volume);
if (err >= 0) {
gVolume = volume;
volume = 0;
err = ioctl(fd, FM_IOCTL_SET_VOLUME, &volume);
}
}
}
break;
}
V4L2(video for Linux 2)驱动
V4L2(video for linux) 可以支持多种设备,它可以有以下5种接口:
1、视频采集接口(video capture interface):这种应用的设备可以是高频头或者摄像头.V4L2的最初设计就是应用于这种功能的.下面也是着重讲解这种应用;
2、视频输出接口(video output interface):可以驱动计算机的外围视频图像设备——像可以输出电视信号格式的设备;
3、直接传输视频接口(video overlay interface):它的主要工作是把从视频采集设备采集过来的信号直接输出到输出设备之上,而不用经过系统的CPU;
4、视频间隔消隐信号接口(VBI interface):它可以使应用可以访问传输消隐期的视频信号;
5、收音机接口(radio interface):可用来处理从AM或FM高频头设备接收来的音频流;
V4L2驱动的主要功能是使程序有发现设备的能力和操作设备.它主要是用过一系列的回调函数来实现这些功能.像设置高频头的频率,帧频,视频压缩格式和图像像参数等等.