Android应用层到Framework到HAL再到驱动层的整个流程分析 | 您所在的位置:网站首页 › 安卓5层 › Android应用层到Framework到HAL再到驱动层的整个流程分析 |
本篇参考老罗的实例进行总结。老罗写六篇,层层嵌套,他告诉了我们流程,但没有说编程思想,所以,即使知道怎么做也很快会忘调,因此打算总结下每层之间是怎么调用的,以加深印象。不对细节进行探讨。细节可以参见老罗的blog:http://blog.csdn.net/luoshengyang/article/details/6567257 老罗的分析是从驱动到应用层的,但我想从app开发者的角度去反思这个流程,我反过来说吧。 Tips:老罗这个例子,太多hello相关的函数和类了,要区分的话,目录是个好东西!要注意当前说的层在哪个目录!我会把它加粗。 Tips2:封装是理清各层关系的关键,除了驱动,上面的app/framework(JNI)/HAL层主要工作都是封装。 应用层->Framwork层->HAL层 问题一.作为app开发者,如果我想调用硬件驱动的一个功能,我要怎么做?1.先按常规办法,做好UI界面。可以IDE中调试好。 2.在事件触发函数里,调用SystemService,获取底层的服务,并把它转化为aidl接口 [javascript] view plain copy import android.os.IHelloService; public class Hello extends Activity implements OnClickListener { private IHelloService helloService = null; ..... public void onCreat(Bundle savedInstanceState){ ..... helloService = IHelloService.Stub.asInterface( ServiceManager.getService("hello")); ..... } } 3.在onClick函数里调用该接口,让service执行目标功能。 [cpp] view plain copy public void onClick(View v) { ..... helloService.setVal(val); ..... } 问题二.如果要在SDK源码里测试,有什么要注意?——Android.mk1.在SDK里,aidl文件,会产生在out/target/common/obj目录下,自己去搜吧(参照http://blog.csdn.net/xzongyuan/article/details/38119551) 2.如果你在Eclipse上写aidl文件,会产生在apk源码目录的gen下。因此,如果要把源码复制到SDK,要把gen目录删掉,不然这个目录会生成aidl相关的java文件,会和第一步生成的产生冲突。 3.在源码目录新增加Android.mk,这样SDK编译的时候,才会把该源码编译进去。例如:可以把自己的测试代码放到:/package/experimental/hello 下,并在该目录新增Android.mk,这点可以查看兄弟目录的文件结构。 Android.mk的文件内容如下: LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE_TAGS := optional LOCAL_SRC_FILES := $(call all-subdir-java-files) LOCAL_PACKAGE_NAME := Hello include $(BUILD_PACKAGE) 问题三.要怎样设计一个IHelloService供上层调用?1.进入到frameworks/base/core/java/android/os目录,新增IHelloService.aidl接口定义文件: USER-NAME@MACHINE-NAME:~/Android$ cd frameworks/base/core/java/android/os USER-NAME@MACHINE-NAME:~/Android/frameworks/base/core/java/android/os$ vi IHelloService.aidl IHelloService.aidl定义了IHelloService接口: [cpp] view plain copy package android.os; interface IHelloService { void setVal(int val); int getVal(); } 2.为啥必须是os文件夹下呢?android下级目录还有很多其它目录,我猜测应该都可以放进去的。只需要你改下/framework/base下的Android.mk,可见Android.mk在SDK里面是很重要的,它是个组织文件的Makefile。例子: 返回到frameworks/base目录,打开Android.mk文件,修改LOCAL_SRC_FILES变量的值,增加IHelloService.aidl源文件 [cpp] view plain copy LOCAL_SRC_FILES += / .................................................................... core/java/android/os/IVibratorService.aidl / core/java/android/os/IHelloService.aidl / core/java/android/service/urlrenderer/IUrlRendererService.aidl / ..................................................................... 编译后,会生成 IHelloService.java(就是上面提到的/out/target/common下的目录),这个文件的IHelloService接口,会实现一个Stub子接口,该子接口提供了一个函数, [cpp] view plain copy public static com.styleflying.AIDL.forActivity asInterface(android.os.IBinder obj) { if ((obj==null)) { return null; }这个函数就是前面提到的供Activity用的asInterface了。 activity里的使用方法如下,把具体的服务调出来了: [cpp] view plain copy helloService = IHelloService.Stub.asInterface( ServiceManager.getService("hello")); 3.这个IHelloService对象应该放在哪里?定一个类,继承它,并封装它的函数,最后把它注册到ServiceManager就行了 进入到frameworks/base/services/java/com/android/server目录,新增HelloService.java文件: [cpp] view plain copy 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"; /*封装IHelloService接口的函数*/ HelloService() { init_native(); } public void setVal(int val) { setVal_native(val); } public int getVal() { return getVal_native(); } private static native boolean init_native(); |
CopyRight 2018-2019 实验室设备网 版权所有 |