第1课第4.4节_Android硬件访问服务编写HAL代码

4 编写HAL代码

源码下载方法
第一次:
git clone https://github.com/weidongshan/SYS_0001_LEDDemo.git
更新:
git pull origin
取出指定版本:
git checkout v1 // 有JNI没有HAL
git checkout v2 // 有JNI,HAL
git checkout v3 // add MODULE TAG, DEVICE TAG

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

dlopen

external\chromium_org\third_party\hwcplus\src\hardware.c   (参考代码)
hw_get_module("led")

1. 模块名==>文件名
hw_get_module_by_class("led", NULL)
name = "led"
property_get xxx是某个属性
hw_module_exists 判断是否存在led.xxx.so

它用来判断"name"."subname".so文件是否存在
查找的目录:
a. HAL_LIBRARY_PATH 环境变量

b. /vendor/lib/hw

c. /system/lib/hw

/vendor/lib/hw 这个目录下没有文件,tiny4412所以只能去/system/lib/hw这个目录下找

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

V2:
(3) JNI: 重新上传
frameworks/base/services/core/jni/com_android_server_LedService.cpp

(4) HAL: led_hal.h
led_hal.c
把新文件上传到服务器, 所在目录:
hardware/libhardware/include/hardware/led_hal.h

hardware/libhardware/modules 在这个目录下创建一个目录led,放入led_hal.c和自己写一个Android.mk

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
LOCAL_MODULE_RELATIVE_PATH := 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
$ mmm hardware/libhardware/modules/led
$ make snod
$ ./gen-img.sh

最终生成system.img文件

打印信息简介:
a. 有三类打印信息: app, system, radio
程序里使用 ALOGx, SLOGx, RLOGx来打印
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

选出自己感兴趣的信息:

和上一个章节相比,主要修改了

com_android_server_LedService.cpp

添加了led_hal.h   led_hal.c  Android.mk

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 <stdio.h>

#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.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;

    ALOGI("native ledOpen ...");

    /* 1. hw_get_module */
    err = hw_get_module("led", (hw_module_t const**)&module);
    if (err == 0) {
        /* 2. get device : module->methods->open */
        err = module->methods->open(module, NULL, &device);
        if (err == 0) {
            /* 3. call led_open */
            led_device = (led_device_t *)device;
            return led_device->led_open(led_device);
        } else {
            return -1;
        }
    }

    return -1;
}

void ledClose(JNIEnv *env, jobject cls)
{
    //ALOGI("native ledClose ...");
    //close(fd);
}

jint ledCtrl(JNIEnv *env, jobject cls, jint which, jint status)
{
    ALOGI("native ledCtrl %d, %d", which, 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));
}

}

led_hal.c

#define LOG_TAG "LedHal"

/* 1. 实现一个名为HMI的hw_module_t结构体 */

/* 2. 实现一个open函数, 它返回led_device_t结构体 */

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

/* 参考 hardware\libhardware\modules\vibrator\vibrator.c
 */

#include <hardware/vibrator.h>
#include <hardware/hardware.h>

#include <cutils/log.h>

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>

#include <hardware/led_hal.h>

#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <utils/Log.h>

static int fd;

/** Close this device */
static int led_close(struct hw_device_t* device)
{
    close(fd);
    return 0;
}

static int led_open(struct led_device_t* dev)
{
    fd = open("/dev/leds", O_RDWR);
    ALOGI("led_open : %d", fd);
    if (fd >= 0)
        return 0;
    else
        return -1;
}

static int led_ctrl(struct led_device_t* dev, int which, int status)
{
    int ret = ioctl(fd, status, which);
    ALOGI("led_ctrl : %d, %d, %d", which, status, ret);
    return ret;
}

