JNI向上提供本地函数,向下加载HAL文件,并调用HAL的函数;

HAL负责访问驱动程序执行硬件操作

JNI和HAL都是用c语言或者C++语言编写的,JNI加载HAL的实质就是使用dlopen加载动态库文件

安多人源代码中第dlopen做了一层封装,在JNI中是通过hw_get_module来加载动态库

external\chromium_org\third_party\hwcplus\src\hardware.c
hw_get_module("led")//分析hw_get_module

  1. 模块名==>文件名
    hw_get_module_by_class("led", NULL)
      name = "led"
        property_get(prop_name,prop,NULL)     prop_name是某个属性,根据属性来获得prop值
        hw_module_exists 判断是否存在led.prop.so
(在运行的Android系统中执行 getprop ro.hardware可以查看这个ro.hardware属性存在么,并打印其值)

  2. 加载
    load
      dlopen(filename)
      dlsym("HMI") 从SO文件中获得名为HMI的hw_module_t结构体
      strcmp(id, hmi->id) 判断名字是否一致(hmi->id, "led")

      如果一致,把找到的hmi结构体传出去

hw_module_exists(char *path, size_t path_len, const char *name,const char *subname)

led.tiny4412.so(不存在)
led.exynos4.so(不存在)
led.default.so(存在)

它用来判断"name"."subname".so文件是否存在
查找的目录:
a. HAL_LIBRARY_PATH 环境变量
b. /vendor/lib/hw
c. /system/lib/hw    //4412开发板只会去这个目录下去查找,其他几个目录都没设置

property_get : 属性系统
属性<键,值> <name, value>

JNI 怎么使用 HAL
a. hw_get_module 获得一个hw_module_t结构体
b. 调用 module->methods->open(module, device_name, &device) //module里面有多个device
  获得一个hw_device_t结构体
  并且把hw_device_t结构体转换为设备自定义的结构体

HAL 怎么写
a. 实现一个名为HMI的hw_module_t结构体
b. 实现一个open函数, 它会根据name返回一个设备自定义的结构体
  这个设备自定义的结构体的第1个成员是 hw_device_t结构体
  还可以定义设备相关的成员

打印信息简介:
a. 有三类打印信息: app, system, radio
程序里使用 ALOGx, SLOGx, RLOGx来打印(分别对应应用打印信息、系统打印信息,Radio打印信息)
b. x表示6种打印级别,有:
V Verbose
D Debug
I Info
W Warn
E Error
F Fatal

比如:
#define LOG_TAG "LedHal"
ALOGI("led_open : %d", fd);

c. 打印出来的格式为:
I        / LedHal     ( 1987)   : led_open : 65
(级别) LOG_TAG 进程号 打印信息

d. 在开发板上使用 logcat 命令查看 或者logcat LEDHAL:I *:S(过滤规则) 或者logcat | grep “LedHal”
logcat LedHal:I *:S//*.S表示其他信息不打印

过滤规则:<tag>[:priority]

实现led_hal.c

/*a. 实现一个名为HMI的hw_module_t结构体*/
/*b. 实现一个open函数, 它会根据name返回一个设备自定义的结构体led_device_t*/

/*c.实现led_device_t结构体*/

/*参看文件hardware\libhardware\modules\vibrator\vibrator.c*/

#define LOG_TAG "LedHal"//ALOGI会用到这个宏定义来打印,然后在打印信息中我们可以通过筛选Ledhal来区分不同的打印信息

#include <hardware/led_hal.h>

#include <hardware/hardware.h>

......还有很多头文件.........

static int fd;

static int led_open(struct led_device_t *dev)

{

    fd = open("/dev/leds",O_RDWR);

    ALOGI(“ ledOpen:%d”,fd);//打印

    if(fd >=0)

      return 0;

    else

      return -1;

}

static int led_close(struct led_device_t *dev){

  close(fd);

  return 0;

}

static int led_ctrl(struct led_device_t *dev,int which,int status)

{

    int ret = ioctl(fd,status,which);

    return ret;

}

static struct led_device_t led_dev = {

  .common = {

  .close = led_close ,

  },

  .led_open = led_open ,

  .led_ctrl = led_ctrl ,

};

