【转】Android 驱动开发系列四

原文网址:http://www.2cto.com/kf/201304/202040.html

时隔多日,终于都抽出时间来写blog了。废话不多说,接着上一篇,这里将介绍如何编写HAL层(硬件抽象层)对应的JNI方法。

这里提到的都是在ICS源码里编译的。

1、定义JNI层接口
进入到android-4.0.4_r1.2/hardware/libhardware/include/hardware目录,并创建 ttt.h 文件,内容如下:

[cpp]
#ifndef ANDROID_TTT_INTERFACE_H  
#define ANDROID_TTT_INTERFACE_H  
#include <hardware/hardware.h>  
 
__BEGIN_DECLS 
 
// 定义模块ID  
#define HELLO_HARDWARE_MODULE_ID    "ttt"  
 
// 硬件模块结构体  
struct ttt_module_t{ 
    struct hw_module_t common; 
}; 
 
// hardware interface struct  
struct ttt_device_t{ 
    struct hw_device_t common; 
    int fd; 
    int(*set_val)(struct ttt_device_t* dev, int val); 
    int(*get_val)(struct ttt_device_t* dev, int* val); 
}; 
 
__END_DECLS 
 
 
#endif

#ifndef ANDROID_TTT_INTERFACE_H
#define ANDROID_TTT_INTERFACE_H
#include <hardware/hardware.h>

__BEGIN_DECLS

// 定义模块ID
#define HELLO_HARDWARE_MODULE_ID "ttt"

// 硬件模块结构体
struct ttt_module_t{
    struct hw_module_t common;
};

// hardware interface struct
struct ttt_device_t{
 struct hw_device_t common;
 int fd;
 int(*set_val)(struct ttt_device_t* dev, int val);
 int(*get_val)(struct ttt_device_t* dev, int* val);
};

__END_DECLS

#endif

2、实现JNI层接口功能
进入到android-4.0.4_r1.2/frameworks/base/services/jni目录,并创建com_android_server_TTTService.cpp文件,其内容如下:

[cpp]
#define LOG_TAG     "TTTService"  
 
#include "jni.h"  
#include "JNIHelp.h"  
#include "android_runtime/AndroidRuntime.h"  
#include <utils/misc.h>  
#include <utils/Log.h>  
#include <hardware/hardware.h>  
#include <hardware/ttt.h>  
#include <stdio.h>  
 
namespace android 

    struct ttt_device_t* ttt_device = NULL; 
 
    // through the HAL interface to set the register value  
    static void ttt_setVal(JNIEnv* env, jobject clazz, jint value){ 
        int val = value; 
        LOGI("TTT JNI: set value %d to device.", val); 
        if(!ttt_device){ 
            LOGI("TTT JNI: device is not open."); 
            return; 
        } 
 
        ttt_device->set_val(ttt_device, val); 
    } 
 
    // through the HAL interface to read the register value  
    static jint ttt_getVal(JNIEnv* env, jobject clazz){ 
        int val = 0; 
        if(!ttt_device){ 
            LOGI("TTT JNI: device is not open."); 
            return val; 
        } 
        ttt_device->get_val(ttt_device, &val); 
 
        LOGI("TTT JNI: get value %d from device.", val); 
 
        return val; 
    } 
 
    // through the HAL interface to open the hardware device  
    static inline int ttt_device_open(const hw_module_t* module, struct ttt_device_t** device){ 
        return module->methods->open(module, HELLO_HARDWARE_MODULE_ID, (struct hw_device_t**)device); 
    } 
 
    // throught the hardware module ID to load the HAL module and open the device  
    static jboolean ttt_init(JNIEnv* env, jclass clazz){ 
        ttt_module_t* module; 
 
        LOGI("TTT JNI: initializing..."); 
        if(hw_get_module(HELLO_HARDWARE_MODULE_ID, (const struct hw_module_t**)&module) == 0){ 
            LOGI("TTT JNI: ttt stub found."); 
            if(ttt_device_open(&(module->common), &ttt_device) == 0){ 
                LOGI("TTT JNI: ttt device is open."); 
                return 0; 
            } 
            LOGE("TTT JNI: failed to open ttt device."); 
            return -1; 
        } 
 
        LOGE("TTT JNI: failed to get ttt stub module."); 
        return -1; 
    } 
 
    // JNI methods table  
    static const JNINativeMethod method_table[] = { 
        {"init_native", "()Z", (void*)ttt_init}, 
        {"setVal_native", "(I)V", (void*)ttt_setVal}, 
        {"getVal_native", "()I", (void*)ttt_getVal}, 
    }; 
 
    // regist JNI method  
    int register_android_server_TTTService(JNIEnv* env){ 
        return jniRegisterNativeMethods(env, "com/android/server/TTTService", method_table, NELEM(method_table)); 
    } 
};

