led HAL简单案例分析

CSDN Android客户端 下载就送50C币      又见人月神话      最流行的语言想学就学      写博文,传代码,送C币    
 

深入浅出 - Android系统移植与平台开发(十) - led HAL简单设计案例分析

分类: Android移植   9872人阅读  评论(18)  收藏  举报
android java jni module 平台

目录(?)[+]


通过前两节HAL框架分析和JNI概述,我们对Android提供的Stub HAL有了比较详细的了解了,下面我们来看下led的实例,写驱动点亮led灯,就如同写程序,学语言打印HelloWorld一样,如果说打印HelloWorld是一门新语言使用的第一声吆喝,那么点亮led灯就是我们学习HAL的一座灯塔,指挥我们在后面的复杂的HAL代码里准确找到方向。

 LedHAL实例架构


上图描述了我们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设备,LedService对于LedDemo应用程序而言是Led设备的服务提供者,LedService运行在Dalvik中没有办法直接访问Led硬件设备,它只能将具体的Led操作交给本地代码来实现,通过JNI来调用Led硬件操作的封装库libled_runtime.so,由HAL Stub框架可知,在libled_runtime.so中首先查找注册为led的硬件设备module,找到之后保存其操作接口指针在本地库中等待框架层LedService调用。led.default.so是HAL层代码,它是上层操作的具体实施者,它并不是一个动态库(也就是说它并没有被任何进程加载并链接),它只是在本地代码查找硬件设备module时通过ldopen”杀鸡取卵”找module,返回该硬件module对应的device操作结构体中封装的函数指针。

其调用时序如下:


Led HAL实例代码分析

我们来看下led实例的目录结构:


主要文件如下:

com.hello.LedService.cpp:它在frameworks/services/jni目录下,是的Led本地服务代码

led.c:HAL代码

led.h:HAL代码头文件

LedDemo.java:应用程序代码

LedService.java:Led框架层服务代码

在Android的源码目录下,框架层服务代码应该放在frameworks/services/java/包名/目录下,由Android的编译系统统一编译生成system/framework/services.jar文件,由于我们的测试代码属于厂商定制代码,尽量不要放到frameworks的源码树里,我将其和LedDemo应用程序放在一起了,虽然这种方式从Android框架层次上不标准。

另外,本地服务代码的文件名要和对应的框架层Java代码的名字匹配(包名+类文件名,包目录用“_“代替)。有源码目录里都有对应的一个Android.mk文件,它是Android编译系统的指导文件,用来编译目标module。

1)        Android.mk文件分析

先来看下led源码中①号Android.mk:

[plain]  view plain copy
  1. include $(call all-subdir-makefiles)  

代码很简单,表示包含当前目录下所有的Android.mk文件

先来看下led_app目录下的③号Android.mk:

[plain]  view plain copy
  1. # 调用宏my-dir,这个宏返回当前Android.mk文件所在的路径  
  2. LOCAL_PATH:= $(call my-dir)                                       
  3.   
  4. # 包含CLEAR_VARS变量指向的mk文件build/core/clear_vars.mk,它主要用来清除编译时依赖的编译变量  
  5. include $(CLEAR_VARS)                                      
  6.   
  7. # 指定当前目标的TAG标签,关于其作用见前面Android编译系统章节  
  8. LOCAL_MODULE_TAGS := user  
  9.   
  10. # 当前mk文件的编译目标模块  
  11. LOCAL_PACKAGE_NAME := LedDemo  
  12.   
  13. # 编译目标时依赖的源码,它调用了一个宏all-java-files-under,该宏在build/core/definitions.mk中定义  
  14. # 表示在当前目录下查找所有的java文件,将查找到的java文件返回  
  15. LOCAL_SRC_FILES := $(callall-java-files-under, src)  
  16.   
  17. # 在编译Android应用程序时都要指定API level,也就是当前程序的编译平台版本  
  18. # 这里表示使用当前源码的版本  
  19. LOCAL_SDK_VERSION := current  
  20.   
  21. # 最重要的就是这句代码,它包含了一个文件build/core/package.mk,根据前面设置的编译变量,编译生成Android包文件,即:apk文件  
  22. 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代码分析