static int led_device_open(const struct hw_module_t *module,const char *id,struct hw_device_t **device)

{

  //正常的做法是通过id找到led_device_t ,这里有位只有一个led_device_t,就没有查找了

  *device = &led_dev //led_dev 的第一个成员就是hw_device_t ,他们地址一样

}

static struct hw_module_methods_t led_module_methods {

  .open = led_device_open;

};

struct hw_module_t HAL_MODULE_INFO_SYM = {

  //.tag = HARDWARE_MODULE_TAG,

  //.module_api_version = ........,

  //.hal_api_version = HARDWARE_HAL_API_VERSION,

  .id = "led ",//JNI中通过hw_get_module('led')来获得hw_module_t

  //.name =,

  //.auth,

  .methods = led_module_methods;

}

实现led_hal.h

#ifndef ANDROID_LED_INTERFACE_H

#define ANDROID_LED_INTERFACE_H

#include <stdint.h>

#include <sys/cdefs.h>

#include <sys/types.h>

#include <hardware/hardware.h>

__BEGIN_DECLS

struct led_device_t {

  struct hw_device_t common;

  int (*led_open)(struct led_device_t *dev);

  int (*led_ctrl)(struct led_device_t *dev,int which,int status);

}

__END_DECLS

#endif

修改之前写的JNI文件com_android_server_LedService.cpp

  #define LOG_TAG "LedService"

  #include "jni.h"

  #include "JNIHelp.h"

  #include "android_runtime/AndroidRuntime.h"

  #include <utils/misc.h>

  #include <utils/Log.h>

  #include <hardware_legacy/vibrator.h>

  #include <stdio.h>

  //还有一些头问题

  #include <hardware/led_hal.h>

  namespace android

  {

  static led_device_t* led_device;

  jint ledOpen(JNIEnv *env,jobject cls)

  {

    jint err;

    hw_module_t* module;

    hw_device_t* device;

    /*1、调用hw_get_module*/

    err = hw_get_module("led",(hw_module_t const **)&module);

    if(err == 0){

      /*2、调用module->methods->open来get device*/

      err = module->methods->open(module,NULL,&device)

      if(err == 0){

        led_device = (light_device_t *)device;

        /*3、call led_open*/

        return led_device ->led_open(led_device );

      }else{

        return -1;

      }

    }  

    return -1;

  } 

  void ledClose(JNIEnv *env,jobject cls) 

  {

    

  }  

  jint ledCtrl(JNIEnv *env,jobject cls,jint which,jint status)

  {

    return led_device->led_ctrl(led_device,which,status);

  }

  static const JNINativeMethod methods[] = {

    {"native_ledOpen","()I",(void *)ledOpen},

    {"native_ledClose","()V",(void *)ledClose},

    {"native_ledCtrl","(II)I",(void *)ledCtrl},

  };

  int register_android_server_LedService(JNIEnv *env)

  {

    return jniRegisterNativeMethods(env,"com/android/server/LedService",methods,NELEM(methods));

  }

  }

上传编译:

(1)、JNI重新上传到

  frameworks/base/services/core/jni/com_android_server_LedService.cpp

(2)、HAL:led_hal.h和led_hal.c

 hardware/libhardware/include/hardware/led_hal.h

 hardware/libhardware/modules/led/led_hal.c

 hardware/libhardware/modules/led/Android.mk

Android.mk内容如下:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := led.default  //指定了最后编译出来的模块是led.default.so,这就和前面分析的通过hw_get_module找so对应上了

LOCAL_MODULE_RELATIVE_PATH :=hw  //指定了so存在的目录在/system/lib/hw下

LOCAL_C_INCLUDES := hardware/libhardware  //头文件

LOCAL__SRC_FILES := led_hal.c  //源文件

LOCAL_SHARED_LIBRARIES := liblog

LOCAL_MODULE_TAGS := eng

include $(BUILD_SHARED_LIBRARY)

编译:

mmm frameworks/base/services  //编译JNI

mmm hardware/libhardware/modules/led   //编译C库 led.default.so

make snod

./gen-img.sh