#define LOG_TAG     "TTTService"

#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
#include <utils/misc.h>
#include <utils/Log.h>
#include <hardware/hardware.h>
#include <hardware/ttt.h>
#include <stdio.h>

namespace android
{
    struct ttt_device_t* ttt_device = NULL;

// through the HAL interface to set the register value
    static void ttt_setVal(JNIEnv* env, jobject clazz, jint value){
        int val = value;
        LOGI("TTT JNI: set value %d to device.", val);
        if(!ttt_device){
            LOGI("TTT JNI: device is not open.");
            return;
        }

ttt_device->set_val(ttt_device, val);
    }

// through the HAL interface to read the register value
    static jint ttt_getVal(JNIEnv* env, jobject clazz){
        int val = 0;
        if(!ttt_device){
            LOGI("TTT JNI: device is not open.");
            return val;
        }
        ttt_device->get_val(ttt_device, &val);

LOGI("TTT JNI: get value %d from device.", val);

return val;
    }

// through the HAL interface to open the hardware device
    static inline int ttt_device_open(const hw_module_t* module, struct ttt_device_t** device){
        return module->methods->open(module, HELLO_HARDWARE_MODULE_ID, (struct hw_device_t**)device);
    }

// throught the hardware module ID to load the HAL module and open the device
    static jboolean ttt_init(JNIEnv* env, jclass clazz){
        ttt_module_t* module;

LOGI("TTT JNI: initializing...");
        if(hw_get_module(HELLO_HARDWARE_MODULE_ID, (const struct hw_module_t**)&module) == 0){
            LOGI("TTT JNI: ttt stub found.");
            if(ttt_device_open(&(module->common), &ttt_device) == 0){
                LOGI("TTT JNI: ttt device is open.");
                return 0;
            }
            LOGE("TTT JNI: failed to open ttt device.");
            return -1;
        }

LOGE("TTT JNI: failed to get ttt stub module.");
        return -1;
    }

// JNI methods table
    static const JNINativeMethod method_table[] = {
        {"init_native", "()Z", (void*)ttt_init},
        {"setVal_native", "(I)V", (void*)ttt_setVal},
        {"getVal_native", "()I", (void*)ttt_getVal},
    };

// regist JNI method
    int register_android_server_TTTService(JNIEnv* env){
        return jniRegisterNativeMethods(env, "com/android/server/TTTService", method_table, NELEM(method_table));
    }
};

3、添加JNI初始化调用
修改android-4.0.4_r1.2/frameworks/base/services/jni目录下的 onload.cpp 文件,在 JNI_OnLoad函数中的return之前添加下面一句:

[cpp]
register_android_server_TTTService(env);

register_android_server_TTTService(env);同时,在该文件中的namespace中添加下面一句声明:

[cpp]
int register_android_server_TTTService(JNIEnv* env);

int register_android_server_TTTService(JNIEnv* env);

这样,在系统初始化时,就会调用register_android_server_TTTService方法来加载JNI方法了。

4、添加编译JNI的配置
修改android-4.0.4_r1.2/frameworks/base/services/jni目录下的 Android.mk 文件,在 LOCAL_SRC_FILES 变量中添加下面一行:

[cpp]
com_android_server_TTTService.cpp \

com_android_server_TTTService.cpp \这里是添加编译配置。