学习过Android应用的同学对其目录结构很熟悉,LedDemo的源码在src目录下。

@ led_app/src/com/farsight/LedDemo.java:

[java]  view plain copy
  1. package com.hello;  
  2.   
  3.  import com.hello.LedService;  
  4.   
  5.  import com.hello.R;  
  6.   
  7.  importandroid.app.Activity;  
  8.   
  9.  importandroid.os.Bundle;  
  10.   
  11.  importandroid.util.Log;  
  12.   
  13.  importandroid.view.View;  
  14.   
  15.  import android.view.View.OnClickListener;  
  16.   
  17.  importandroid.widget.Button;  
  18.   
  19.    
  20.   
  21.  public classLedDemo extends Activity {  
  22.      privateLedService led_svc;  
  23.      private Buttonbtn;  
  24.      private booleaniflag = false;  
  25.      private Stringtitle;  
  26.   
  27.       /** Calledwhen the activity is first created. */  
  28.      @Override  
  29.      public void onCreate(Bundle savedInstanceState) {  
  30.         super.onCreate(savedInstanceState);  
  31.         setContentView(R.layout.main);  
  32.   
  33.         Log.i("Java App""OnCreate");  
  34.          led_svc =new LedService();  
  35.          btn =(Button) this.findViewById(R.id.Button01);  
  36.         this.btn.setOnClickListener(new OnClickListener() {  
  37.             public void onClick(View v) {  
  38.                 Log.i("Java App""btnOnClicked");  
  39.                 if (iflag) {  
  40.                     title = led_svc.set_off();  
  41.                     btn.setText("Turn On");  
  42.                     setTitle(title);  
  43.                     iflag = false;  
  44.                 } else {  
  45.                     title = led_svc.set_on();  
  46.                     btn.setText("Turn Off");  
  47.                     setTitle(title);  
  48.                     iflag = true;  
  49.                 }  
  50.              }  
  51.          });  
  52.      }  
  53.  }  

代码很简单,Activity上有一个按钮,当Activity初始化时创建LedService对象,按钮按下时通过LedService对象调用其方法set_on()和set_off()。

 

3)        LedService代码分析

我们来看下LedService的代码:

@led_app/src/com/farsight/LedService.java:

[java]  view plain copy
  1. package com.hello;  
  2. import android.util.Log;  
  3.   
  4. public class LedService {  
  5.   
  6.     /* 
  7.      * loadnative service. 
  8.      */  
  9.     static {         // 静态初始化语言块,仅在类被加载时被执行一次,通常用来加载库  
  10.         Log.i ("Java Service" , "Load Native Serivce LIB" );  
  11.        System.loadLibrary ( "led_runtime" );  
  12.     }  
  13.   
  14.     // 构造方法  
  15.     public LedService() {        
  16.         int icount ;  
  17.   
  18.         Log.i ("Java Service" , "do init Native Call" );  
  19.         _init ();           
  20.         icount =_get_count ();  
  21.         Log.d ("Java Service" , "led count = " + icount );  
  22.         Log.d ("Java Service" , "Init OK " );  
  23.     }  
  24.   
  25.     /* 
  26.      * LED nativemethods. 
  27.      */  
  28.     public Stringset_on() {  
  29.         Log.i ("com.hello.LedService" , "LED On" );  
  30.         _set_on();  
  31.         return"led on" ;  
  32.      }  
  33.   
  34.      public String set_off() {  
  35.          Log.i ("com.hello.LedService" , "LED Off" );  
  36.          _set_off();  
  37.          return"led off" ;  
  38.      }  
  39.   
  40.      /* 
  41.      * declare all the native interface. 
  42.      */  
  43.      private static native boolean _init();  
  44.      private static native int _set_on();  
  45.      private static native int _set_off();  
  46.      private static native int _get_count();  
  47.   
  48.   }  

通过分析上面代码可知LedService的工作:

l   加载本地服务的库代码

l   在构造方法里调用_init本地代码,对Led进行初始化,并调用get_count得到Led灯的个数

l   为LedDemo应用程序提供两个API:set_on和set_off,这两个API方法实际上也是交给了本地服务代码来操作的

