6.4 Android硬件访问服务编写HAL代码
JNI向上提供本地函数,向下加载HAL文件,并调用HAL的函数;
HAL负责访问驱动程序执行硬件操作
JNI和HAL都是用c语言或者C++语言编写的,JNI加载HAL的实质就是使用dlopen加载动态库文件
安多人源代码中第dlopen做了一层封装,在JNI中是通过hw_get_module来加载动态库
external\chromium_org\third_party\hwcplus\src\hardware.c
hw_get_module("led")//分析hw_get_module
1. 模块名==>文件名
hw_get_module_by_class("led", NULL)
name = "led"
property_get(prop_name,prop,NULL) prop_name是某个属性,根据属性来获得prop值
hw_module_exists 判断是否存在led.prop.so
(在运行的Android系统中执行 getprop ro.hardware可以查看这个ro.hardware属性存在么,并打印其值)
2. 加载
load
dlopen(filename)
dlsym("HMI") 从SO文件中获得名为HMI的hw_module_t结构体
strcmp(id, hmi->id) 判断名字是否一致(hmi->id, "led")
如果一致,把找到的hmi结构体传出去
hw_module_exists(char *path, size_t path_len, const char *name,const char *subname)
led.tiny4412.so(不存在)
led.exynos4.so(不存在)
led.default.so(存在)
它用来判断"name"."subname".so文件是否存在
查找的目录:
a. HAL_LIBRARY_PATH 环境变量
b. /vendor/lib/hw
c. /system/lib/hw //4412开发板只会去这个目录下去查找,其他几个目录都没设置
property_get : 属性系统
属性<键,值> <name, value>
JNI 怎么使用 HAL
a. hw_get_module 获得一个hw_module_t结构体
b. 调用 module->methods->open(module, device_name, &device) //module里面有多个device
获得一个hw_device_t结构体
并且把hw_device_t结构体转换为设备自定义的结构体
HAL 怎么写
a. 实现一个名为HMI的hw_module_t结构体
b. 实现一个open函数, 它会根据name返回一个设备自定义的结构体
这个设备自定义的结构体的第1个成员是 hw_device_t结构体
还可以定义设备相关的成员
打印信息简介:
a. 有三类打印信息: app, system, radio
程序里使用 ALOGx, SLOGx, RLOGx来打印(分别对应应用打印信息、系统打印信息,Radio打印信息)
b. x表示6种打印级别,有:
V Verbose
D Debug
I Info
W Warn
E Error
F Fatal
比如:
#define LOG_TAG "LedHal"
ALOGI("led_open : %d", fd);
c. 打印出来的格式为:
I / LedHal ( 1987) : led_open : 65
(级别) LOG_TAG 进程号 打印信息
d. 在开发板上使用 logcat 命令查看 或者logcat LEDHAL:I *:S(过滤规则) 或者logcat | grep “LedHal”
logcat LedHal:I *:S//*.S表示其他信息不打印
过滤规则:<tag>[:priority]
实现led_hal.c
/*a. 实现一个名为HMI的hw_module_t结构体*/
/*b. 实现一个open函数, 它会根据name返回一个设备自定义的结构体led_device_t*/
/*c.实现led_device_t结构体*/
/*参看文件hardware\libhardware\modules\vibrator\vibrator.c*/
#define LOG_TAG "LedHal"//ALOGI会用到这个宏定义来打印,然后在打印信息中我们可以通过筛选Ledhal来区分不同的打印信息
#include <hardware/led_hal.h>
#include <hardware/hardware.h>
......还有很多头文件.........
static int fd;
static int led_open(struct led_device_t *dev)
{
fd = open("/dev/leds",O_RDWR);
ALOGI(“ ledOpen:%d”,fd);//打印
if(fd >=0)
return 0;
else
return -1;
}
static int led_close(struct led_device_t *dev){
close(fd);
return 0;
}
static int led_ctrl(struct led_device_t *dev,int which,int status)
{
int ret = ioctl(fd,status,which);
return ret;
}
static struct led_device_t led_dev = {
.common = {
.close = led_close ,
},
.led_open = led_open ,
.led_ctrl = led_ctrl ,
};
static int led_device_open(const struct hw_module_t *module,const char *id,struct hw_device_t **device)
{
//正常的做法是通过id找到led_device_t ,这里有位只有一个led_device_t,就没有查找了
*device = &led_dev //led_dev 的第一个成员就是hw_device_t ,他们地址一样
}
static struct hw_module_methods_t led_module_methods {
.open = led_device_open;
};
struct hw_module_t HAL_MODULE_INFO_SYM = {
//.tag = HARDWARE_MODULE_TAG,
//.module_api_version = ........,
//.hal_api_version = HARDWARE_HAL_API_VERSION,
.id = "led ",//JNI中通过hw_get_module('led')来获得hw_module_t
//.name =,
//.auth,
.methods = led_module_methods;
}
实现led_hal.h
#ifndef ANDROID_LED_INTERFACE_H
#define ANDROID_LED_INTERFACE_H
#include <stdint.h>
#include <sys/cdefs.h>
#include <sys/types.h>
#include <hardware/hardware.h>
__BEGIN_DECLS
struct led_device_t {
struct hw_device_t common;
int (*led_open)(struct led_device_t *dev);
int (*led_ctrl)(struct led_device_t *dev,int which,int status);
}
__END_DECLS
#endif
修改之前写的JNI文件com_android_server_LedService.cpp
#define LOG_TAG "LedService"
#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
#include <utils/misc.h>
#include <utils/Log.h>
#include <hardware_legacy/vibrator.h>
#include <stdio.h>
//还有一些头问题
#include <hardware/led_hal.h>
namespace android
{
static led_device_t* led_device;
jint ledOpen(JNIEnv *env,jobject cls)
{
jint err;
hw_module_t* module;
hw_device_t* device;
/*1、调用hw_get_module*/
err = hw_get_module("led",(hw_module_t const **)&module);
if(err == 0){
/*2、调用module->methods->open来get device*/
err = module->methods->open(module,NULL,&device)
if(err == 0){
led_device = (light_device_t *)device;
/*3、call led_open*/
return led_device ->led_open(led_device );
}else{
return -1;
}
}
return -1;
}
void ledClose(JNIEnv *env,jobject cls)
{
}
jint ledCtrl(JNIEnv *env,jobject cls,jint which,jint status)
{
return led_device->led_ctrl(led_device,which,status);
}
static const JNINativeMethod methods[] = {
{"native_ledOpen","()I",(void *)ledOpen},
{"native_ledClose","()V",(void *)ledClose},
{"native_ledCtrl","(II)I",(void *)ledCtrl},
};
int register_android_server_LedService(JNIEnv *env)
{
return jniRegisterNativeMethods(env,"com/android/server/LedService",methods,NELEM(methods));
}
}
上传编译:
(1)、JNI重新上传到
frameworks/base/services/core/jni/com_android_server_LedService.cpp
(2)、HAL:led_hal.h和led_hal.c
hardware/libhardware/include/hardware/led_hal.h
hardware/libhardware/modules/led/led_hal.c
hardware/libhardware/modules/led/Android.mk
Android.mk内容如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := led.default //指定了最后编译出来的模块是led.default.so,这就和前面分析的通过hw_get_module找so对应上了
LOCAL_MODULE_RELATIVE_PATH :=hw //指定了so存在的目录在/system/lib/hw下
LOCAL_C_INCLUDES := hardware/libhardware //头文件
LOCAL__SRC_FILES := led_hal.c //源文件
LOCAL_SHARED_LIBRARIES := liblog
LOCAL_MODULE_TAGS := eng
include $(BUILD_SHARED_LIBRARY)
编译:
mmm frameworks/base/services //编译JNI
mmm hardware/libhardware/modules/led //编译C库 led.default.so
make snod
./gen-img.sh
6.4 Android硬件访问服务编写HAL代码的更多相关文章
- 2.Android硬件访问服务编写系统代码【转】
本文转载自:https://blog.csdn.net/qq_33443989/article/details/76696772 版权声明:本文为博主(Tower)自学笔记,欢迎转载! :-) ...
- 6.2、Android硬件访问服务编写系统代码
1.实现接口文件给App使用,接口文件是应用程序查询获得服务时获得 使用AIDL(Android接口定义语言)来实现ILedService.java接口 定义ILedService.aidl inte ...
- 6.1、Android硬件访问服务之框架
1.通过前面led点亮的例子,其流程如下 Android app(java)(通过loadLibrary)——>C library(C库做如下事情)——>1.JNI_Onload 2.jn ...
- 6.5 Android硬件访问服务使用反射
1.前面的例子中App为了能够范问ILedService接口,把classes.jar导入到应用程序中,但是我们不想把classes编进apk包里面去,这样导致我们的apk程序会很大(解压缩apk会发 ...
- Android硬件访问服务中的HAL-查看打印的信息
JNI 向上提供本地函数,向下加载HAL文件并调用HAL的函数 HAL 负责访问驱动程序执行硬件操作. external\chromium_org\third_party\hwcplus\src\h ...
- 6.3 Android硬件访问服务APP代码
以下步骤是操作MainActivity类 1.导入包 import android.os.ILedService 2.添加成员变量 private ILedService iLedService = ...
- 硬件访问服务学习笔记_WDS
1.Android驱动框架App1 App2 App3 App4-------------------硬件访问服务-------------------JNI-------------------C库 ...
- LED硬件访问服务(2)——JNI/HAL
一.系统编程 1.SystemServer.java类中提供了main()方法,说明它是以一个进程的方式存在的,启动后直接执行其run() 2.注册服务ServiceManager.addServic ...
- 在Ubuntu上为Android系统的Application Frameworks层增加硬件访问服务(老罗学习笔记5)
在数字科技日新月异的今天,软件和硬件的完美结合,造就了智能移动设备的流行.今天大家对iOS和Android系统的趋之若鹜,一定程度上是由于这两个系统上有着丰富多彩的各种应用软件.因此,软件和硬件的关系 ...
随机推荐
- Es61
ECMAScript和JavaScript的关系 ECMAScript 6(以下简称ES6)是JavaScript语言的下一代标准,已经在2015年6月正式发布了.Mozilla公司将在这个标准的基础 ...
- SpringBoot与Dubbo的整合-zookeeper和监控中心搭建
对于Dubbo的应用已经是十分普遍,自从阿里巴巴开源以来,国内许多公司就采用了dubbo的架构来开发项目.不过再dubbo十分火的时候,突然就停止更新了, 只有当当网还在其基础进行了拓展(dubbox ...
- AMD规范(RequireJS)、CMD规范(SeaJS)、CommonJS(BravoJS)规范的辨析
首先,AMD,CMD,CommonJS都实现了文件模块化. 对于依赖的模块:AMD是提前执行:CMD是延迟执行: AMD是依赖前置,CMD是依赖就近: AMD官方解释:https://github.c ...
- jersey+jetty实现文件上传
服务配置与启动类 import org.glassfish.jersey.servlet.ServletContainer; import javax.ws.rs.Path; import org.e ...
- 小的时候.by小雷
小的时候,总是有很多想法. 想去做,却做不成. 因为,自己小,被父母约束着,被学校圈着,被老师教育着. 想买个小霸王游戏机,没钱.在父辈的眼中,"游戏" ,游戏室,电脑游戏 ...
- [React] Use the URL as the source of truth in React
In Single Page Apps we're used to fetch the data on event callbacks. That disables the capacity to u ...
- HDU 5188 zhx and contest(带限制条件的 01背包)
Problem Description As one of the most powerful brushes in the world, zhx usually takes part in all ...
- js36---函数嵌套
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/stri ...
- [NOI.AC#41]最短路 线性基
链接 题解 如果不加边,两个点之间的长度是唯一的(只能走最短路径),因为如果重复走,就异或掉了. 因此,先DFS预处理一下每个点到根的距离 \(d[x]\) ,那么 \(x,y\) 之间的距离为 $d ...
- NOPI 锁定Excel单元格不让编辑的方法
简介:原生态纯JavaScript 100大技巧大收集---你值得拥有 http://www.cnblogs.com/xl900912/p/4223629.html 从博客园上看都的关于JS的一些常见 ...