zoukankan      html  css  js  c++  java
  • 【转】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]
    root@brantyou-ubuntu:~/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 
    root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2# 

    root@brantyou-ubuntu:~/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
    root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2#[cpp] view plaincopyprint?root@brantyou-ubuntu:~/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” 
    root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2#  

    root@brantyou-ubuntu:~/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”
    root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2#
    矮油~~~这里出错了,提示没有找到 libsystem_server.so 文件。
    执行下面的命令,生成 libsystem_server.so 文件:

    [cpp]
    root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2# make libsystem_server 

    root@brantyou-ubuntu:~/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 
    root@brantyou-ubuntu:~/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
    root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2# 好了,这个问题解决了,我们继续编译这个JNI。

    [cpp]
    root@brantyou-ubuntu:~/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” 
    root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2# 

    root@brantyou-ubuntu:~/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”
    root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2#很好,这一次已经顺利的编译完了。


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

    [cpp]
    root@brantyou-ubuntu:~/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 
    root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2#  

    root@brantyou-ubuntu:~/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
    root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2# 这样就成功的把我们编写的JNI打包到 system.img中了。

  • 相关阅读:
    IIS配置Asp.net时,出现“未能加载文件或程序集“System.Web.Extensions.Design, Version=1.0.61025.0”
    如何ping测有端口的网站
    职场情况--小领导人品不好,大领导很欣赏我,该不该将小领导的搓事告诉大领导?
    https://www.cnblogs.com/netoxi/p/7258895.html
    java基本数据类型
    不用犹豫什么时候声明实例变量或者拒不变量
    java多线程
    架构考虑
    多线程一共就俩问题:1.线程安全(访问共享数据) 2.线程通信(wait(),notify())
    csrf攻击
  • 原文地址:https://www.cnblogs.com/wi100sh/p/4338512.html
Copyright © 2011-2022 走看看