应用层绕过HAL调用驱动(以Radio为例)

为什么要绕过Hal层调用驱动

  • 硬件抽象层是位于操作系统 内核与硬件电路之间的接口层,其目的在于将硬件抽象化。它隐藏了特定平台的硬件接口细节,为操作系统提供虚拟硬件平台,使其具有硬件无关性,可在多种平台上进行移植。在Android内核源码(不是linux内核源码)中添加HAL层、JNI层、开启系统服务,这是一个比较复杂的过程,很多标准的设备都采用这种方式设计,比如说wifi、gps、sensor等,这种调用过程看起来比较标准,但是如果作为第三方开发就会很麻烦,HAL层、JNI层,系统服务层,每层都需要编译Android内核源码,这样就会延长了产品的开发周期,所以编写本文意在简化应用层与驱动的交互逻辑,虽增加耦合,但在平台有限的开发环境中能大大提高开发效率,可从应用层调试驱动减少系统编译和排错的成本。

  • 简化前后结构概览

一. 创建访问驱动的新方式

1.编写Jni代码访问驱动节点

相关文件地址:

AndroidM_3561_after/vendor/xxx/packages/apps/Radio/app/src/main/jni/RadioDriveJni.cpp
可参照FaRadioService.cpp,实现节点的open/close/read/write

extern "C"JNIEXPORT jint JNICALLJava_com_xxx_radio_radiodrive_RadioDriveJni_init(JNIEnv *env, jobject instance) {    fd = open(DEVICE_NAME, O_RDWR);       if(fd < 0)    {        LOGE("Fail to open device file /dev/FlyRadio --%s.",DEVICE_NAME);        return -1;    }        return 0;}extern "C"JNIEXPORT jint JNICALLJava_com_xxx_radio_radiodrive_RadioDriveJni_setMute(JNIEnv *env, jobject instance,         jboolean muted) {    unsigned char buf[5] = {0xa0,0x66,0x01,0x00};        buf[3] = muted;        mMute = muted;        if(write(fd, buf,sizeof(buf)))    {        return 0;        }      return -1;}extern "C"JNIEXPORT jboolean JNICALLJava_com_xxx_radio_radiodrive_RadioDriveJni_destroy(JNIEnv *env, jobject instance) {    if(fd != -1){        if(!close(fd)){            return 0;                }    }    return -1;}

2.新建Android.mk文件跟随系统一起编译到system/lib目录,module命名为’ libfaradio_drive_jni ’

相关文件地址:

AndroidM_3561_after/vendor/xxx/packages/apps/Radio/app/src/main/jni/Android.mk

LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES:= \                RadioDriveJni.cpp \ LOCAL_SHARED_LIBRARIES := libutils libcutils LOCAL_C_INCLUDES += $(LOCAL_PATH)/include ifneq ($(XXX_LIB_OUT_PATH),)LOCAL_MODULE_PATH := $(XXX_LIB_OUT_PATH)endif LOCAL_MODULE:= libfaradio_drive_jni include $(BUILD_SHARED_LIBRARY)

3.Radio根目录下的Android.mk文件里引入上述创建的mk文件

相关文件地址:

AndroidM_3561_after/vendor/xxx/packages/apps/RadioAndroid.mk

include $(LOCAL_PATH)/app/src/main/jni/Android.mk

4.将libfaradio_drive_jni module 添加到device.mk白名单

相关文件地址:
AndroidM_3561_after/system/core/rootdir/device.mk

PRODUCT_PACKAGES += libfaradio_drive_jni

5.赋予应用读写驱动节点的权限

相关文件地址:
AndroidM_3561_after/system/core/rootdir/ueventd.rc

AndroidM_3561_after/external/sepolicy/system_app.te

在ueventd.rc中添加,

/dev/FlyRadio  0666  system  system

在system_app.te中添加,’ fly_radio_device ’ 为/dev/FlyRadio节点在file_contexts文件中的定义

allow system_app fly_radio_device:chr_file  rw_file_perms;

二. 移除访问驱动的旧方式

根据结构图一步一步定位再移除

1.移除Hal层
相关文件地址:

AndroidM_3561_after/hardware/libhardware/modules/xxx/FlyRadioHal.c

AndroidM_3561_after/hardware/libhardware/modules/xxx/Android.mk

直接删除即可

2.移除Service

相关文件地址:

AndroidM_3561_after/vendor/xxx/frameworks/native/faradio/service/FaRadioService.h

AndroidM_3561_after/vendor/xxx/frameworks/native/faradio/service/FaRadioService.cpp

AndroidM_3561_after/vendor/xxx/frameworks/native/faradio/service/IaRadioService.h

AndroidM_3561_after/vendor/xxx/frameworks/native/faradio/service/IaRadioService.cpp

直接删除即可

由于这里没有Android.mk文件,所有应该被父目录相应的Android.mk文件引入,在AndroidM_3561_after/vendor/xxx/frameworks/native/faradio/中查看Android.mk,果然有对service文件夹的引入,删除即可

LOCAL_C_INCLUDES += \        $(LOCAL_PATH)/service \

3.移除Service启动的入口

相关文件地址:

AndroidM_3561_after/vendor/xxx/frameworks/native/launcher/ServicesLauncher.cpp

注释掉FaRadioService启动的代码即可

extern "C" void instantiateServices(int tag){    if(tag == 1){        int status = launchService("/system/lib/libfaradioservice.so");        if(status == -1)            ALOGE("ServicesLauncher load library Error.");    }}

4.移除调用FaradioService的Jni封装

相关文件地址:

AndroidM_3561_after/vendor/xxx/frameworks/base/jni/com_xxx_radio_Radio.cpp

直接删除即可,和2一样移除相关Andorid.mk对此文件的依赖

###5.移除device.mk对已移除module的依赖
相关文件地址:

AndroidM_3561_after/vendor/xxx/device/device.mk

# PRODUCT_PACKAGES += \#libfaradioservice \# add xxx radio# PRODUCT_PACKAGES += radio.default

三. 编译系统

更多相关文章

  1. Android(安卓)Odex 文件使用
  2. [Android]如何做一个崩溃率少于千分之三噶应用app(17)-组件化SDK
  3. Android自定义适配器---实现简单文件管理器
  4. 上传音乐到Android模拟器的SD卡,并在Android模拟器上播放
  5. android屏幕适配计算方式及适配values文件生成
  6. Android中的软件安全和逆向分析[一]—apk反编译破解以及java汇编
  7. 自动化代码检查优化Lint
  8. 两个Android工程之间的调用
  9. 长聚微嵌 DMA-210U Android(安卓)入门第一天------烧写uboot、ke

随机推荐

  1. 内网安装mysql主从服务,mysql版本5.6.38-w
  2. 查询从每个组中查找第二大值
  3. 2018年5月05日 Python3-Mysql连接
  4. 数据库Mysql的学习(一)
  5. 解决Myeclipse下Debug出现Source not fou
  6. ORACLE 两表关联更新
  7. MySQL乐观锁在分布式场景下的实践
  8. 求sql存储过程!--创建存储过程统计各仓库
  9. SQL语句的优化
  10. Asp.net中Web.config连接字符串及配置数