由于Java代码无法直接操作底层硬件,通过JNI方法将具体的操作交给本地底层代码实现,自己只是一个API Provider,即:服务提供者。

让我们来到底层本地代码,先看下底层代码的Android.mk文件:

@ frameworks/Android.mk:

[plain]  view plain copy
  1. LOCAL_PATH:= $(call my-dir)  
  2. include $(CLEAR_VARS)  
  3.   
  4. LOCAL_MODULE_TAGS := eng  
  5. LOCAL_MODULE:= libled_runtime                    # 编译目标模块  
  6. LOCAL_SRC_FILES:= \  
  7.        services/jni/com_farsight_LedService.cpp  
  8.   
  9.    
  10. LOCAL_SHARED_LIBRARIES := \                       # 编译时依赖的动态库  
  11.        libandroid_runtime  \  
  12.        libnativehelper    \  
  13.         libcutils         \  
  14.         libutils          \  
  15.        libhardware  
  16.   
  17.  LOCAL_C_INCLUDES += \                                  #编译时用到的头文件目录  
  18.        $(JNI_H_INCLUDE)  
  19.   
  20. LOCAL_PRELINK_MODULE := false                            # 本目标为非预链接模块  
  21. include $(BUILD_SHARED_LIBRARY)                # 编译生成共享动态库  

结合前面分析的Android.mk不难看懂这个mk文件。之前的mk文件是编译成Android apk文件,这儿编译成so共享库,所以LOCAL_MODULE和include $(BUILD_SHARED_LIBRARY)与前面mk文件不同,关于Android.mk文件里的变量作用,请查看Android编译系统章节。

总而言之,本地代码编译生成的目标是libled_runtime.so文件。

 

4)        Led本地服务代码分析

我们来看下本地服务的源码:

@ frameworks/services/jni/com_farsight_LedService.cpp:

[cpp]  view plain copy
  1. #define LOG_TAG "LedService"  
  2. #include "utils/Log.h"  
  3. #include   
  4. #include   
  5. #include   
  6. #include   
  7. #include   
  8. #include "../../../hardware/led.h"  
  9.   
  10. static led_control_device_t *sLedDevice = 0;  
  11. static led_module_t* sLedModule=0;   
  12.   
  13. static jint get_count(void)  
  14. {  
  15.     LOGI("%sE", __func__);  
  16.    if(sLedDevice)  
  17.         returnsLedDevice->get_led_count(sLedDevice);  
  18.     else  
  19.        LOGI("sLedDevice is null");  
  20.     return 0;  
  21. }  
  22.   
  23.   
  24. static jint led_setOn(JNIEnv* env, jobject thiz) {  
  25.     LOGI("%sE", __func__);  
  26.     if(sLedDevice) {  
  27.        sLedDevice->set_on(sLedDevice);  
  28.     }else{  
  29.        LOGI("sLedDevice is null");  
  30.     }  
  31.     return 0;  
  32.  }   
  33.   
  34.  static jint led_setOff(JNIEnv* env, jobject thiz) {  
  35.     LOGI("%s E", __func__);  
  36.      if(sLedDevice) {  
  37.         sLedDevice->set_off(sLedDevice);  
  38.      }else{  
  39.          LOGI("sLedDevice is null");  
  40.      }  
  41.      return 0;  
  42.  }  
  43.   
  44. static inline int led_control_open(const structhw_module_t* module,  
  45.      structled_control_device_t** device) {  
  46.     LOGI("%s E ", __func__);  
  47.      returnmodule->methods->open(module,  
  48.         LED_HARDWARE_MODULE_ID, (struct hw_device_t**)device);  
  49. }  
  50.   
  51. static jint led_init(JNIEnv *env, jclass clazz)  
  52. {  
  53.     led_module_tconst * module;  
  54.     LOGI("%s E ", __func__);  
  55.      if(hw_get_module(LED_HARDWARE_MODULE_ID, (const hw_module_t**)&module) == 0){  
  56.         LOGI("get Module OK");  
  57.         sLedModule = (led_module_t *) module;  
  58.         if(led_control_open(&module->common, &sLedDevice) != 0) {  
  59.            LOGI("led_init error");  
  60.            return-1;  
  61.         }  
  62.     }   
  63.   
  64.     LOGI("led_init success");  
  65.     return 0;  
  66. }  
  67.   
  68.    
  69.   
  70.  /* 
  71.   * 
  72.   * Array ofmethods. 
  73.   * Each entryhas three fields: the name of the method, the method 
  74.   * signature,and a pointer to the native implementation. 
  75.   */  
  76. static const JNINativeMethod gMethods[] = {  
  77.     {"_init",    "()Z",(void*)led_init},  
  78.     {"_set_on",   "()I",(void*)led_setOn },  
  79.     {"_set_off""()I",(void*)led_setOff },  
  80.     {"_get_count""()I",(void*)get_count },  
  81. };  
  82.   
  83.   static int registerMethods(JNIEnv* env) {  
  84.      static constchar* const kClassName = "com/hello/LedService";  
  85.      jclass clazz;  
  86.      /* look upthe class */  
  87.      clazz =env->FindClass(kClassName);  
  88.      if (clazz ==NULL) {  
  89.         LOGE("Can't find class %s\n", kClassName);  
  90.          return-1;  
  91.      }   
  92.   
  93.      /* registerall the methods */  
  94.      if(env->RegisterNatives(clazz, gMethods,  
  95.             sizeof(gMethods) / sizeof(gMethods[0])) != JNI_OK)  
  96.      {  
  97.         LOGE("Failed registering methods for %s\n", kClassName);  
  98.          return -1;  
  99.      }  
  100.      /* fill outthe rest of the ID cache */  
  101.      return 0;  
  102.  }  
  103.   
  104.    
  105.   
  106.  /* 
  107.   * This iscalled by the VM when the shared library is first loaded. 
  108.   */  
  109.  jint JNI_OnLoad(JavaVM* vm, void* reserved) {  
  110.      JNIEnv* env= NULL;  
  111.      jint result= -1;  
  112.     LOGI("JNI_OnLoad");  
  113.      if(vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {  
  114.         LOGE("ERROR: GetEnv failed\n");  
  115.          gotofail;  
  116.      }  
  117.   
  118.      assert(env!= NULL);  
  119.      if(registerMethods(env) != 0) {  
  120.          LOGE("ERROR: PlatformLibrary nativeregistration failed\n");  
  121.          gotofail;  
  122.      }  
  123.      /* success-- return valid version number */  
  124.      result =JNI_VERSION_1_4;   
  125.   
  126.  fail:  
  127.      return result;  
  128.  }  

         这儿的代码不太容易读,因为里面是JNI的类型和JNI特性的代码,看代码先找入口。LedService.java框架代码一加载就调用静态初始化语句块里的System.loadLibrary ( "led_runtime" ),加载libled_runtime.so,该库刚好是前面Android.mk文件的目标文件,也就是说LedService加载的库就是由上面的本地代码生成的。当一个动态库被Dalvik加载时,首先在Dalvik会回调该库代码里的JNI_OnLoad函数。也就是说JNI_OnLoad就是本地服务代码的入口函数。

         JNI_OnLoad的代码一般来说是死的,使用的时候直接拷贝过来即可,vm->GetEnv会返回JNIEnv指针,而这个指针其实就是Java虚拟机的环境变量,我们可以通过该指针去调用JNI提供的方法,如FindClass等,调用registerMethods方法,在方法里通过JNIEnv的FindClass查找LedService类的引用,然后在该类中注册本地方法与Java方法的映射关系,上层Java代码可以通过这个映射关系调用到本地代码的实现。RegisterNatives方法接收三个参数:

l  第一个参数jclass:要注册哪个类里的本地方法映射关系

l  第二个参数JNINativeMethod*:这是一个本地方法与Java方法映射数组,JNINativeMethod是个结构体,每个元素是一个Java方法到本地方法的映射。

[cpp]  view plain copy
  1. typedef struct {  
  2.          constchar* name;  
  3.          constchar* signature;  
  4.          void*fnPtr;  
  5. } JNINativeMethod;  

         name:表示Java方法名

         signature:表示方法的签名

         fnPtr:Java方法对应的本地方法指针

l  第三个参数size:映射关系个数

由代码可知,Java方法与本地方法的映射关系如下:

Java方法

本地方法

void _init()

jint led_init(JNIEnv *env, jclass clazz)

int _set_on()

jint led_setOn(JNIEnv* env, jobject thiz)

int _set_off()

jint led_setOff(JNIEnv* env, jobject thiz)

int _get_count()

jint get_count(void)

通过上表可知,本地方法参数中默认会有两个参数:JNIEnv* env, jobject thiz,分别表示JNI环境和调用当前方法的对象引用,当然你也可以不设置这两个参数,在这种情况下你就不能访问Java环境中的成员。本地方法与Java方法的签名必须一致,返回值不一致不会造成错误。

现在我们再来回顾下我们的调用调用流程:

l  LedDemo创建了LedService对象

l  LedService类加载时加载了对应的本地服务库,在本地服务库里Dalvik自动调用JNI_OnLoad函数,注册Java方法和本地方法映射关系。

根据Java语言特点,当LedDemo对象创建时会调用其构造方法LedService()。

[cpp]  view plain copy
  1. // 构造方法  
  2.     public LedService() {        
  3.         int icount ;  
  4.         Log.i ("Java Service" , "do init Native Call" );  
  5.         _init ();           
  6.         icount =_get_count ();  
  7.         Log.d ("Java Service" , "led count = " + icount );  
  8.         Log.d ("Java Service" , "Init OK " );  
  9.     }  

在LedService构造方法里直接调用了本地方法_init和_get_count(通过native保留字声明),也就是说调用了本地服务代码里的jint led_init(JNIEnv *env, jclass clazz)和jintget_count(void)。

在led_init方法里的内容就是我们前面分析HAL框架代码的使用规则了。

l  通过hw_get_module方法查到到注册为LED_HARDWARE_MODULE_ID,即:”led”的module模块。

l  通过与led_module关联的open函数指针打开led设备,返回其device_t结构体,保存在本地代码中,有的朋友可能会问,不是本地方法不能持续保存一个引用吗?由于device_t结构是在open设备时通过malloc分配的,只要当前进程不死,该指针一直可用,在这儿本地代码并没有保存Dalvik里的引用,保存的是mallco的分配空间地址,但是在关闭设备时记得要将该地址空间free了,否则就内存泄漏了。

l  拿到了led设备的device_t结构之后,当LedDemo上的按钮按下时调用LedService对象的set_on和set_off方法,这两个LedService方法直接调用了本地服务代码的对应映射方法,本地方法直接调用使用device_t指向的函数来间接调用驱动操作代码。

好吧,让我们再来看一个详细的时序图:


不用多解释了。

最后一个文件,HAL对应的Android.mk文件:

@ hardware/Android.mk:

[plain]  view plain copy
  1. LOCAL_PATH := $(call my-dir)  
  2. include $(CLEAR_VARS)  
  3.   
  4. LOCAL_C_INCLUDES += \  
  5.          include/  
  6.   
  7. LOCAL_PRELINK_MODULE := false  
  8. LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw  
  9. LOCAL_SHARED_LIBRARIES := liblog  
  10. LOCAL_SRC_FILES := led.c  
  11. LOCAL_MODULE := led.default  
  12. include $(BUILD_SHARED_LIBRARY)  

注:LOCAL_PRELINK_MODULE:= false要加上,否则编译出错

指定目标名为:led.default

目标输入目录LOCAL_MODULE_PATH为:/system/lib/hw/,不指定会默认输出到/system/lib目录下。

根据前面HAL框架分析可知,HAL Stub库默认加载地址为:/vendor/lib/hw/或/system/lib/hw/,在这两个目录查找:硬件id名.default.so,所以我们这儿指定了HAL Stub的编译目标名为led.default,编译成动态库,输出目录为:$(TARGET_OUT_SHARED_LIBRARIES)/hw,TARGET_OUT_SHARED_LIBRARIES指/system/lib/目录。

5) 深入理解