5、开始编译
[cpp]
[email protected]:~/workspace/android-4.0.4_r1.2# . build/envsetup.sh  
including device/moto/stingray/vendorsetup.sh 
including device/moto/wingray/vendorsetup.sh 
including device/samsung/crespo4g/vendorsetup.sh 
including device/samsung/crespo/vendorsetup.sh 
including device/samsung/maguro/vendorsetup.sh 
including device/samsung/smdkc110/vendorsetup.sh 
including device/samsung/smdkv210/vendorsetup.sh 
including device/samsung/torospr/vendorsetup.sh 
including device/samsung/toro/vendorsetup.sh 
including device/samsung/tuna/vendorsetup.sh 
including device/ti/panda/vendorsetup.sh 
including sdk/bash_completion/adb.bash 
[email protected]:~/workspace/android-4.0.4_r1.2#

[email protected]:~/workspace/android-4.0.4_r1.2# . build/envsetup.sh
including device/moto/stingray/vendorsetup.sh
including device/moto/wingray/vendorsetup.sh
including device/samsung/crespo4g/vendorsetup.sh
including device/samsung/crespo/vendorsetup.sh
including device/samsung/maguro/vendorsetup.sh
including device/samsung/smdkc110/vendorsetup.sh
including device/samsung/smdkv210/vendorsetup.sh
including device/samsung/torospr/vendorsetup.sh
including device/samsung/toro/vendorsetup.sh
including device/samsung/tuna/vendorsetup.sh
including device/ti/panda/vendorsetup.sh
including sdk/bash_completion/adb.bash
[email protected]:~/workspace/android-4.0.4_r1.2#[cpp] view plaincopypr[email protected]:~/workspace/android-4.0.4_r1.2# mmm frameworks/base/services/jni 
============================================ 
PLATFORM_VERSION_CODENAME=REL 
PLATFORM_VERSION=4.0.4 
TARGET_PRODUCT=full 
TARGET_BUILD_VARIANT=eng 
TARGET_BUILD_TYPE=release 
TARGET_BUILD_APPS= 
TARGET_ARCH=arm 
TARGET_ARCH_VARIANT=armv7-a 
HOST_ARCH=x86 
HOST_OS=linux 
HOST_BUILD_TYPE=release 
BUILD_ID=IMM76I 
============================================ 
make:进入目录‘/home/brantyou/workspace/android-4.0.4_r1.2‘ 
target thumb C++: libandroid_servers <= frameworks/base/services/jni/com_android_server_HelloService.cpp 
target thumb C++: libandroid_servers <= frameworks/base/services/jni/com_android_server_TTTService.cpp 
target thumb C++: libandroid_servers <= frameworks/base/services/jni/onload.cpp 
make: *** 没有规则可以创建“out/target/product/generic/obj/SHARED_LIBRARIES/libandroid_servers_intermediates/LINKED/libandroid_servers.so”需要的目标“out/target/product/generic/obj/lib/libsystem_server.so”。 停止。 
make:离开目录“/home/brantyou/workspace/android-4.0.4_r1.2” 
[email protected]:~/workspace/android-4.0.4_r1.2#

[email protected]:~/workspace/android-4.0.4_r1.2# mmm frameworks/base/services/jni
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=4.0.4
TARGET_PRODUCT=full
TARGET_BUILD_VARIANT=eng
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
TARGET_ARCH_VARIANT=armv7-a
HOST_ARCH=x86
HOST_OS=linux
HOST_BUILD_TYPE=release
BUILD_ID=IMM76I
============================================
make:进入目录‘/home/brantyou/workspace/android-4.0.4_r1.2‘
target thumb C++: libandroid_servers <= frameworks/base/services/jni/com_android_server_HelloService.cpp
target thumb C++: libandroid_servers <= frameworks/base/services/jni/com_android_server_TTTService.cpp
target thumb C++: libandroid_servers <= frameworks/base/services/jni/onload.cpp
make: *** 没有规则可以创建“out/target/product/generic/obj/SHARED_LIBRARIES/libandroid_servers_intermediates/LINKED/libandroid_servers.so”需要的目标“out/target/product/generic/obj/lib/libsystem_server.so”。 停止。
make:离开目录“/home/brantyou/workspace/android-4.0.4_r1.2”
[email protected]:~/workspace/android-4.0.4_r1.2#
矮油~~~这里出错了,提示没有找到 libsystem_server.so 文件。
执行下面的命令,生成 libsystem_server.so 文件:

[cpp]
[email protected]:~/workspace/android-4.0.4_r1.2# make libsystem_server

[email protected]:~/workspace/android-4.0.4_r1.2# make libsystem_server生成之后的提示:

[cpp]
Install: out/target/product/generic/system/lib/libvorbisidec.so 
Install: out/target/product/generic/system/lib/libstagefright_yuv.so 
Install: out/target/product/generic/system/lib/libdrmframework.so 
Install: out/target/product/generic/system/lib/libchromium_net.so 
Install: out/target/product/generic/system/lib/libstagefright_amrnb_common.so 
Install: out/target/product/generic/system/lib/libstagefright_enc_common.so 
Install: out/target/product/generic/system/lib/libstagefright_avc_common.so 
Install: out/target/product/generic/system/lib/libstagefright.so 
Install: out/target/product/generic/system/lib/libstagefright_omx.so 
Install: out/target/product/generic/system/lib/libmediaplayerservice.so 
Install: out/target/product/generic/system/lib/libinput.so 
Install: out/target/product/generic/system/lib/libsystem_server.so 
[email protected]:~/workspace/android-4.0.4_r1.2#

Install: out/target/product/generic/system/lib/libvorbisidec.so
Install: out/target/product/generic/system/lib/libstagefright_yuv.so
Install: out/target/product/generic/system/lib/libdrmframework.so
Install: out/target/product/generic/system/lib/libchromium_net.so
Install: out/target/product/generic/system/lib/libstagefright_amrnb_common.so
Install: out/target/product/generic/system/lib/libstagefright_enc_common.so
Install: out/target/product/generic/system/lib/libstagefright_avc_common.so
Install: out/target/product/generic/system/lib/libstagefright.so
Install: out/target/product/generic/system/lib/libstagefright_omx.so
Install: out/target/product/generic/system/lib/libmediaplayerservice.so
Install: out/target/product/generic/system/lib/libinput.so
Install: out/target/product/generic/system/lib/libsystem_server.so
[email protected]:~/workspace/android-4.0.4_r1.2# 好了,这个问题解决了,我们继续编译这个JNI。

[cpp]
[email protected]:~/workspace/android-4.0.4_r1.2# mmm frameworks/base/services/jni 
============================================ 
PLATFORM_VERSION_CODENAME=REL 
PLATFORM_VERSION=4.0.4 
TARGET_PRODUCT=full 
TARGET_BUILD_VARIANT=eng 
TARGET_BUILD_TYPE=release 
TARGET_BUILD_APPS= 
TARGET_ARCH=arm 
TARGET_ARCH_VARIANT=armv7-a 
HOST_ARCH=x86 
HOST_OS=linux 
HOST_BUILD_TYPE=release 
BUILD_ID=IMM76I 
============================================ 
make:进入目录‘/home/brantyou/workspace/android-4.0.4_r1.2‘ 
target SharedLib: libandroid_servers (out/target/product/generic/obj/SHARED_LIBRARIES/libandroid_servers_intermediates/LINKED/libandroid_servers.so) 
target Symbolic: libandroid_servers (out/target/product/generic/symbols/system/lib/libandroid_servers.so) 
target Strip: libandroid_servers (out/target/product/generic/obj/lib/libandroid_servers.so) 
Install: out/target/product/generic/system/lib/libandroid_servers.so 
make:离开目录“/home/brantyou/workspace/android-4.0.4_r1.2” 
[email protected]:~/workspace/android-4.0.4_r1.2#

