《深入浅出 - android系统移植与平台开发(十) - led hal案例分析》由会员分享,可在线阅读,更多相关《深入浅出 - android系统移植与平台开发(十) - led hal案例分析(14页珍藏版)》请在金锄头文库上搜索。
1、本文由兰州白癜风医院 http:/ 本文由兰州白癜风医院 http:/ 深入浅出深入浅出 - Android 系统移植与平台开发(十)系统移植与平台开发(十) - led HAL案例分析案例分析 通过前两节 HAL 框架分析和 JNI 概述,我们对 Android 提供的 Stub HAL 有了比较详细的了解了,下面我们来看下 led 的实例,写驱动点亮 led 灯,就如同写程序,学语言打印HelloWorld 一样,如果说打印 HelloWorld 是一门新语言使用的第一声吆喝,那么点亮 led灯就是我们学习 HAL 的一座灯塔,指挥我们在后面的复杂的 HAL 代码里准确找到方向。 LedH
2、AL 实例架构实例架构 上图描述了我们 Led 实例的框架层次: l LedDemo.java:是我们写的 Android 应用程序 l LedService.java: 是根据 Led HAL 封装的 Java 框架层的 API, 主要用于向应用层提供框架层 API,它属于 Android 的框架层 l libled_runtime.so:由于 Java 代码不能访问 HAL 层,该库是 LedService.java 对应的本地代码部分 l led.default.so:针对 led 硬件的 HAL 代码 LedDemo 通过 LedService 提供的框架层 API 访问 Led 设备
3、,LedService 对于 LedDemo应用程序而言是Led 设备的服务提供者, LedService运行在Dalvik中没有办法直接访问Led硬件设备,它只能将具体的 Led 操作交给本地代码来实现,通过 JNI 来调用 Led 硬件操作的封装库 libled_runtime.so,由 HAL Stub 框架可知,在 libled_runtime.so 中首先查找注册本文由兰州白癜风医院 http:/ 本文由兰州白癜风医院 http:/ 为 led 的硬件设备 module,找到之后保存其操作接口指针在本地库中等待框架层LedService 调用。led.default.so 是 HAL
4、 层代码,它是上层操作的具体实施者,它并不是一个动态库(也就是说它并没有被任何进程加载并链接),它只是在本地代码查找硬件设备module 时通过 ldopen”杀鸡取卵”找 module,返回该硬件 module 对应的 device 操作结构体中封装的函数指针。 其调用时序如下: Led HAL 实例代码分析实例代码分析 我们来看下 led 实例的目录结构: 本文由兰州白癜风医院 http:/ 本文由兰州白癜风医院 http:/ 主要文件如下: com.hello.LedService.cpp:它在 frameworks/services/jni 目录下,是的 Led 本地服务代码 led.
5、c:HAL 代码 led.h:HAL 代码头文件 LedDemo.java:应用程序代码 LedService.java:Led 框架层服务代码 在 Android 的源码目录下,框架层服务代码应该放在 frameworks/services/java/包名/目录下,由 Android 的编译系统统一编译生成 system/framework/services.jar 文件,由于我们的测试代码属于厂商定制代码,尽量不要放到 frameworks 的源码树里,我将其和 LedDemo应用程序放在一起了,虽然这种方式从 Android 框架层次上不标准。 另外,本地服务代码的文件名要和对应的框架层
6、 Java 代码的名字匹配(包名+类文件名,包目录用“_“代替)。有源码目录里都有对应的一个 Android.mk 文件,它是 Android 编译系统的指导文件,用来编译目标 module。 1) Android.mk 文件分析文件分析 先来看下 led 源码中号 Android.mk: include $(call all-subdir-makefiles) 代码很简单,表示包含当前目录下所有的 Android.mk 文件 先来看下 led_app 目录下的号 Android.mk: # 调用宏 my-dir,这个宏返回当前 Android.mk 文件所在的路径 LOCAL_PATH:=
7、$(call my-dir) # 包含 CLEAR_VARS 变量指向的 mk 文件 build/core/clear_vars.mk,它主要用来清除编译时依赖的编译变量 include $(CLEAR_VARS) # 指定当前目标的 TAG 标签,关于其作用见前面 Android 编译系统章节 LOCAL_MODULE_TAGS := user # 当前 mk 文件的编译目标模块 LOCAL_PACKAGE_NAME := LedDemo # 编译目标时依赖的源码,它调用了一个宏 all-java-files-under,该宏在build/core/definitions.mk 中定义 #
8、表示在当前目录下查找所有的 java 文件,将查找到的 java 文件返回 LOCAL_SRC_FILES := $(callall-java-files-under, src) # 在编译 Android 应用程序时都要指定 API level,也就是当前程序的编译平台版本 本文由兰州白癜风医院 http:/ 本文由兰州白癜风医院 http:/ # 这里表示使用当前源码的版本 LOCAL_SDK_VERSION := current # 最重要的就是这句代码,它包含了一个文件 build/core/package.mk,根据前面设置的编译变量,编译生成 Android 包文件,即:apk 文
9、件 include $(BUILD_PACKAGE) 上述代码中都加了注释,基本上每一个编译目标都有类似上述的编译变量的声明: LOCAL_MODULE_TAGS LOCAL_PACKAGE_NAME LOCAL_SRC_FILES 由于所有的 Android.mk 最终被编译系统包含,所以在编译每个目标模块时,都要通过LOCAL_PATH:= $(call my-dir)指定当前目标的目录,然后调用 include $(CLEAR_VARS)先清除编译系统依赖的重要的编译变量,再生成新的编译变量。 让我们来看看 LedDemo 目标对应的源码吧。 2) LedDemo 代码分析代码分析 学习
10、过 Android 应用的同学对其目录结构很熟悉,LedDemo 的源码在 src 目录下。 led_app/src/com/farsight/LedDemo.java: package com.hello; import com.hello.LedService; import com.hello.R; importandroid.app.Activity; importandroid.os.Bundle; importandroid.util.Log; importandroid.view.View; import android.view.View.OnClickListener; im
11、portandroid.widget.Button; public classLedDemo extends Activity privateLedService led_svc; private Buttonbtn; private booleaniflag = false; private Stringtitle; /* Calledwhen the activity is first created. */ Override public voidonCreate(Bundle savedInstanceState) 本文由兰州白癜风医院 http:/ 本文由兰州白癜风医院 http:/
12、 super.onCreate(savedInstanceState); setContentView(R.layout.main); Log.i(“Java App“, “OnCreate“); led_svc =new LedService(); btn =(Button) this.findViewById(R.id.Button01); this.btn.setOnClickListener(new OnClickListener() public void onClick(View v) Log.i(“Java App“, “btnOnClicked“); if (iflag) ti
13、tle = led_svc.set_off(); btn.setText(“Turn On“); setTitle(title); iflag = false; else title = led_svc.set_on(); btn.setText(“Turn Off“); setTitle(title); iflag = true; ); 代码很简单,Activity上有一个按钮,当 Activity初始化时创建 LedService 对象,按钮按下时通过 LedService 对象调用其方法 set_on()和 set_off()。 3) LedService 代码分析代码分析 我们来看下
14、LedService 的代码: led_app/src/com/farsight/LedService.java: package com.hello; import android.util.Log; public class LedService /* * loadnative service. 本文由兰州白癜风医院 http:/ 本文由兰州白癜风医院 http:/ */ static / 静态初始化语言块,仅在类被加载时被执行一次,通常用来加载库 Log.i (“Java Service“ , “Load Native Serivce LIB“ ); System.loadLibrary
15、 ( “led_runtime“ ); / 构造方法 publicLedService() int icount ; Log.i (“Java Service“ , “do init Native Call“ ); _init (); icount =_get_count (); Log.d (“Java Service“ , “led count = “ + icount ); Log.d (“Java Service“ , “Init OK “ ); /* * LED nativemethods. */ public Stringset_on() Log.i (“com.hello.LedService“ , “LED On“ ); _set_on(); retur