6.4 Android硬件访问服务编写HAL代码的更多相关文章

  1. 2.Android硬件访问服务编写系统代码【转】

    本文转载自:https://blog.csdn.net/qq_33443989/article/details/76696772 版权声明:本文为博主(Tower)自学笔记,欢迎转载! :-)     ...

  2. 6.2、Android硬件访问服务编写系统代码

    1.实现接口文件给App使用,接口文件是应用程序查询获得服务时获得 使用AIDL(Android接口定义语言)来实现ILedService.java接口 定义ILedService.aidl inte ...

  3. 6.1、Android硬件访问服务之框架

    1.通过前面led点亮的例子,其流程如下 Android app(java)(通过loadLibrary)——>C library(C库做如下事情)——>1.JNI_Onload 2.jn ...

  4. 6.5 Android硬件访问服务使用反射

    1.前面的例子中App为了能够范问ILedService接口,把classes.jar导入到应用程序中,但是我们不想把classes编进apk包里面去,这样导致我们的apk程序会很大(解压缩apk会发 ...

  5. Android硬件访问服务中的HAL-查看打印的信息

    JNI  向上提供本地函数,向下加载HAL文件并调用HAL的函数 HAL 负责访问驱动程序执行硬件操作. external\chromium_org\third_party\hwcplus\src\h ...

  6. 6.3 Android硬件访问服务APP代码

    以下步骤是操作MainActivity类 1.导入包 import android.os.ILedService 2.添加成员变量 private ILedService iLedService = ...

  7. 硬件访问服务学习笔记_WDS

    1.Android驱动框架App1 App2 App3 App4-------------------硬件访问服务-------------------JNI-------------------C库 ...

  8. LED硬件访问服务(2)——JNI/HAL

    一.系统编程 1.SystemServer.java类中提供了main()方法,说明它是以一个进程的方式存在的,启动后直接执行其run() 2.注册服务ServiceManager.addServic ...

  9. 在Ubuntu上为Android系统的Application Frameworks层增加硬件访问服务(老罗学习笔记5)

    在数字科技日新月异的今天,软件和硬件的完美结合,造就了智能移动设备的流行.今天大家对iOS和Android系统的趋之若鹜,一定程度上是由于这两个系统上有着丰富多彩的各种应用软件.因此,软件和硬件的关系 ...

随机推荐

  1. Scott Hanselman的问题-1

    Scott Hanselman的问题 .Net 程序员面试 C# 语言篇 (回答Scott Hanselman的问题)   过去几年都在忙着找项目,赶项目,没有时间好好整理深究自己在工作中学到的东西. ...

  2. POJ 2394 Dijkstra

    题意: 思路: 裸的Dijkstra 爆敲一发模板 //By SiriusRen #include <queue> #include <cstdio> #include < ...

  3. Lucene 定义

    福利 => 每天都推送 欢迎大家,关注微信扫码并加入我的4个微信公众号:   大数据躺过的坑      Java从入门到架构师      人工智能躺过的坑         Java全栈大联盟   ...

  4. ajax模仿iframe

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  5. hdu 1588 Gauss Fibonacci(矩阵嵌矩阵)

    题目大意: 求出斐波那契中的 第 k*i+b 项的和. 思路分析: 定义斐波那契数列的矩阵 f(n)为斐波那契第n项 F(n) = f(n+1) f(n) 那么能够知道矩阵 A = 1 1 1  0 ...

  6. 16.REPL 命令

    转自:http://www.runoob.com/nodejs/nodejs-tutorial.html ctrl + c - 退出当前终端. ctrl + c 按下两次 - 退出 Node REPL ...

  7. jodd-servlet工具集锦

    Jodd提供了许多servlet和jsp相关的工具. Utils ServletUtils类集成了不同的servlet工具,你可以检测multipart请求,读取授权头,下载预备,cookie操作,读 ...

  8. golang API 例子实现

    golang API 例子实现 http://files.cnblogs.com/files/rojas/astaxie.zip

  9. ORA-16055: FAL request rejected

    主库频繁报错如下: ORA-16055: FAL request rejected   解决办法: ALTER SYSTEM SET log_archive_dest_state_2='DEFER' ...

  10. JS / CSS 实现的便签记录本

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...