刚开始以为android 开发跟普通嵌入式开发差不多,无非加一个app和屏幕,然后和主应用程序或者kernel交互罢了。应该和以前做过的一些方案类似,比如加一个 goahead 做webui或者加一个 ucgui 做屏幕显示或者类似openwrt里面编译一个apk可以安装和卸载,或者类似 legato,应用层提供一系列service 给上层。所以我想架构应该是:
然后一看代码结构,有点茫然。问人查资料知,应用层或者框架层Java代码,通过JNI技术调用C或C++写的so库代码,在so库代码中调用底层驱动,从而实现上层应用操作底层硬件的目的。实现硬件操作的so库为module。
这里面有个重要概念,HAL层,硬件抽象层的代码会使用open read write等系统调用操作驱动层的文件系统(dev、sysfs、proc),同时它也有自己的数据结构,为上层提供接口,并导出和本体模块相关ID号。上层可以使用hw_get_module获得HAL中写的方法。
废话不多说,直接上例子,比较直观。
kernel层。在kernel\drivers\char\目录下加入 hello_k.c ,hello的驱动程序,修改目录下Makefile:
obj-y += hello_k.o
编译kernel,烧录kernel.img , 在文件系统里可以发现 /sys/class/hello/hello 和 /dev/hello 设备节点。
HAL 层。在hardware\libhardware\modules\下创建hello-hal目录,增加 hello-hal.c 和Android.mk文件。
在hello-hal.c中添加hello_device_open函数,去 open /dev/hello;hello_set_val函数去write /dev/hello; hello_get_val去read /dev/hello。这些函数其实在JNI 层直接读写/dev/hello也行,为什么不这样呢? 规避Linux的GPL开源协议吧, 这也许就是HAL层存在的一个原因。配置hello_device_t结构体:
struct hello_module_t HAL_MODULE_INFO_SYM = {
.common = {
.tag = HARDWARE_MODULE_TAG,
//.module_api_version = FINGERPRINT_MODULE_API_VERSION_2_0,
.hal_api_version = HARDWARE_HAL_API_VERSION,
.id = HELLO_HARDWARE_MODULE_ID,
.name = "Demo test hello HAL",
.author = "test",
.methods = &hello_module_methods,
},
};
另外还需创建对应头文件,hardware\libhardware\include\hardware\hello-hal.h,不做介绍。
编译: mmm hardware/libhardware/modules/hello-hal
生成: system/lib/hw/hello.default.so
JNI 层。对HAL层提供的方法进行“翻译”,并转化成 android runtime 的JNI方法表,当Java代码调用时候可以正确的寻找到 native 的代码。在 frameworks\base\services\core\jni\onload.cpp JNI_OnLoad函数中增加,注册hello 服务:
register_android_server_HelloService(env)
在frameworks\base\services\core\jni\ 目录下增加com_android_server_HelloService.cpp文件。这个文件里,创建了 hello_init函数,里面 hw_get_module 与HAL层进行衔接;创建hello_device_open函数调用 HAL层 hello_device_open 函数;创建hello_getVal函数调用HAL 层hello_get_val函数;hello_setVal 调用HAL层hello_set_val函数。配置结构体:
static const JNINativeMethod method_table[] = {
{"init_native", "()Z", (void*)hello_init},
{"setVal_native", "(I)V", (void*)hello_setVal},
{"getVal_native", "()I", (void*)hello_getVal},
};
在 frameworks\base\services\core\jni\Android.mk中增加:
com_android_server_HelloService.cpp \
编译: mmm frameworks/base/services/
生成: system/lib/libandroid_servers.so
通信代理 AIDL (Android Interface DefinitionLanguage)。如果在一个进程中(例如Activity)要调用另一个进程中(例如Service)对象的操作,就可以使用AIDL生成可序列化的参数。在core/java/android/os/下创建IHelloService.aidl, 建立aidl通信接口。
interface IHelloService {
void setVal(int val);
int getVal();
}
然后同时修改 frameworks\base\Android.mk,在 LOCAL_SRC_FILES += 下增加:
core/java/android/os/IHelloService.aidl \
编译: mmm frameworks/base
生成: system\framework\framework.jar
Service java。在frameworks/base/core/java/com/android/server/下创建HelloService.java:
import android.os.IHelloService; // IHelloService.aidl
public class HelloService extends IHelloService.Stub {
private static final String TAG = "HelloService";
HelloService() {
init_native(); //JNI层接口 hello_init
}
public void setVal(int val) {
setVal_native(val); //JNI层接口 hello_setVal
}
public int getVal() {
return getVal_native(); //JNI层接口 hello_getVal
}
private static native boolean init_native();
private static native void setVal_native(int val);
private static native int getVal_native();
};
修改frameworks\base\services\java\com\android\server\SystemServer.java,在system_server中注册hello_service到servicemanager:
ServiceManager.addService("hello", new HelloService()); //HelloService.java
编译: make update-api(新加了API, 需要更新 API doc) ; make -j12
生成: system.img
烧录后测试结果结果: service list | grep hello
service list | grep hello
27 hello: [android.os.IHelloService]
好了,现在就是android app client 的事情了,可参考 http://blog.csdn.net/luoshengyang/article/details/6580267。
以上代码:https://github.com/kinbo/note-for-work/tree/master/note-hd/andriod-hello
参考文章:
http://blog.csdn.net/eliot_shao/article/details/51888035 系列
https://www.jianshu.com/p/fa36e5faea67