[email protected]:~/workspace/android-4.0.4_r1.2# mmm frameworks/base/services/jni
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=4.0.4
TARGET_PRODUCT=full
TARGET_BUILD_VARIANT=eng
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
TARGET_ARCH_VARIANT=armv7-a
HOST_ARCH=x86
HOST_OS=linux
HOST_BUILD_TYPE=release
BUILD_ID=IMM76I
============================================
make:进入目录‘/home/brantyou/workspace/android-4.0.4_r1.2‘
target SharedLib: libandroid_servers (out/target/product/generic/obj/SHARED_LIBRARIES/libandroid_servers_intermediates/LINKED/libandroid_servers.so)
target Symbolic: libandroid_servers (out/target/product/generic/symbols/system/lib/libandroid_servers.so)
target Strip: libandroid_servers (out/target/product/generic/obj/lib/libandroid_servers.so)
Install: out/target/product/generic/system/lib/libandroid_servers.so
make:离开目录“/home/brantyou/workspace/android-4.0.4_r1.2”
[email protected]:~/workspace/android-4.0.4_r1.2#很好,这一次已经顺利的编译完了。

下面我们需要重新打包这个 system.img,包我们编写的JNI方法包含进去:

[cpp]
[email protected]:~/workspace/android-4.0.4_r1.2# make snod 
============================================ 
PLATFORM_VERSION_CODENAME=REL 
PLATFORM_VERSION=4.0.4 
TARGET_PRODUCT=full 
TARGET_BUILD_VARIANT=eng 
TARGET_BUILD_TYPE=release 
TARGET_BUILD_APPS= 
TARGET_ARCH=arm 
TARGET_ARCH_VARIANT=armv7-a 
HOST_ARCH=x86 
HOST_OS=linux 
HOST_BUILD_TYPE=release 
BUILD_ID=IMM76I 
============================================ 
make snod: ignoring dependencies 
Target system fs image: out/target/product/generic/system.img 
out/target/product/generic/system.img total size is 44107008 
[email protected]:~/workspace/android-4.0.4_r1.2#

[email protected]:~/workspace/android-4.0.4_r1.2# make snod
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=4.0.4
TARGET_PRODUCT=full
TARGET_BUILD_VARIANT=eng
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
TARGET_ARCH_VARIANT=armv7-a
HOST_ARCH=x86
HOST_OS=linux
HOST_BUILD_TYPE=release
BUILD_ID=IMM76I
============================================
make snod: ignoring dependencies
Target system fs image: out/target/product/generic/system.img
out/target/product/generic/system.img total size is 44107008
[email protected]:~/workspace/android-4.0.4_r1.2# 这样就成功的把我们编写的JNI打包到 system.img中了。

时间: 2024-10-14 00:38:14

【转】Android 驱动开发系列四的相关文章

Android驱动开发第四章随想

本章主要讲解搭建Android系统移植开发环境的整个流程,首先讲解如何搭建嵌入式交叉开发环境,包括交叉编译环境,各种服务程序和应用程序的安装配置和使用: 1)GNU交叉工具链的下载从ARM官方网站下载www.arm.linux.org.uk,可以从该站点下载2.95.3工具链:ftp://ftp.arm.linux.org.uk/pub/armlinux/toolchain/cross-2.95.3.tar.bz22)cross-2.95.3.tar.bz2包的安装步骤a.#mkdir/usr/

Android深度探索HAL与驱动开发 第四章

Android深度探索HAL与驱动开发 第四章 源代码的下载和编译 读书笔记 一.下载编译和测试Android源代码 1.配置Android源代码下载环境 创建一个用于存放下载脚本文件的目录(可将该文件放到任何一个目录在这里使用-/bin) # mkdir ~/bin # PATH=~/bin:$PATH 2.下载repo脚本文件(用于下载Android源代码) # curl htttps://dl-ssl.google.com/dl/googlesource/git-repo/repo> ~/

Android深度探索(卷1)HAL与驱动开发 第四章 源代码的下载和编译 读书笔记

