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
  1. import android.os.IHelloService;  
  2. public class Hello extends Activity implements OnClickListener {   
  3.    private IHelloService helloService = null;  
  4.     .....  
  5.    public void onCreat(Bundle savedInstanceState){  
  6.     .....  
  7.        helloService = IHelloService.Stub.asInterface( ServiceManager.getService("hello"));   
  8.     .....  
  9.   }  
  10. }  
3.在onClick函数里调用该接口,让service执行目标功能。
  1. public void onClick(View v) {   
  2.   .....  
  3.   helloService.setVal(val);  
  4.   .....  
  5. }  

问题二.如果要在SDK源码里测试,有什么要注意?——Android.mk

1.在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接口:

  1. package android.os;    
  2.      
  3. interface IHelloService {    
  4.     void setVal(int val);    
  5.     int getVal();    
  6. }    
2.为啥必须是os文件夹下呢?android下级目录还有很多其它目录,我猜测应该都可以放进去的。只需要你改下

/framework/base下的Android.mk,可见Android.mk在SDK里面是很重要的,它是个组织文件的Makefile。例子:

返回到frameworks/base目录,打开Android.mk文件,修改LOCAL_SRC_FILES变量的值,增加IHelloService.aidl源文件

  1. LOCAL_SRC_FILES += /  
  2.   
  3.    ....................................................................  
  4.   
  5.    core/java/android/os/IVibratorService.aidl /  
  6.   
  7.    core/java/android/os/IHelloService.aidl /  
  8.   
  9.    core/java/android/service/urlrenderer/IUrlRendererService.aidl /  
  10.   
  11.    .....................................................................  

编译后,会生成 IHelloService.java(就是上面提到的/out/target/common下的目录),这个文件的IHelloService接口,会实现一个Stub子接口,该子接口提供了一个函数,
  1. public static com.styleflying.AIDL.forActivity asInterface(android.os.IBinder obj)    
  2. {    
  3.    if ((obj==null)) {    
  4.    return null;    
  5. }    

这个函数就是前面提到的供Activity用的asInterface了。

activity里的使用方法如下,把具体的服务调出来了:

  1. helloService = IHelloService.Stub.asInterface( ServiceManager.getService("hello"));   

3.这个IHelloService对象应该放在哪里?

定一个类,继承它,并封装它的函数,最后把它注册到ServiceManager就行了

进入到frameworks/base/services/java/com/android/server目录,新增HelloService.java文件:

  1. <span><span class="keyword">package</span><span> com.android.server;  </span></span><span><span class="keyword">  
  2. import</span><span> android.content.Context;  </span></span><span><span></span></span><span><span class="keyword">  
  3. import</span><span> android.os.IHelloService;  </span></span><span></span><span><span class="keyword">  
  4. import</span><span> android.util.Slog;    
  5. </span></span>public class HelloService extends IHelloService.Stub {    
  6.     private static final String TAG = "HelloService";    
  7.     /*封装IHelloService接口的函数*/  
  8.     HelloService() {      
  9.         init_native();    
  10.     }    
  11.     public void setVal(int val) {    
  12.         setVal_native(val);    
  13.     }       
  14.     public int getVal() {    
  15.         return getVal_native();    
  16.     }    
  17.         
  18.     private static native boolean init_native();    
  19.     
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值