我们从进程空间的概念来分析下我们上面写的代码。


我们前面的示例代码中,将LedDemo.java和LedService.java都放在了一个APK文件里,这也就意味着这个应用程序编译完之后,它会运行在一个Dalvik虚拟机实例中,即:一个进程里,在LedService.java中加载了libled_runtime.so库,通过JNI调用了本地代码,根据动态库的运行原理,我们知道,libled_runtime.so在第一次引用时会被加载到内存中并映射到引用库的进程空间中,我们可以简单理解为引用库的程序和被引用的库在一个进程中,而在libled_runtime.so库中,又通过dlopen打开了库文件led.default.so(该库并没有被库加载器加载,而是被当成一个文件打开的),同样我们可以理解为led.default.so和libled_runtime.so在同一个进程中。

由此可见,上面示例的Led HAL代码全部都在一个进程中实现,在该示例中的LedService功能比较多余,基本上不能算是一个服务。如果LedDemo运行在两个进程中,就意味着两个进程里的LedService不能复用,通常我们所谓的Service服务一般向客户端提供服务并且同时可以为多个客户端服务(如下图),所以我们的示例Led HAL代码不是完美的HAL模型,我们后面章节会再实现一个比较完美的HAL架构。






23
2
主题推荐
移植 设计 android android应用 应用程序
猜你在找
TP调试
高通Android平台硬件调试之Camera篇
queue_delayed_work和queue_work区别
v4l2 编程接口二 driver
实现uboot 命令自动补全 及 修正设置环境变量时自启动内核
iOS开发Swift语言学习教程
Java基础核心技术:多线程(day16-day17)
Android入门实战教程
Java基础核心技术:IO(day15-day16)
Linux企业常用文件管理命令详解
准备好了么? 跳吧             ! 更多职位尽在 CSDN JOB
【精准广告投放】C/C++研发工程师/数据挖掘工程师
百度在线网络技术(北京)有限公司
|
18-35K/月
我要跳槽
C/C++/C#软件工程师
利博国际科技发展有限公司
|
10-20K/月
我要跳槽
C/C++软件开发工程师
合肥赛猊腾龙信息技术有限公司
|
10-20K/月
我要跳槽
C/C++开发
上海云盾信息技术有限公司
|
20-25K/月
我要跳槽
id="ad_frm_0" frameborder="0" scrolling="no" src="http://blog.csdn.net/common/ad.html?t=4&containerId=ad_cen&frmId=ad_frm_0" style="border-width: 0px; overflow: hidden; width: 984px; height: 90px;">
查看评论
10楼  心鑫 2014-05-14 17:01发表 [回复]
请问:我把mokoid的源码放在device目录下,编译有问题,修改下编译没问题,在/build/target/product/generic_no_telephony.mk下添加了 LedTest \
LedClient \
在out/target/product/generic/system/app目录下也有对应的apk,可为什么在虚拟机里就是看不到apk呢?
你的串口的例子就没问题,实在找不出两都的差别了
Re:  mr_raptor 2014-05-17 19:14发表 [回复]
回复proud2005:你看看你的Logcat,你的这个问题我遇到过,不是因为API level不对,就是APk安装出了问题。
9楼  南枫co 2014-05-09 21:55发表 [回复]
请问,你这个工程怎么编译的呢?有c,cpp,java
Re:  mr_raptor 2014-05-12 10:57发表 [回复]
回复far5811:通过编写Android.mk文件来实现编译,Android的编译系统会自动完成编译。详细请看Android编译系统一、二、三文章。
Re:  南枫co 2014-05-24 21:10发表 [回复]
回复mr_raptor:嗯,我还有个问题请教下:
假设系统开发和应用开不是同一个人,想将uart,led,i2c等的Hal,jni,server直接编译进system.img里面,这样就可以多个应用访问这个公共的接口了,而不需要每个应用都写一套hal,jni,server等,但是应用开发的时候不知道怎么引用这些接口,Eclipse里不识别。
Re:  南枫co 2014-05-24 21:09发表 [回复]
回复mr_raptor:嗯,我还有个问题请教下:
假设系统开发和应用开不是同一个人,想将uart,led,i2c等的Hal,jni,server直接编译进system.img里面,这样就可以多个应用访问这个公共的接口了,而不需要每个应用都写一套hal,jni,server等,但是应用开发的时候不知道怎么引用这些接口,Eclipse里不识别。
8楼  bossqingge 2014-04-24 23:07发表 [回复]
时不时来拜读你的文章啊
7楼  wujijunzhu 2014-04-16 15:27发表 [回复]
顶!
6楼  mozun1 2014-03-26 15:37发表 [回复]
源代码 有地方下载吗?, 你出的书在哪里? 谢谢
5楼  pianov 2013-08-15 17:37发表 [回复]
您好
frameworks/Android.mk:裡的 services/jni/com_farsight_LedService.cpp有寫錯嗎?
應該是frameworks/services/jni/com_hello_LedService.cpp嗎?
Re:  mr_raptor 2014-01-17 11:21发表 [回复]
回复pianovv510:您看的很仔细,是有写错,已经修改了,多谢指正,祝您学习愉快。
4楼  williamlin3 2013-03-11 10:46发表 [回复]
文章写得很好,没有经你允许我转走了几篇。不介意吧??
Re:  mr_raptor 2013-03-11 17:11发表 [回复]
回复williamlin3:欢迎转载,互相学习~
3楼  fandh2011 2012-12-01 11:13发表 [回复]
问题解决了,硬件id名是LED_HARDWARE_MODULE_ID一类的!
2楼  fandh2011 2012-12-01 10:27发表 [回复]
“硬件id名.default.so”???
硬件id名可以理解为/dev/led或/dev/beep等设备下的设备号吗?
1楼  JayZhang 2012-10-18 08:47发表 [回复]
在平台移植的时候更多的是把,jni,service都编译到系统中去吧!
Re:  mr_raptor 2012-10-18 09:43发表 [回复]
回复zhangjie201412:不管什么移植,最终的目标都要编译到系统中,只是出现的位置不一样,Android给的源码里frameworks目录是框架层主要代码,包含Java部分和对应的JNI部分,不过,Google希望第三方厂商的代码放在vendor或device目录下,而不是直接修改Android的原生源码,所以我们自己添加的代码放到了vendor或device目录下,当然,如果你要放到frameworks下,也没有问题,这对产品开发没有问题,但是如果从开源的角度来看,特定设备的源码放到了框架层,就意味着,其它人使用你的源码,也要使用相同的设备了,别人不利用你的框架!!祝你工作愉快
Re:  JayZhang 2012-10-18 13:57发表 [回复]
回复mr_raptor:嗯,多谢赐教
发表评论
  • 用 户 名:
  • u012497906
  • 评论内容:
      
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
id="ad_frm_1" frameborder="0" scrolling="no" src="http://blog.csdn.net/common/ad.html?t=5&containerId=ad_bot&frmId=ad_frm_1" style="border-width: 0px; overflow: hidden; width: 984px; height: 0px;">
核心技术类目
全部主题  Hadoop  AWS  移动游戏  Java  Android  iOS  Swift  智能硬件  Docker  OpenStack  VPN  Spark  ERP  IE10 Eclipse  CRM  JavaScript  数据库  Ubuntu  NFC  WAP  jQuery  BI  HTML5  Spring  Apache  .NET  API  HTML  SDK  IIS Fedora  XML  LBS  Unity  Splashtop  UML  components  Windows Mobile  Rails  QEMU  KDE  Cassandra  CloudStack  FTC coremail  OPhone  CouchBase  云计算  iOS6  Rackspace  Web App  SpringSide  Maemo  Compuware  大数据  aptech  Perl Tornado  Ruby  Hibernate  ThinkPHP  HBase  Pure  Solr  Angular  Cloud Foundry  Redis  Scala  Django  Bootstrap
    个人资料
    led HAL简单案例分析_第4张图片 
    mr_raptor
     
    1
    • 访问:563314次
    • 积分:7578
    • 等级: 
    • 排名:第1133名
    • 原创:95篇
    • 转载:28篇
    • 译文:1篇
    • 评论:716条
    个人简介

    mr_raptor
    北京

    width="200" height="22" src="http://widget.weibo.com/relationship/followbutton.php?width=200&height=22&uid=3166445905&style=5&btn=red&dpc=1" border="0" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" allowtransparency="" style="border-color: rgb(210, 210, 210); width: 64px; height: 22px;">


    《深入浅出:嵌入式底层软件开发》作者,从事Android移动开发、嵌入式系统开发。 

    邮箱:[email protected]
    博客专栏
    led HAL简单案例分析_第5张图片 Android平台移植

    文章:32篇

    阅读:245881
    led HAL简单案例分析_第6张图片 WindowsPhone开发技术专栏

    文章:13篇

    阅读:49149
    文章分类
  • Android移植(59)
  • ARM体系结构(22)
  • Linux内核(3)
  • 裸板驱动(10)
  • 其它杂项(14)
  • WindowsPhone(15)
  • C语言详解(10)
    阅读排行
  • Android编译系统详解(一)(21408)
  • 深入浅出 - Android系统移植与平台开发(二) - 准备Android开发环境(17362)
  • 深入浅出 - Android系统移植与平台开发(十一) - Sensor HAL框架分析之一(14385)
  • 深入浅出 - Android系统移植与平台开发(一)(13899)
  • ARM处理器模式切换(含MRS,MSR指令)(12371)
  • Android编译系统详解(二)(12253)
  • 我与《深入浅出嵌入式底层软件开发》(12174)
  • 深入浅出 - Android系统移植与平台开发(八)- HAL Stub框架分析(11819)
  • 深入浅出 - Android系统移植与平台开发(六)- 为Android启动加速(11626)
  • Android编译系统详解(三)(11258)
    文章存档
  • 2015年04月(4)
  • 2015年01月(2)
  • 2014年08月(2)
  • 2014年06月(8)
  • 2014年05月(1)
    展开
    评论排行
  • WindowsPhone下拉刷新控件 - PullRefreshListBox(一)(97)
  • WindowsPhone下拉刷新控件 - PullRefreshListBox(二)(57)
  • S3C2440 SDRAM内存驱动(40)
  • WindowsPhone之我见(35)
  • 深入浅出 - Android系统移植与平台开发(十一) - Sensor HAL框架分析之一(28)
  • 我与《深入浅出嵌入式底层软件开发》(21)
  • 整理Windows Phone 7教程(很全面)(20)
  • 深入浅出 - Android系统移植与平台开发(十) - led HAL简单设计案例分析(18)
  • mini6410中断控制器-VIC中断控制器(16)
  • miniOS_V2.0更新(15)
    最新评论
  • 深入浅出 - Android系统移植与平台开发(三)- 配置Vmware网络

    qq_26476749: 多谢楼主无私奉献该顶

  • 蓝牙聊天室App设计与实现

    diagram98: 唐老师,在Eclipse中import此源码运行发现只能发送信息,不能接收。提示TAG:Blueto...

  • Android蓝牙调试助手

    luguoqingting1956: 老师,我是初学者,看到你的百度里面Android应用开发从基础到项目第一讲【华清远见】课程,来找源码...

  • 深入浅出 - Android系统移植与平台开发(十二)- Android JNI机制

    Emilio66: 哥们可以出本书 了

  • Android蓝牙调试助手

    xiaobailong24: 有源码吗?楼主。希望分享一下,谢谢哈

  • 深入浅出 - Android系统移植与平台开发(一)

    剑晨无痕: 楼主有出书么~~书名叫什么啊

  • 深入浅出 - Android系统移植与平台开发(十二)- Android JNI机制

    EmilyLv: 对JNI的知识点将的很全面,很强大,学习了

  • 深入浅出 - Android系统移植与平台开发(十四) - Sensor HAL框架分析之四

    Vincent_shawn: 老师,如果我要添加一个一个新的传感器到sensor框架,该怎么做,看得迷迷糊糊的,刚接触androi...

  • 深入浅出 - Android系统移植与平台开发(十四) - Sensor HAL框架分析之四

    Vincent_shawn: 老师,如果我要添加一个一个新的传感器到sensor框架,该怎么做,看得迷迷糊糊的,刚接触androi...

  • 深入浅出 - Android系统移植与平台开发(一)

    frankqs: 书名是什么?谢谢 !

 

你可能感兴趣的:(Android)