主要内容:
1. HAL and JNI 框架
2. HAL 介绍3. JNI 介绍
1. HAL and JNI 框架
2. HAL 介绍
在 Android 原始码里,HAL 主要的实作储存于以下目录:
1-. libhardware_legacy/ - 过去的实作、采取链接库模块的观念进行
2-. libhardware/ - 新版的实作、调整为 HAL stub 的观念
Hardware/libhardware/include/hardware/hardware.hHardware/libhardware/hardware.c
3-. ril/ - Radio Interface Layer
HAL stuct define:
Hardware/libhardware/include/hardware/hardware.h
int hw_get_module(const char *id, const struct hw_module_t **module);
int hw_get_module_by_class(const char *class_id, const char *inst,
const struct hw_module_t **module);
Hardware/libhardware/hardware.c :
硬件 抽象 层 模块 文件 的 命名 规范 为“< MODULE_ ID>. variant. so”
HAL使用方法:
(1)Native code通过hw_get_module调 用获取HAL stub:
hw_get_module (LED_HARDWARE_MODULE_ID, (const hw_module_t**)&module)
(2)通过继承hw_module_methods_t的callback来 open设备:
module->methods->open(module, LED_HARDWARE_MODULE_ID, (struct hw_device_t**)device);
(3)通过继承 hw_device_t的callback来控制设备:
sLedDevice->set_on(sLedDevice, led);sLedDevice->set_off(sLedDevice, led);
HAL的加载过程:
Hardware/libhardware/hardware.c :
模块加载过程:hw_get_module(XXX_HARDWARE_MODULE_ID, (const hw_module_t**)&module)
依次在/system/lib/hw和/vendor/lib/hw目录中检查是否存在相应的“
其中,variant分别等于属性“ro.hardware”、“ro.product.board”、“ro.board.platform”和“ro.arch”的值。
只要其中一个存在,即停止查找。
如果上述文件均不存在,则继续在/system/lib/hw目录中检查 “
调用dlopen打开上述找到的so文件。
调用dlsys获得上述打开的so文件里面的符号HAL_MODULE_INFO_SYM。
将符号HAL_MODULE_INFO_SYM强制转换为一个hw_moudle_t结构体。
HAL 驱动例子— Sensor HAL:
hardware/moto/sensors/XX_hal/SensorHal.cpp
static struct hw_module_methods_t sensors_module_methods = {
open: open_sensors };
struct sensors_module_t HAL_MODULE_INFO_SYM = {
common: {
tag: HARDWARE_MODULE_TAG,
version_major: 1,
version_minor: 0,
id: SENSORS_HARDWARE_MODULE_ID,
name: "Motorola Sensors Module",
author: "Motorola",
methods: &sensors_module_methods,
dso: NULL,
reserved: {0}, },
get_sensors_list: sensors__get_sensors_list,
set_operation_mode: sensors__set_operation_mode };
3. JNI 介绍
3.1 什么是JNI
在Android Framework 中,需要提供一种媒介或桥梁,将Java 层(上层)与C\C++层(底层)有机联系起来,使得他们相互协调,共同完成某些任务,充当该桥梁的就是Java本地接口JNI(Java Native Interface)。它允许Java代码与基于C/C++编写的应用程序和库进行交互操作。
3.2 什么情况下要用到JNI
1)注重处理速度
与本地代码C/C++相比,Java的代码执行速度要慢一些,如果对程序的执行速度有较高的要求,建议用C\C++编写代码,然后在Java中通过JNI调用基于C/C++编写的部分
2)硬件控制
为了更好地控制硬件,硬件代码通常用C语言编写,然后借助JNI将其与Java层连接起来,从而实现对硬件 的控制
3)既有C/C++代码的复用
在程序编写的过程中,常常有一些已经编写好的C/C++代码,既提高了编程效率,又确保了程序的安全性和健壮性。在复用这些C/C++代码时就要通过JNI来实现
3.3 Java代码中通过JNI调用C函数
在Java代码中通过JNI调用C函数的步骤如下:
第一步:编写Java代码
第二步:编译Java代码
第三步:生成C语言头文件
第四步:编写C代码
第五步:生成C共享库
第六步:运行Java程序
3.4 通过JNI注册本地方法完成映射
3.5 JNI--Sensor
JAVA中定义JNI NATIVE 接口 :
/frameworks/base/core/java/android/hardware/SystemSensorManager.java
private static native void nativeClassInit();
private static native long nativeCreate(String opPackageName);
private static native boolean nativeGetSensorAtIndex(long nativeInstance,
Sensor sensor, int index);
private static native void nativeGetDynamicSensors(long nativeInstance, List
private static native boolean nativeIsDataInjectionEnabled(long nativeInstance);
private static native int nativeCreateDirectChannel(
long nativeInstance, long size, int channelType, int fd, HardwareBuffer buffer);
private static native void nativeDestroyDirectChannel( )
C++中实现JAVA中定义的NATIVE接口,并与JAVA中定义的方法进行映射 :
/frameworks/base/core/jni/android_hardware_SensorManager.cpp
static const JNINativeMethod gSystemSensorManagerMethods[] = {
{"nativeClassInit", "()V", (void*)nativeClassInit },
{"nativeCreate", "(Ljava/lang/String;)J", (void*)nativeCreate },
{"nativeGetSensorAtIndex", "(JLandroid/hardware/Sensor;I)Z",
(void*)nativeGetSensorAtIndex },
{"nativeGetDynamicSensors","(JLjava/util/List;)V",
(void*)nativeGetDynamicSensors },
{"nativeIsDataInjectionEnabled", "(J)Z",
(void*)nativeIsDataInjectionEnabled },
C++中注册NATIVE方法 :
int register_android_hardware_SensorManager(JNIEnv *env)
{
RegisterMethodsOrDie(env, "android/hardware/SystemSensorManager",
gSystemSensorManagerMethods, NELEM(gSystemSensorManagerMethods));
return 0;
}