




已阅读5页,还剩18页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
绿色箭头:表示插入SD卡后事件传递以及SD卡挂载红色箭头:表示挂载成功后的消息传递流程黄色箭头:表示MountService发出挂载/卸载SD卡的命令Android各层次调用流程概述2012-07-07 18:16:33Android的硬件抽象层: 简单来说,就是对Linux内核驱动程序的封装,向上提供接口,屏蔽低层的实现细节。 也就是说,把对硬件的支持分成了两层, 一层放在用户空间(User Space),(硬件抽象层) 一层放在内核空间(Kernel Space),(Linux内核驱动程序)下面这个图阐述了硬件抽象层在Android系统中的位置,以及它和其它层的关系:二,简单的总结进入到Android源代码工程的external目录,创建hello目录:cd externalmkdir hello在hello目录中新建Android.mk文件: LOCAL_PATH := $(callmy-dir) include $(CLEAR_VARS) LOCAL_MODULE_TAGS := optional LOCAL_MODULE :=hello LOCAL_SRC_FILES := $(call all-subdir-c-files) include $(BUILD_EXECUTABLE)注意,BUILD_EXECUTABLE表示我们要编译的是可执行程序。使用mmm命令进行编译: mmm ./external/hello 编译成功后,就可以在out/target/product/gerneric/system/bin目录下,看到可执行文件hello了。重新打包Android系统文件system.img: make snod 这样,重新打包后的system.img文件就包含刚才编译好的hello可执行文件了。 七. 运行模拟器,使用/system/bin/hello可执行程序来访问Linux内核驱动程序。 emulator -kernel ./kernel/common/arch/arm/boot/zImage & adb shell cd system/bin ./hello-三,编写硬件抽象层 进入到在hardware/libhardware/include/hardware目录,新建hello.h文件: cd hardware/libhardware/include/hardware vi hello.h hello.h文件的内容如下:#ifndef ANDROID_HELLO_INTERFACE_H#define ANDROID_HELLO_INTERFACE_H#include _BEGIN_DECLS/*定义模块ID*/#defineHELLO_HARDWARE_MODULE_IDhello/*硬件模块结构体*/structhello_module_t struct hw_module_tcommon;/*硬件接口结构体*/structhello_device_t structhw_device_t common; int fd; /设备文件描述符 int (*set_val)(struct hello_device_t* dev, int val); /为该HAL对上提供的函数接口 int (*get_val)(struct hello_device_t* dev, int* val);_END_DECLS#endif进入到hardware/libhardware/modules目录,新建hello目录,并添加hello.c文件。 hello.c的内容较多,我们分段来看。 首先是包含相关头文件和定义相关结构:#define LOG_TAG HelloStub #include #include #include #include #include #include #define DEVICE_NAME /dev/hello #define MODULE_NAME Hello #define MODULE_AUTHOR /*设备打开和关闭接口*/ static inthello_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t* device); static inthello_device_close(struct hw_device_t* device); /*设备访问接口*/ static inthello_set_val(struct hello_device_t* dev, int val); static inthello_get_val(struct hello_device_t* dev, int* val); /*模块方法表*/ static struct hw_module_methods_t hello_module_methods = open: hello_device_open ; /*模块实例变量*/ struct hello_module_t HAL_MODULE_INFO_SYM= common: tag:HARDWARE_MODULE_TAG, version_major: 1, version_minor: 0, id: HELLO_HARDWARE_MODULE_ID, name: MODULE_NAME, author: MODULE_AUTHOR, methods: &hello_module_methods, ; 实例变量名必须为HAL_MODULE_INFO_SYM, tag也必须为HARDWARE_MODULE_TAG。定义hello_device_open函数:static int hello_device_open( const struct hw_module_t* module, const char* name, struct hw_device_t* device ) struct hello_device_t* dev; dev = (struct hello_device_t*)malloc(sizeof(struct hello_device_t); if(!dev) LOGE(Hello Stub: failed to alloc space); return -EFAULT; memset(dev, 0, sizeof(struct hello_device_t); dev-common.tag = HARDWARE_DEVICE_TAG; dev-common.version = 0; dev-common.module = (hw_module_t*)module; dev-common.close = hello_device_close; dev-set_val = hello_set_val; dev-get_val = hello_get_val; if(dev-fd =open(DEVICE_NAME, O_RDWR) = -1) LOGE(Hello Stub: failed to open /dev/hello - %s., strerror(errno);free(dev); return -EFAULT; *device = &(dev-common); LOGI(Hello Stub: open /dev/hello successfully.); return 0; 定义hello_device_close、hello_set_val和hello_get_val这三个函数:static int hello_device_close(struct hw_device_t* device) struct hello_device_t* hello_device = (struct hello_device_t*)device; if(hello_device) close(hello_device-fd); free(hello_device); return 0; static int hello_set_val(struct hello_device_t* dev, int val) LOGI(Hello Stub: set value %d to device., val); write(dev-fd, &val, sizeof(val); return 0; static inthello_get_val(struct hello_device_t* dev, int* val) if(!val) LOGE(Hello Stub: error val pointer); return -EFAULT; read(dev-fd, val, sizeof(*val); LOGI(Hello Stub: get value %d from device, *val); return 0; 继续在hello目录下新建Android.mk文件: LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE_TAGS := optional LOCAL_PRELINK_MODULE := false LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw LOCAL_SHARED_LIBRARIES := liblog LOCAL_SRC_FILES := hello.c LOCAL_MODULE := hello.default include $(BUILD_SHARED_LIBRARY) 注意,LOCAL_MODULE的定义规则,hello后面跟有default,hello.default能够保证我们的模块总能被硬象抽象层加载到。编译: mmm hardware/libhardware/modules/hello 编译成功后,就可以在out/target/product/generic/system/lib/hw目录下看到hello.default.so文件了。重新打包Android系统镜像system.img: make snod 重新打包后,system.img就包含我们定义的硬件抽象层模块hello.default了。 虽然我们在Android系统为我们自己的硬件增加了一个硬件抽象层模块,但是现在Java应用程序还不能访问到我们的硬件。 我们还必须编写JNI方法和在Android的Application Frameworks层增加API接口,才能让上层Application访问我们的硬件。-四:JNI方法如何为Android硬件抽象层接口编写JNI方法,以便使得上层的Java应用程序能够使用下层提供的硬件服务。 一. 确保Android系统镜像文件system.img已经包含hello.default模块。 二. 进入到frameworks/base/services/jni目录,新建com_android_server_HelloService.cpp文件: cd frameworks/base/services/jni vi com_android_server_HelloService.cpp com_android_server前缀表示的是包名,表示硬件服务HelloService是放在frameworks/base/services/java目录下的com/android/server目录的,即存在一个命令为com.android.server.HelloService的类。首先是包含相应的头文件:#define LOG_TAG HelloService #include jni.h #include JNIHelp.h #include android_runtime/AndroidRuntime.h #include #include #include #include #include /* 接着定义hello_init、hello_getVal和hello_setVal三个JNI方法:*/namespace android /*在硬件抽象层中定义的硬件访问结构体,参考*/ struct hello_device_t* hello_device= NULL; /*通过硬件抽象层定义的硬件访问接口设置硬件寄存器val的值*/ static voidhello_setVal(JNIEnv* env, jobject clazz, jint value) int val = value; LOGI(Hello JNI: set value %d to device., val); if(!hello_device) LOGI(Hello JNI: device is not open.); return; hello_device-set_val(hello_device, val); / 在抽象层的open中定义 /*通过硬件抽象层定义的硬件访问接口读取硬件寄存器val的值*/ static jinthello_getVal(JNIEnv* env, jobject clazz) int val = 0; if(!hello_device) LOGI(Hello JNI: device is not open.); return val; hello_device-get_val(hello_device, &val); LOGI(Hello JNI: get value %d from device., val); return val; /*通过硬件抽象层定义的硬件模块打开接口 打开硬件设备*/ static inline int hello_device_open(const hw_module_t* module, struct hello_device_t* device) return module-methods-open(module, HELLO_HARDWARE_MODULE_ID, (struct hw_device_t*)device); /*通过硬件模块ID来加载指定的硬件抽象层模块并打开硬件*/ static jboolean hello_init(JNIEnv* env, jclass clazz) hello_module_t* module; LOGI(Hello JNI: initializing.); /*加载模块ID为HELLO_HARDWARE_MODULE_ID的硬件抽象层模块, Android硬件抽象层会根据HELLO_HARDWARE_MODULE_ID的值 * 在Android系统的/system/lib/hw目录中找到相应的模块,然后加载起来,并且返回hw_module_t接口给调用者使用。 */ if(hw_get_module(HELLO_HARDWARE_MODULE_ID, (const struct hw_module_t*)&module ) = 0) LOGI(Hello JNI: hello Stub found.); if(hello_device_open(&(module-common), &hello_device) = 0) LOGI(Hello JNI: hello device is open.); return 0; LOGE(Hello JNI: failed to open hello device.); return -1; LOGE(Hello JNI: failed to get hello stub module.); return -1; /*JNI方法表*/ static const JNINativeMethod method_table = init_native, ()Z, (void*)hello_init, setVal_native, (I)V, (void*)hello_setVal, getVal_native, ()I, (void*)hello_getVal, ; /*注册JNI方法*/ int register_android_server_HelloService(JNIEnv *env) return jniRegisterNativeMethods(env, com/android/server/HelloService, method_table, NELEM(method_table) ); /必须对应HelloService所在的包的路径 ; 在Android系统初始化时,使其自动加载该JNI方法调用表- 修改同目录下的onload.cpp文件, (1)在namespace android增加register_android_server_HelloService函数声明: namespace android . int register_android_server_HelloService(JNIEnv *env); ; (2)在JNI_onLoad增加register_android_server_HelloService函数调用: extern C jint JNI_onLoad(JavaVM* vm, void* reserved) . register_android_server_HelloService(env); . (3)修改同目录下的Android.mk文件,在LOCAL_SRC_FILES变量 中增加一行: LOCAL_SRC_FILES:= com_android_server_AlarmManagerService.cpp com_android_server_BatteryService.cpp com_android_server_InputManager.cpp com_android_server_LightsService.cpp com_android_server_PowerManagerService.cpp com_android_server_SystemServer.cpp com_android_server_UsbService.cpp com_android_server_VibratorService.cpp com_android_server_location_GpsLocationProvider.cpp com_android_server_HelloService.cpp / onload.cpp 最后编译 mmm frameworks/base/services/jni make snod 这样,重新打包的system.img镜像文件就包含我们刚才编写的JNI方法了, 我们可以通过Android系统的Application Frameworks层提供的硬件服务HelloService来调用这些JNI方法,进而调用低层的硬件抽象层接口去访问硬件了。五:提供Java访问硬件服务接口 Linux内核层、硬件抽象层和运行时库层提供的自定义硬件服务接口,这些接口都是通过C或者C+语言来实现的。 以下,我们将介绍如何在Android系统的Application Frameworks层提供Java接口的硬件服务。(为什么用代理?) 在Android系统中,硬件服务一般是运行在一个独立的进程中为各种应用程序提供服务。因此,调用这些硬件服务的应用程序与这些硬件服务之间的通信需要通过代理来进行。为此,我们要先定义好通信接口。(1)进入到frameworks/base/core/java/android/os目录,新增IHelloService.aidl接口定义文件: cd frameworks/base/core/java/android/os vi IHelloService.aidlIHelloService.aidl定义了IHelloService接口: package android.os; interface IHelloService voidsetVal(int val); int getVal( ); 该接口主要提供了设备获取硬件寄存器val的值的功能,分别通过setVal和getVal两个函数来实现。(2)返回到frameworks/base目录,打开Android.mk文件,修改LOCAL_SRC_FILES变量的值,增加IHelloService.aidl源文件: core/java/android/os/IHelloService.aidl /(3)编译IHelloService.aidl接口: mmm frameworks/base 这样,就会根据IHelloService.aidl生成相应的IHelloService.Stub接口。(4)进入到frameworks/base/services/java/com/android/server目录,新增HelloService.java文件:package com.android.server; import android.content.Context; import android.os.IHelloService; import android.util.Slog; public class HelloService extends IHelloService.Stub private static final String TAG = HelloService; HelloService() init_native(); public void setVal(int val) setVal_native(val); public int getVal() return getVal_native(); /*HelloService主要是通过调用JNI方法init_native、setVal_native和getVal_native来提供硬件服务 */ private static native boolean init_native(); private static native void setVal_native(int val); private static native int getVal_native(); ; (5) 修改同目录的SystemServer.java文件,在ServerThread:run函数中增加加载HelloService的代码: Override public voidrun() . try Slog.i(TAG, Hello Service); ServiceManager.addService(hello, newHelloService(); catch (Throwable e) Slog.e(TAG, Failure starting Hello Service, e); . (6)编译HelloService和重新打包system.img: mmm frameworks/base/services/java make snod 这样,重新打包后的system.img系统镜像文件就在Application Frameworks层中包含了我们自定义的硬件服务HelloService了,并且会在系统启动的时候,自动加载HelloService。 这时,应用程序就可以通过Java接口来访问Hello硬件服务了。-六:Java调用实例public class Hello extends Activityimplements OnClickListener private final static String LOG_TAG =shy.luo.renju.Hello;private IHelloService helloService = null;private EditText valueText = null;private Button readButton = null;private Button writeButton = null;private Button clearButton = null;/* Called when the activity is first created. */Overridepublic void onCreate(Bundle savedInstanceState) super.onCreate(save
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- Synuclein-alpha-Lys-13C6-15N2-生命科学试剂-MCE
- Silane-1a-3b-5E-7E-22E-9-10-secoergosta-5-7-10-19-22-tetraene-1-3-diyl-bis-oxy-bis-1-1-dimethylethyl-dimethyl-生命科学试剂-MCE
- sEH-IN-3-生命科学试剂-MCE
- 疫情消毒水防疫知识培训课件
- 2025年人机界面设计师资格考试试卷及答案
- 2025年化妆师专业知识考试题库(附答案)
- 2025年东营专技教育平台继续教育公需科目试题及答案
- 浙江省温州市平阳县鳌江镇第三中学九年级体育 第35次课 中华养生 修其德与运其智说课稿
- 湘教版七年级地理上第三章第二节世界的人种说课稿
- 《赢得-》(2015年山东青岛中考满分作文5篇)
- 2026厦门银行秋季校园招聘笔试备考题库及答案解析
- 接诉即办培训课件
- 湖南省九校联盟2026届高三上学期9月第一次联考历史试题(含答案)
- 2025年高压电工复审完整题库(附答案)
- 贷款居间合同免责协议6篇
- 建设工程监理合同(GF-2015-0212)2025版
- 高职院校校企合作实习管理方案
- 主题活动四 健康友谊助成长说课稿-2025-2026学年小学综合实践活动苏少版新疆专用2024三年级上册-苏少版(新疆专用2024)
- (零模)苏州市2026届高三年级期初阳光调研试卷 物理试卷(含答案)
- 2025贵州民航产业集团有限公司招聘120人考试参考题库及答案解析
- 光伏电站安全培训课件
评论
0/150
提交评论