static struct led_device_t led_dev = {
    .common = {
        .tag   = HARDWARE_DEVICE_TAG,
        .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)
{
    *device = &led_dev;
    return 0;
}

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,
    .id = "led",
    .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  // ANDROID_LED_INTERFACE_H
时间: 2024-12-12 04:47:48

第1课第4.4节_Android硬件访问服务编写HAL代码的相关文章

第4课第3节_Android灯光系统_编写HAL_lights.c

JNI文件:com_Android_server_LedService.cpp 注册本地方法,会加载HAL文件: 3. 编写android灯光系统的hal程序 Java: frameworks/base/services/core/java/com/android/server/lights/LightsService.javaJNI: frameworks/base/services/core/jni/com_android_server_lights_LightsService.cppHal

&lt;iOS 导航栏&gt;第一节:导航栏透明方法实现代码

说下导航栏的透明方法: 很多应用需要导航栏随着向上滑动,逐渐从透明变成不透明,很炫酷,大部分应用都在使用导航栏渐变效果,现附上代码然后直接将实现,一会讲下如何来实现,这一部分直接上代码. 先附上代码: 方法声明: #import <UIKit/UIKit.h> @interface IDSNavBarView : UIView - (instancetype)initWithFrame:(CGRect)frame titleImg:(UIImage *)aTitleImg; - (UILabe

工业防火墙架构与技术【第二节:硬件架构②】

2).满足对数据包的处理性能的高速度要求 任何防火墙的基本技术功能都是过滤报文.防火墙检查其接收的每个数据包,以确定数据包是否对应于流量模式的所需模板.防火墙然后过滤(丢弃)或转发与这些模板匹配的数据包.这些模板以规则的形式进行建模.在工控防火墙中,有针对已知协议提前建模好的规则模板,也有后期自动学习进行建模的规则模板.由于工控防火墙处理数据包是一个一个处理,包括数据包的校验,数据包每一层包头的处理,所以数据包越小,到达时间就越短,服务器处理数据包要求就越高.比如64B的小包,如果处理数据包要达

工业防火墙架构与技术【第二节:硬件架构①】

1.3.   工控防火墙的体系架构 那么工控防火墙是如何设计来支撑其部署到工业生产环境中的?这就需要我们了解工控防火墙的架构,这包括两个方面:软件和硬件两部分.也就是防火墙运行在什么软件系统上以及防火墙安装的硬件平台. 软件和硬件架构是防火墙的骨骼,它决定了防火墙整体的工作水平和性能.一般而言,我们可以把常见的防火墙分为基于硬件防火墙.基于虚拟化架构的防火墙和基于软件的防火墙三类. l  基于硬件的防火墙在硬件方面一般采用了主流的三种架构:X86.ASIC和NP.ASIC和NP是专门设计的实现防

工业防火墙架构与技术【第二节:硬件架构④】

下图展示了主板的主电源供电电路设计图: 下图展示了基于主供电电源的以太网.现场总线.以及485总线需要的电源隔离电路设计图. 除此之外,既然断电也是一种可能存在的单点故障,那么在硬件架构设计的时候,本身工业主板的供电还应该考虑的是双备电源电路设计!也就是冗余电源.下图展示了工业主板针对的双备电源电路设计设计图: 因此工业防火墙在硬件架构设计上需要考虑冗余电源供电,当其中一路电源出现故障时,另外一路电源仍然能够保障防火墙的正常工作,同时需要设计中很短的时间之内将电源的故障进行报警,以使得维修人员及

工业防火墙架构与技术【第二节:硬件架构③】

书接上文 3).满足工业环境稳定性要求 从满足工业环境稳定性要求的角度,工业防火墙的需要从硬件和软件层次去考虑本身的稳定性对工业网络的影响.从这个角度说,工业防火墙需要同时具备软硬件Bypass功能.一旦设备异常或者重启,会启动Bypass功能,而无须担心因为工业防火墙本身出现问题而导致工业网络断网.Bypass顾名思义,就是旁路保护系统,也就是说可以通过特定的触发状态(断电或死机)让两个网络不通过工业防火墙的系统,而直接物理上导通.而这个时候工业防火墙也就不会再对网络中的数据包做处理了.基于这

《MonkeyRunner原理剖析》第九章-MonkeyImage实现原理 - 第二节 - ADB截屏服务

作者 自主博客 微信 CSDN 天地会珠海分舵 http://techgogogo.com 服务号:TechGoGoGo 扫描码: http://blog.csdn.net/zhubaitian

阶段1 语言基础+高级_1-3-Java语言高级_05-异常与多线程_第5节 线程池_2_线程池的代码实现

JDK1.5之后提供的 Execituors生产线程池的工厂类 线程池的接口类:ExecutorService 1创建线程池的工厂类 创建类实现Runnable接口,重写里面的run方法 传递线程池任务,执行 线程池里一共就两个线程 销毁线程池 线程池销毁后 程序自动停止 线程池毁后再来执行线程任务就会报错. 原文地址:https://www.cnblogs.com/wangjunwei/p/11261573.html

嵌入式行业入门指导---知乎转载【转】

此文是本人在知乎上看的,觉得很好就分享出来了,并不是本人原创 转自:https://www.zhihu.com/question/47881392 作者:shang链接:https://www.zhihu.com/question/47881392/answer/146734937来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 嵌入式Linux+Android学习路线图作者:韦东山 本文目录1. 程序员的三大方向 1.1 专业领域 1.1.1 学术研究 1.1.2