s5p4418 Android 4.4.2 驱动层 HAL层 服务层 应用层 开发流程记录(二 硬件抽象层HAL)
欢迎转载,务必注明出处:http://blog.csdn.net/wang_shuai_ww/article/details/44305599
本篇文章记录硬件抽象层。
还是跟之前一样,主要参考《Android系统源码情景分析》。
一.硬件抽象层
书里面写的是在/hardware/libhardware目录下写硬件抽象层,我这里并没有在该目录下,因为我使用的是与板子相关的,所以我就放在了板级目录下了,路径为/device/nexell/realarm,在/device/nexell/realarm路径下建立一个led文件夹来存放需要的.c、.h、.mk文件,我的文件名为led.c、led.h、Android.mk,源码分别如下:
led.c:
#include <hardware/hardware.h>
#include "led.h"#include <fcntl.h>
#include <errno.h>
#include <cutils/log.h>
#include <cutils/atomic.h>// 引入log头文件
#include <android/log.h>
// log标签
#define TAG "Led_Load_HAL"
// 定义info信息
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG,__VA_ARGS__)
// 定义debug信息
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)
// 定义error信息
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG,__VA_ARGS__)#define DEVICE_NAME "/dev/real_led"
#define MODULE_NAME "led"
#define MODULE_AUYHOR "wsh_sean@qq.com"#define LED_ON 1
#define LED_OFF 0static int led_device_open(const struct hw_module_t *module, const char *id, struct hw_device_t **device);
static int led_device_close(struct hw_device_t *device);static int led_set_on(struct led_device_t *dev, int num);
static int led_set_off(struct led_device_t *dev, int num);static struct hw_module_methods_t led_module_methods = {open: led_device_open
};struct led_module_t HAL_MODULE_INFO_SYM = {common: {tag: HARDWARE_MODULE_TAG,version_major: 1,version_minor: 0,id: LED_HARDWARE_MODULE_ID,name: DEVICE_NAME,author: MODULE_AUYHOR,methods: &led_module_methods,}
};static int led_device_open(const struct hw_module_t *module, const char *id, struct hw_device_t **device) {if(!strcmp(id, LED_HARDWARE_DEVICE_ID)) {struct led_device_t *dev;dev = (struct led_device_t *)malloc(sizeof(struct led_device_t));if(!dev) {LOGE("Failed to alloc space for led_device_t");return -EFAULT;}memset(dev, 0, sizeof(struct led_device_t));dev->common.tag = HARDWARE_MODULE_TAG;dev->common.version = 0;dev->common.module = (hw_module_t *)module;dev->common.close = led_device_close;dev->set_on = led_set_on;dev->set_off = led_set_off;if((dev->fd = open(DEVICE_NAME, O_RDWR)) == -1) {LOGE("Failed to open device file "DEVICE_NAME"-- %s.", strerror(errno));free(dev);return -EFAULT;}*device = &(dev->common);LOGI("Open device file "DEVICE_NAME" successfully.");return 0;}return -EFAULT;
}static int led_device_close(struct hw_device_t *device){struct led_device_t *led_device = (struct led_device_t *)device;if(led_device){close(led_device->fd);free(led_device);}return 0;
}static int led_set_on(struct led_device_t *dev, int num){if(!dev){LOGE("Null dev pointer.");return -EFAULT;}LOGI("Set the first %d LED lights.", num);ioctl(dev->fd, LED_ON, num);return 0;
}static int led_set_off(struct led_device_t *dev, int num){if(!dev){LOGE("Null dev pointer.");return -EFAULT;}LOGI("Set the first %d LED close.", num);ioctl(dev->fd, LED_OFF, num);return 0;
}
led.h:
#ifndef ANDROID_LED_INTERFACE_H
#define ANDROID_LED_INTERFACE_H#include <hardware/hardware.h>__BEGIN_DECLS#define LED_HARDWARE_MODULE_ID "led"
#define LED_HARDWARE_DEVICE_ID "led"/*自定义模块结构体*/
struct led_module_t {struct hw_module_t common;
};/*自定义设备结构体*/
struct led_device_t {struct hw_device_t common;int fd;int (*set_on)(struct led_device_t *dev, int num);int (*set_off)(struct led_device_t *dev, int num);
};__END_DECLS
#endif
Android.mk:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := led.c
LOCAL_SHARED_LIBRARIES := liblog
#LOCAL_C_INCLUDES += $(JNI_H_INCLUDE)
LOCAL_LDLIBS:=-L$(SYSROOT)/usr/lib -llog
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
LOCAL_MODULE := led.defaultinclude $(BUILD_SHARED_LIBRARY)
上面三个文件生成的是.so文件,该硬件抽象层为JNI方法提供接口。
编译命令是,进入Android源码根目录,执行下面的命令:
mmm ./device/nexell/realarm/led/
在执行上面的mmm命令时,先确保已经把Android源码的环境变量已经添加进系统,也就是是否执行过source ./build/envsetup.sh 这条命令了。
另外在使用mmm指令时,如果没有使用lunch命令选择过编译的板级目标,那么一般默认的可能不是需要的板级目标,所以要使用lunch命令进行选择一下,如下所示:
<strong><span style="color:#ff0000;">wsh@ubuntu:/wsh_space/nexell/s5p4418/debug/android/android$ lunchYou're building on LinuxLunch menu... pick a combo:1. aosp_arm-eng2. aosp_x86-eng3. aosp_mips-eng4. vbox_x86-eng5. mini_x86-userdebug6. mini_mips-userdebug7. mini_armv7a_neon-userdebug8. aosp_manta-userdebug9. aosp_drone2-userdebug10. aosp_drone-userdebug11. aosp_realarm-userdebug12. aosp_grouper-userdebug13. aosp_deb-userdebug14. aosp_flo-userdebug15. aosp_tilapia-userdebug16. aosp_hammerhead-userdebug17. aosp_mako-userdebugWhich would you like? [aosp_arm-eng]</span></strong>
我使用的是realarm的板子,所以选择数字11。
编译完成后,在out/target/product/realarm/system/lib/hw目录下即可看到led.default.so这个文件。
二.硬件访问服务JNI方法
下面的部分,新手可能比较难理解,不过没关系,照着写先实现功能再说,以后慢慢自然就了解了。
1.首先是硬件访问服务接口
硬件访问服务接口一般是在/frameworks/base/core/java/android/os目录下定义。我这里的文件名是ILedService.aidl,源码如下:
package android.os;interface ILedService{int seton(int num);int setoff(int num);
}
为了能够编译它需要修改 /frameworks/base/目录下的Android.mk文件,添加一行代码:core/java/android/os/ILedService.aidl \
是加在LOCAL_SRC_FILES += \后面的任何一个位置,一般是放在最后,由于太长,只贴一部分如下所示:
packages/services/Proxy/com/android/net/IProxyCallback.aidl \packages/services/Proxy/com/android/net/IProxyPortListener.aidl \core/java/android/os/ILedService.aidl \
然后使用下面命令进行编译:
mmm ./frameworks/base/
2.实现硬件访问服务
/** Copyright (C) 2013 The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/package com.android.server;import android.content.Context;
import android.os.ILedService;
import android.util.Slog;/*** Shared singleton foreground thread for the system. This is a thread for regular* foreground service operations, which shouldn't be blocked by anything running in* the background. In particular, the shared background thread could be doing* relatively long-running operations like saving state to disk (in addition to* simply being a background priority), which can cause operations scheduled on it* to be delayed for a user-noticeable amount of time.*/
public class LedService extends ILedService.Stub {private static final String TAG = "LedService";private int mPtr = 0;LedService(){mPtr = init_native();if(mPtr == 0){Slog.e(TAG, "Failed to initialize Led service.");}}public int setOn(int num){if(mPtr == 0){Slog.e(TAG, "Led service is not initialize.");return 0;}setOn_native(mPtr, num);return 0;}public int setOff(int num){if(mPtr == 0){Slog.e(TAG, "Led service is not initialize.");return 0;}setOff_native(mPtr, num);return 0;}private static native int init_native();private static native int setOn_native(int ptr, int num);private static native int setOff_native(int ptr, int num);
};
<span style="font-family: Arial; background-color: rgb(255, 255, 255);">由上面代码可知,实现了硬件服务接口setOn和setOff的具体方法,由于java不能够直接使用HAL层提供的接口,所以这里使用native方式来与JNI方法连接。</span>
编译:
mmm ./frameworks/base/services/java/
编译得到的server.jar就包含了LedService类。
3.硬件访问服务的JNI方法
目录为/frameworks/base/services/jni,文件命名为com_android_server_LedService.cpp,要注意命名格式,一般为com_android_server_xxx.cpp。
源码如下:
#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"#include <utils/misc.h>
#include <utils/Log.h>
#include <hardware/hardware.h>
#include "../../device/nexell/realarm/led/led.h"#include <stdio.h>// 引入log头文件
#include <android/log.h>
// log标签
#define LOG_TAG "LedServiceJNI"
// 定义info信息
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
// 定义debug信息
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
// 定义error信息
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)namespace android
{static jint led_seton(JNIEnv *env, jobject clazz, jint ptr, jint number){led_device_t *device = (led_device_t *)ptr;if(!device){LOGE("Device led is not open");return 0;}int num = number;LOGI("Set the first %d LED lights.", num);device->set_on(device, num);return num;}static jint led_setoff(JNIEnv *env, jobject clazz, jint ptr, jint number){led_device_t *device = (led_device_t *)ptr;if(!device){LOGE("Device led is not open");return 0;}int num = number;LOGI("Set the first %d LED close.", num);device->set_off(device, num);return num;}static inline int led_device_open(const hw_module_t *module, struct led_device_t **device){return module->methods->open(module, LED_HARDWARE_DEVICE_ID, (struct hw_device_t**)device);}static jint led_init(JNIEnv *env, jobject clazz){led_module_t *module;led_device_t *device;LOGI("Initializing HAL stub led......");if(hw_get_module(LED_HARDWARE_MODULE_ID, (const struct hw_module_t**)&module) == 0){LOGI("Device led found");if(led_device_open(&(module->common), &device) == 0){LOGI("Device led is open.");return (jint)device;}LOGE("Failed to open device led.");return 0;}LOGE("Failed to get HAL stub led.");return 0;}static const JNINativeMethod method_table[] = {{"init_native", "()I", (void*)led_init},{"setOn_native", "(II)I", (void*)led_seton},{"setOff_native", "(II)I", (void*)led_setoff},};int register_android_server_LedService(JNIEnv *env){return jniRegisterNativeMethods(env, "com/android/server/LedService", method_table, NELEM(method_table));}
};
另外还需要修改两个文件。
修改/frameworks/base/services/jni/onload.cpp,完整文件如下:
/** Copyright (C) 2009 The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/#include "JNIHelp.h"
#include "jni.h"
#include "utils/Log.h"
#include "utils/misc.h"namespace android {
int register_android_server_AlarmManagerService(JNIEnv* env);
int register_android_server_ConsumerIrService(JNIEnv *env);
int register_android_server_InputApplicationHandle(JNIEnv* env);
int register_android_server_InputWindowHandle(JNIEnv* env);
int register_android_server_InputManager(JNIEnv* env);
int register_android_server_LightsService(JNIEnv* env);
int register_android_server_PowerManagerService(JNIEnv* env);
int register_android_server_SerialService(JNIEnv* env);
int register_android_server_UsbDeviceManager(JNIEnv* env);
int register_android_server_UsbHostManager(JNIEnv* env);
int register_android_server_VibratorService(JNIEnv* env);
int register_android_server_SystemServer(JNIEnv* env);
int register_android_server_location_GpsLocationProvider(JNIEnv* env);
int register_android_server_location_FlpHardwareProvider(JNIEnv* env);
int register_android_server_connectivity_Vpn(JNIEnv* env);
int register_android_server_AssetAtlasService(JNIEnv* env);
int register_android_server_LedService(JNIEnv *env);//user add
};using namespace android;extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)
{JNIEnv* env = NULL;jint result = -1;if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {ALOGE("GetEnv failed!");return result;}ALOG_ASSERT(env, "Could not retrieve the env!");register_android_server_PowerManagerService(env);register_android_server_SerialService(env);register_android_server_InputApplicationHandle(env);register_android_server_InputWindowHandle(env);register_android_server_InputManager(env);register_android_server_LightsService(env);register_android_server_AlarmManagerService(env);register_android_server_UsbDeviceManager(env);register_android_server_UsbHostManager(env);register_android_server_VibratorService(env);register_android_server_SystemServer(env);register_android_server_location_GpsLocationProvider(env);register_android_server_location_FlpHardwareProvider(env);register_android_server_connectivity_Vpn(env);register_android_server_AssetAtlasService(env);register_android_server_ConsumerIrService(env);register_android_server_LedService(env);//user addreturn JNI_VERSION_1_4;
}
添加了int register_android_server_LedService(JNIEnv *env);//user add和register_android_server_LedService(env);//user add。
修改/frameworks/base/services/jni/Android.mk文件,添加如下:
LOCAL_SRC_FILES:= \......com_android_server_LedService.cpp \onload.cpp
然后编译之,命令为:
mmm ./frameworks/base/services/jni/
生成的libandroid_servers.so文件就包含了我们实现的native方法了。 到此硬件访问服务LedService的实现就完成了,下面介绍怎么启动它。
三.启动硬件服务的方法
该部分的目的是让系统在启动的时候就加载led服务。
修改目录/frameworks/base/services/java/com/android/server/目录下的SystemServer.java文件,如下所示:
ActivityManagerService.self().systemReady(new Runnable() {public void run() {<pre name="code" class="cpp"><span style="white-space:pre"> </span>......
<span style="white-space:pre"> </span>//user addtry {Slog.i(TAG, "Realarmled service");ServiceManager.addService("led", new LedService());} catch (Throwable e) {Slog.e(TAG, "Failure starting Realarmled Service", e);}
<span style="white-space:pre"> </span>}
让系统在启动的时候加载LedService服务。
编译:
mmm ./frameworks/base/services/java/
到这里,out/target/product/realarm/system目录下就已经包含了我们所编译后的jar和.so文件了,打包系统文件烧写到开发板,下一个博客记录怎么写配套的应用程序app。
注意:打包之前检查一下ueventd.realarm.rc这个文件的最后时候有这一句/dev/real_led 0666 systemsystem,该句是修改驱动程序生成的real_led设备节点权限,以提供给HAL使用,否则会提示没有权限,无法打开的错误。
应用程序的写法介绍用两种方式,eclipse和Android源码目录下这两种方式。这里面涉及一些库的使用题,也是最头痛的事情,怎么让eclipse能够应用我们自己的类。
s5p4418 Android 4.4.2 驱动层 HAL层 服务层 应用层 开发流程记录(二 硬件抽象层HAL)相关推荐
- s5p4418 Android 4.4.2 驱动层 HAL层 服务层 应用层 开发流程记录(一 硬件驱动层)
欢迎转载,务必注明出处:http://blog.csdn.net/wang_shuai_ww/article/details/44303069 本文章是记录Android开发中驱动层.HAL层.应用层 ...
- s5p4418 Android 4.4.2 驱动层 HAL层 服务层 应用层 开发流程记录(三 APP应用)
欢迎转载,务必注明出处:http://blog.csdn.net/wang_shuai_ww/article/details/44416041 eclipse完整工程下载地址:http://downl ...
- s5p4418 Android 4.4.2 驱动层 HAL层 服务层 应用层 开发流程记录(二 硬件抽象层HAL 第二种 ioctl操作方法)
欢迎转载,务必注明出处:http://blog.csdn.net/wang_shuai_ww/article/details/44407641 本篇与http://blog.csdn.net/wang ...
- Android 10.0 SystemUI下拉状态栏UI定制化开发系列(十二)
目录 1.概述 2.核心代码 3.核心代码部分分析 3.1 NotificationStackScrollLayout.java代码分析 3.2接下来分析Activat
- Android应用开发 led 驱动层 hal硬件抽象层 应用层 详细教程记录(含源码)
本篇文章是为了能够更好的搜索到介绍驱动到应用的详细介绍文章. 关于驱动层 hal硬件抽象层 应用层请参考s5p4418 Android 4.4.2 驱动层 HAL层 服务层 应用层 开发流程记录系列, ...
- 解密:IT运维艺术之集群(4层AND7层)
负载均衡 概述; 负载均衡 建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽.增加吞吐量.加强网络数据处理能力.提高网络的灵活性和可用性. 负载均衡,英文名称为Load ...
- android调频收音机代码,android 收音机 FM 驱动 hal层 框架层以及应用层代码
[实例简介] android 收音机 FM 驱动 hal层 框架层以及应用层代码 方法一 不需要framework部分 1.fm放到 \hardware\rk2x 2.FmRadio 放到 packa ...
- Android 底层驱动开发步骤——linux内核层、HAL层、JNI层
1.Linux驱动实现 2.Linux内核驱动测试 3.Android HAL层实现 4.Aidl实现 5.Service java实现 6.Service jni 实现 7.注册service和jn ...
- Android 系统(4)---Android HAL层与Linux Kernel层驱动开发简介
Android HAL层与Linux Kernel层驱动开发简介 近日稍微对Android中的驱动开发做了一些简要的了解,稍稍理清了一下Android驱动开发的套路,总结一下笔记. HAL:Hardw ...
最新文章
- 如何仿写thinkphp的C方法?
- 使用JavaMail发送邮件,465端口开启ssl加密传输
- mac下日期、时间戳互转
- Android: 生成安卓可使用的Tflite文件
- 关于用批处理写ftp上传文件
- 未为dll加载任何符号_专家发现aspersky 和Trend Micro安全性解决方案中的DLL劫持问题...
- python与数据处理_python数据处理:数据合并和Reshaping
- C++连接mysql及遇到的相关问题
- windows守护进程_在Linux的Windows子系统上(WSL)使用Docker(Ubuntu)
- pdf在线翻译_如何将英文的PDF文档翻译成中文简体?
- Excel条件格式化(conditional formatting)应用
- jQuery 学习笔记 事件委派
- R语言——决策树模型
- BAJ占领A股市场!
- 资深程序员的书单 - 转载自@Axb
- Atitit Atitit.软件兼容性原理----------API兼容 Qa7
- 蓝桥杯 省赛 杨辉三角形 python组(转)
- 微信分享只有链接没有图标和标题正文
- 利用 UPnP 的反射攻击分析
- 基于Vue使用Arco Design组件封装一个七牛云上传图片的函数
热门文章
- 网上选课系统java大作业_Java面向对象设计大作业——公选课选课系统
- mysql 两张表合并查询_mysql中的分区表和合并表详解(一个常见知识点)
- python应用于期货_Python期货量化交易基础教程(17)
- php 图片上传 水印,PHP - 图片上传并添加水印
- python定义x_Python 定义函数(示例代码)
- java压缩流的用法_Java对压缩包的操作(解压缩)
- 哪些计算机p玩游戏,有了这个神器,你的电脑玩什么游戏都带得动
- python requests发送websocket_Pywss - 用python实现WebSocket服务端
- android 模拟器 相册里传照片_引力相册APP下载-引力相册下载v1.1 官方版
- Pandas数据排序,人人都能学会的几种方法