android FM JNI库参考原生实现

参考不同平台下FMRadio App中jni库的实现,本文是基于MTK平台实现,所以参考vendor\mediatek\proprietary\packages\apps\FMRadio\jni\fmr
.
├── Android.mk
├── common.cpp
├── fm.h
├── fmr_core.cpp
├── fmr_err.cpp
├── fmr.h
├── libfm_jni.cpp
├── NOTICE
└── README
最先应该关注的是,底层驱动控制FM的方式,当然我们会想到最简单粗暴的形式是,直接操作所有功能节点,实际情况是做了封装,以ioctl命令去执行我们熟悉的powerup、powerdown、tune、seek、mute等等.

fmr.h,需要直接关注下其中定义好的ioctl命令,此处也需要一个前提,即是kernel必须实现了这些供调用
// ********** **FM IOCTL define start *******************************
#define FM_IOC_MAGIC 0xf5
#define FM_IOCTL_POWERUP _IOWR(FM_IOC_MAGIC, 0, struct fm_tune_parm
)
#define FM_IOCTL_POWERDOWN _IOWR(FM_IOC_MAGIC, 1, int32_t
)
#define FM_IOCTL_TUNE _IOWR(FM_IOC_MAGIC, 2, struct fm_tune_parm
)
#define FM_IOCTL_SEEK _IOWR(FM_IOC_MAGIC, 3, struct fm_seek_parm
)
#define FM_IOCTL_SETVOL _IOWR(FM_IOC_MAGIC, 4, uint32_t
)
#define FM_IOCTL_GETVOL _IOWR(FM_IOC_MAGIC, 5, uint32_t
)
#define FM_IOCTL_MUTE _IOWR(FM_IOC_MAGIC, 6, uint32_t
)
#define FM_IOCTL_GETRSSI _IOWR(FM_IOC_MAGIC, 7, int32_t
)
#define FM_IOCTL_SCAN _IOWR(FM_IOC_MAGIC, 8, struct fm_scan_parm
)
#define FM_IOCTL_STOP_SCAN _IO(FM_IOC_MAGIC, 9)

so为独立的,方便与内置的FM做模块兼容,基本的代码调用
代码结构如下:
.
├── Android.mk
├── common.cpp
├── ext_fm.cpp
├── fm.h
├── fmr_core.cpp
└── fmr.h

common.cpp直接封装底层ioctl的接口
结构体fm_cbk_tbl定义需要封装的所有ioctl命令的函数

struct fm_cbk_tbl {
    //Basic functions.
    int (*open_dev)(const char *pname, int *fd);
    int (*close_dev)(int fd);
    int (*pwr_up)(int fd, int band, int freq);
    int (*pwr_down)(int fd, int type);
    int (*seek)(int fd, int *freq, int band, int dir, int lev);
    ...
}

入口函数,指针指向

void FM_interface_init(struct fm_cbk_tbl *cbk_tbl)
{
    //Basic functions.
    cbk_tbl->open_dev = COM_open_dev_ext;
    cbk_tbl->close_dev = COM_close_dev_ext;
    cbk_tbl->pwr_up = COM_pwr_up_ext;
    cbk_tbl->pwr_down = COM_pwr_down_ext;
    cbk_tbl->tune = COM_tune_ext;
    cbk_tbl->set_mute = COM_set_mute_ext;
    cbk_tbl->seek_all_ext = COM_Seek_all_ext_fm;
...
    return;
}

单个函数具体实现,以上电为例,FM_IOCTL_POWERUP即是底层已经实现具体功能的ioctl

int COM_pwr_up_ext(int fd, int band, int freq)
{	
	fm_tune_parm parm;
	
	int ret = 0;
	int pwrState = -1;
	parm.band = band;
	parm.freq = freq;
	ret = ioctl(fd, FM_IOCTL_POWERUP, &parm);
	LOGE("%s, ExtFm Externel FM power up \n", __func__);
	if(ret < 0){
		LOGE("%s, ExtFm Externel FM power up failed\n", __func__);
	}
	return ret;

}

fmr_core.cpp进一步封装,供jni调用

int FMR_pwr_up(int idx, int freq)
{
    int ret = 0;

    FMR_ASSERT(FMR_cbk_tbl(idx).pwr_up);

    LOGI("%s,[freq=%d]\n", __func__, freq);
    if (freq < fmr_data.cfg_data.low_band || freq > fmr_data.cfg_data.high_band) {
        LOGE("%s error freq: %d\n", __func__, freq);
        ret = -ERR_INVALID_PARA;
        return ret;
    }
    ret = FMR_cbk_tbl(idx).pwr_up(FMR_fd(idx), fmr_data.cfg_data.band, freq);
    if (ret < 1) {
        LOGE("%s failed, [ret=%d]\n", __func__, ret);
    }
    fmr_data.cur_freq = freq;
    LOGD("%s, [ret=%d]\n", __func__, ret);
    return ret;
}

ext_fm.cpp jni函数的注册,以提供静态接口给上层app java调用

jboolean powerUp(JNIEnv *env, jobject thiz, jfloat freq)
{
	int ret = 0;
	int tmp_freq;
	UNUSED(env);
	UNUSED(thiz);

	LOGI("%s, [freq=%d]\n", __func__, (int)freq);
	tmp_freq = (int)(freq * 100);		 //Eg, 87.5 * 100 --> 8750
	ret = FMR_pwr_up(g_idx, tmp_freq);

	LOGD(" ExtFm [ret=%d]\n", ret);
	return ret?JNI_FALSE:JNI_TRUE;
}

APP的调用方式

System.loadLibrary("ext_fm_jni");

注意打包函数so时,需要注意下Android.mk的module名字的形式一定得加上lib的前缀libext_fm_jni,最终生成肯定也是libext_fm_jni.so供java调用

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_SRC_FILES := \
    common.cpp	\
    ext_fm.cpp	\
    fmr_core.cpp	

LOCAL_C_INCLUDES := $(JNI_H_INCLUDE) \
    frameworks/base/include/media

LOCAL_SHARED_LIBRARIES := \
    libcutils \
    libdl \
    libmedia \
    liblog

LOCAL_MODULE := libext_fm_jni
LOCAL_CFLAGS += \
    -Wno-error=unused-parameter  \
    -Wno-error=deprecated-register

新增加ExtFm.java,直接参考源码的实现就可以,唯一的区别,修改为public方法以供调用

package com.android.fmradio;

/**
 * This class define FM native interface, will description FM native interface
 */
public class FmNative {
    static {
        System.loadLibrary("fmjni");
    }
...

    /**
     * power up FM with frequency use long antenna
     *
     * @param frequency frequency(50KHZ, 87.55; 100KHZ, 87.5)
     *
     * @return (true, success; false, failed)
     */
    public static native boolean powerUp(float frequency);
...
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值