如何封装HAL API以及对应的JAVA API
2014-02-27 15:13
387 查看
如何封装HAL API以及对应的JAVA
API
Abstraction Layer)层。主要作用就是通过这一层给上层提供不变的API,如果硬件有所改变,只需要修改HAL的实现,大部分情况下可以保持提供给上层的API不会变化。这样硬件的改变后,上层的软件不需要改就可以继续工作。
图1 包含HAL层的Android架构
下面以led为例介绍如何封装HAL
结构图:
通过宏TARGET_PRODUCT选择编译哪一个led文件。led_stub.c里面只有空的函数定义没有实现,提供给用户实现自己的led
HAL驱动,这也是stub(桩)的含义。
set_led_state函数就是led
hal提供给上层的API。
在这个例子中,set_led_state函数接受的颜色参数是colorARGB,不过我们的硬件只认识红色和绿色,如果设置为0就是红色,1就是绿色,那么我们就要把colorARGB转换成0或者1,然后调用linux驱动去设置。
设置的过程就是通过调用linux对设备文件的写入而实现,设备文件就是:
const char* const COLOR_FILE = "/sys/class/leds/left/color";
还有其他的设备文件,用来设置其他的属性:
const char* const CADENCE_FILE = "/sys/class/leds/left/cadence";
const char* const BT_WIFI_FILE = "/sys/class/leds/right/brightness";
Native Interface)。上层的java程序会定义一些函数为native的,意思是这些函数将在其他的语言中实现,比如c。然后在c中实现这些函数,然后通过jni注册为java所声明的函数,这样java调用native函数就会调用对应的c/c++函数。
app使用的API封装。
package android.os;
注意函数申明的前缀”native”,注意类名android.os.Hardware(package
android.os)。
类的路径名就是类名android.os.hardware,在java应用程序中引用的话,用语句:
定制的包可以放在: Android\Frameworks\base\core\java\com\huawei(或者google等等)
比如Android\Frameworks\base\core\java\com\huawei\android\debug\JNITest.java
用包的时候用语句:
把set_led_state封装成setLedState,加了参数,所加的参数就是为了和上层java程序联系用的。
把c的函数指针放到一个数组里面,方便批量的注册。第一个参数”setLedState”要和java声明的函数名称一样。第二个参数"(III)I",表示setLedState函数有3个int参数,返回值是int。第三个参数是c/c++函数指针。
Android/os/Hardware是java的类名。
数组gRegJNI[]保存了所有注册JNI的函数,在android启动的时候会依次调用,把所有系统需要的Native函数都注册到虚拟机中。我们的register_android_os_Hardware函数自然要放在其中。
函数jniRegisterNativeMethods是jni的标准函数,作用是把c函数注册到JNI中。这样java
API就和HAL提供的API联系起来了。
最后用一幅图来描述调用关系
API
HAL
Android与硬件访问有关的文件都在hardware目录中,组成了所谓的HAL(HardwareAbstraction Layer)层。主要作用就是通过这一层给上层提供不变的API,如果硬件有所改变,只需要修改HAL的实现,大部分情况下可以保持提供给上层的API不会变化。这样硬件的改变后,上层的软件不需要改就可以继续工作。
图1 包含HAL层的Android架构
下面以led为例介绍如何封装HAL
API以及对应的JAVA API
结构图:Android\hardware\libhardware\led\Android.mk
ifeq ($(TARGET_PRODUCT),sooner) LOCAL_SRC_FILES += led/led_sardine.c else ifeq ($(TARGET_PRODUCT),dream) LOCAL_SRC_FILES += led/led_trout.c else LOCAL_SRC_FILES += led/led_stub.c endif endif
通过宏TARGET_PRODUCT选择编译哪一个led文件。led_stub.c里面只有空的函数定义没有实现,提供给用户实现自己的led
HAL驱动,这也是stub(桩)的含义。
Android\hardware\libhardware\include\hardware\led.h
int set_led_state(unsigned colorARGB, int onMS, int offMS);set_led_state函数就是led
hal提供给上层的API。
Android\hardware\libhardware\led\led_sardine.c
实现set_led_state函数,set_led_state主要做的工作很简单,就是把上层应用传递进来的参数进行转换,然后通过调用linux驱动,把参数设置到硬件上。在这个例子中,set_led_state函数接受的颜色参数是colorARGB,不过我们的硬件只认识红色和绿色,如果设置为0就是红色,1就是绿色,那么我们就要把colorARGB转换成0或者1,然后调用linux驱动去设置。
设置的过程就是通过调用linux对设备文件的写入而实现,设备文件就是:
const char* const COLOR_FILE = "/sys/class/leds/left/color";
还有其他的设备文件,用来设置其他的属性:
const char* const CADENCE_FILE = "/sys/class/leds/left/cadence";
const char* const BT_WIFI_FILE = "/sys/class/leds/right/brightness";
HAL提供的API如何被java程序所使用
Android的app是java实现的,那么要调用c语言或者c++语言实现的HAL的接口需要借助java的一种机制--JNI(JavaNative Interface)。上层的java程序会定义一些函数为native的,意思是这些函数将在其他的语言中实现,比如c。然后在c中实现这些函数,然后通过jni注册为java所声明的函数,这样java调用native函数就会调用对应的c/c++函数。
上层java 声明的API
搜索函数名setLedState,可以找到javaapp使用的API封装。
package android.os;
Android\Frameworks\base\core\java\android\os\hardware.java
/** * {@hide} */ public class Hardware { /** * Control the LED. */ public static native int setLedState(int colorARGB, int onMS, int offMS); ….. }
注意函数申明的前缀”native”,注意类名android.os.Hardware(package
android.os)。
类的路径名就是类名android.os.hardware,在java应用程序中引用的话,用语句:
import android.os.hardware
定制的包可以放在: Android\Frameworks\base\core\java\com\huawei(或者google等等)
比如Android\Frameworks\base\core\java\com\huawei\android\debug\JNITest.java
用包的时候用语句:
import com.huawei.android.debug
Android\Frameworks\base\core\jni\android_os_Hardware.cpp
static jboolean setLedState(JNIEnv *env, jobject clazz, jint colorARGB, jint onMS, jint offMS) { return set_led_state(colorARGB, onMS, offMS); }
把set_led_state封装成setLedState,加了参数,所加的参数就是为了和上层java程序联系用的。
static JNINativeMethod g_methods[] = { /* name, signature, funcPtr */ { "setLedState", "(III)I", (void*)setLedState }, { "getFlashlightEnabled", "()Z", (void*)getFlashlightEnabled }, { "setFlashlightEnabled", "(Z)V", (void*)setFlashlightEnabled }, { "enableCameraFlash", "(I)V", (void*)enableCameraFlash }, { "setScreenBacklight", "(I)V", (void*)setScreenBacklight }, { "setKeyboardBacklight", "(Z)V", (void*)setKeyboardBacklight }, { "setButtonBacklight", "(Z)V", (void*)setButtonBacklight }, };
把c的函数指针放到一个数组里面,方便批量的注册。第一个参数”setLedState”要和java声明的函数名称一样。第二个参数"(III)I",表示setLedState函数有3个int参数,返回值是int。第三个参数是c/c++函数指针。
int register_android_os_Hardware(JNIEnv* env) { return AndroidRuntime::registerNativeMethods(env, "android/os/Hardware", g_methods, NELEM(g_methods)); }
Android/os/Hardware是java的类名。
Android\Frameworks\base\core\jni\AndroidRuntime.cpp
static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_os_Binder), REG_JNI(register_android_os_Hardware), …… }
数组gRegJNI[]保存了所有注册JNI的函数,在android启动的时候会依次调用,把所有系统需要的Native函数都注册到虚拟机中。我们的register_android_os_Hardware函数自然要放在其中。
/* * Register native methods using JNI. */ /*static*/ int AndroidRuntime::registerNativeMethods(JNIEnv* env, const char* className, const JNINativeMethod* gMethods, int numMethods) { return jniRegisterNativeMethods(env, className, gMethods, numMethods); }
函数jniRegisterNativeMethods是jni的标准函数,作用是把c函数注册到JNI中。这样java
API就和HAL提供的API联系起来了。
最后用一幅图来描述调用关系
相关文章推荐
- java基本数据类型、对应的封装类以及字符串之间的相互转换
- 如何在Eclipse中查看Java类库的源代码以及相应的api
- hbase初识---hbase shell操作以及对应java API开发
- 如何轻松 查看Java API ,以及Android API源码(免去翻墙的痛苦)
- javaAPI深入理解(1)如何截短一个List以及List.subList()方法的坑
- 如何在Eclipse中查看Java类库的源代码以及相应的api
- 如何在Eclipse中查看Java类库的源代码以及相应的api
- 如何在Eclipse中查看Java类库的源代码以及相应的api
- 品味Java如何封装Window GUI API
- MyBatis之八:需要说明的几个java api的生命周期以及封装
- 黑马程序员----什么是java,面型对象的思想以及如何为编写java程序配置相对应的环境
- javaAPI深入理解(1)如何截断一个List以及List.subList()方法的坑
- 如何开发一个java开源框架-----Jvn框架之实现文件的上传以及方法封装(第六讲)八哥实力讲解
- 如何在Eclipse中查看Java类库的源代码以及相应的api
- java反射:数据类型及返回值对应的类类型以及Class类的基本API
- java 与mysql对应类型以及MySQl基本语法
- java中如何遍历实体类的属性和数据类型以及属性值
- 《徐徐道来话Java》(2):泛型和数组,以及Java是如何实现泛型的
- 【JavaWeb-20】3种对象状态以及相互转化、一级缓存和快照、Session其他API、一对多配置和操作、cascade
- Java中如何封装自己的类,建立并使用自己的类库?