Android深度探索(卷1)HAL与驱动开发 第四章 源代码的下载和编译 读书笔记     本章学习了使用git下载两套源代码并搭建两个开发环境.分别为Android源代码和Linux内核源代码.Android源代码中包含了HAL(即硬件抽象层) 的代码,并学习了如何搭建这两种开发环境. Android 的移植的本质就是Linux内核的移植,Linux内核的移植主要是Linux驱动的移植.而开发和测试Linux驱动就需要安装以上两个开发环境. 搭建两套环境的具体步骤如下: 一.下载编译和测试A

初入android驱动开发之字符设备(四-中断)

上一篇讲到android驱动开发中,应用是怎样去操作底层硬件的整个流程,实现了按键控制led的亮灭.当然,这是一个非常easy的实例,只是略微演变一下,就能够得到广泛的应用. 如开发扫描头,应用透过监听上报的按键的键值,监听到,则调用扫描头的模块.成功,则点亮LED灯,并把扫描头解码后的条码信息.通过广播的形式发出.又扯到其他地方,这里主要说说中断. 1. 中断的一些概念 中断,是什么? 中断.能够看成是cpu对特殊事件的一种处理的机制,这类特殊事件一般指紧急事件或者说异常事件.非常easy的一

S5PV210开发系列四_uCGUI的移植

S5PV210开发系列四 uCGUI的移植 象棋小子          1048272975 GUI(图形用户界面)极大地方便了非专业用户的使用,用户无需记忆大量的命令,取而代之的是可以通过窗口.菜单.按键等方式进行操作.在某些场合,设计一款人机界面丰富友好的嵌入式产品能赢得更多的用户.笔者此处就S5PV210基于uCGUI图形用户界面的使用作一个简单的介绍. 1. uCGUI移植概述 1.1. S5PV210 Bootloader 笔者的S5PV210的Bootloader设置最高的CPU主频

Android 快速开发系列 打造万能的ListView GridView 适配器

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38902805 ,本文出自[张鸿洋的博客] 1.概述 相信做Android开发的写得最多的就是ListView,GridView的适配器吧,记得以前开发一同事开发项目,一个项目下来基本就一直在写ListView的Adapter都快吐了~~~对于Adapter一般都继承BaseAdapter复写几个方法,getView里面使用ViewHolder模式,其实大部分的代码基本都是类似的

【视频】嵌入式Linux/Android驱动开发揭秘(1)触摸屏驱动开发

嵌入式Linux/Android驱动开发揭秘(1)触摸屏驱动开发 专题简介:自1971年,美国人SamHurst发明了世界上第一个触摸传感器以来,触摸屏技术不断革新,给了程序设计师和UI工程师无限的想象空间,它极大改善了终端用户对各种设备的操作方便程度,现在我们的日常生活如手机.平板等,已经很大程度上依赖于和习惯于使用和操作触摸屏.做为工程师,我们很有必要掌握触摸屏的工作原理和软件驱动方法,如果您对一窥如何在嵌入式中操控和使用触摸屏这一司空见惯却又神奇的技术感兴趣,敬请关注! 1.LINUX驱动

Android驱动开发前的准备

最近看了一些Android驱动开发前需要知道的资料,收获很多,接下来就谈谈我自己的一些心得体会. Android在近几年时间发展迅速,已经成为智能手机操作系统的老大.不过,因为Android原生的代码支持的设备并不多,所以我们要想在自己的设备上完美地运行Android就需要另外地开发一些程序,从而可以让Android识别相应设备的硬件,这个过程就成为Android移植. Android移植可以分为两部分:应用移植和系统移植.其中,应用移植是指将Android系统架构的第四层应用程序移植到某一个特

Android驱动开发5-8章读书笔记

Android驱动开发读书笔记                                                              第五章 S5PV210是一款32位处理器,具有低功耗的的特点,可为移动设备和一般应用提高性能的微处理器解决方案.它集成了ARM CORTEX-A8核心.实现了ARM架构V7且支持外围设备.他的关键功能是“以带有NEON的cpu子系统为基础的arm”,32/32kb i/d缓存,512kb l2缓存,操作频率800hz为1.1v,1ghz为1.2