HAL(4) -- 开发android源码硬件访问服务和应用测试程序

本文详细介绍了在Android系统中实现硬件访问服务的过程,包括定义接口、实现服务、JNI方法编写、系统启动配置和应用集成。实现了从硬件抽象层到应用程序框架层的交互,使开发者能够高效地访问和控制硬件资源。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


通常情况下,开发好硬件抽象层模块后,通常需要在应用程序宽假层中实现一个硬件访问服务!
硬件访问服务通过硬件抽象层模块来为应用程序提供硬件读写操作。
由于硬件抽象层模块式使用C/C++语言来开发,应用程序框架层中的硬件访问服务是使用java语言来开发,
因此,硬件访问服务需要通过java接口(JNI)来调用硬件抽象层模块!
 
 
(1):定义硬件访问接口 (以下内容涉及aidl,有兴趣的读者可以看一下android应用的远程service相关的内容)
 
在Android系统中,通常把硬件访问服务接口定义在frameworks/base/core/java/android/os目录中,所有在这里,我们把服务接口 --zhx_print_service.aidl也保存到这里!内容:
 
frameworks/base/core/java/android/os/zhx_print_service.aidl
 
package android.os;

interface zhx_print_service
{
    void setVal(int val);
    int getVal();
}
然后再frameworks/base/目录中,打开里面的Android.mk文件修改LOCAL_SRC_FILES变量。
 
LOCAL_SRC_FILES += \
...
voip/java/android/net/sip/ISipService.aidl \
core/java/android/os/zhx_print_service.aidl
 
接在在当前目录下编译该硬件访问服务接口,操作如下:
 

ics/frameworks/base$ mm
 
通过上面操作后,编译后得到的framework.jar文件就会包括zhx_print_service接口了!!!
 
 
(2):实现硬件访问服务 (就相当于定义一些可以给java调用的函数!)
 
frameworks/base/service/java/com/android/server/zhx_Print_Service.java
 
package com.android.server;

import android.content.Context;
import android.util.Slog;
import android.os.zhx_print_service;

public class zhx_Print_Service extends zhx_print_service.Stub
{
    private static final String TAG ="zhx Service : ";

    private int mPtr = 0;

    zhx_Print_Service()
    {
        /*zhx_print_init 为jni层函数,该函数通过调用HAL层函数实现对驱动的调用*/

       mPtr = zhx_print_init();            

        if(mPtr != 0)
        {
            Slog.e(TAG,"Failed to initialize freg service.");
        }
    }

    public void setVal(int val)
    {
        if(zhx_print_set_val(val)== 0)
        {
            Slog.i(TAG,"done with the setting");
        }
        else
        {
            Slog.e(TAG,"setting val error");
        }
    }


    public int getVal()
    {
        int val = 0;
        Slog.i(TAG,"before to get,the val is "+val);
        val = zhx_print_get_val();
        Slog.i(TAG,"get the val by the \"zhx_print_get_val val\" = "+val);
        return val;
    }

    //声明以下函数时JNI层中定义
    public native int zhx_print_get_val();
    public native int zhx_print_set_val(int val);
    public native int zhx_print_init();
}
硬件访问服务zhx_Print_Service继承了zhx_print_service.Stub类,
并且实现了该zhx_print_service.aidl接口定义的函数setVal和getVal!
 
编写好源码后,我们需要执行以下命令:
 
ics/frameworks/base/services/java$ mm
 
编译好后,在services.jar文件中就包含有zhx_Print_Service类了!!!
 
(3):实现硬件访问服务的JNI方法
 
Android系统源码中,通常把硬件访问服务的JNI方法放到frameworks/base/service/jni目录中,
所有,在这里,我们把实现硬件访问服务zhx_Print_Service.java的JNI方法
com_android_service_zhx_print_service.cpp也保存到这个目录中,内容如下:
 
frameworks/base/services/jni/com_android_server_zhx_print_server.cpp(jni也可以用c语言来编写)
 
#define LOG_TAG"zhx_jni :"

/*jni使用头*/
#include <jni.h>
#include <JNIHelp.h>
/*HAL层使用头*/
#include <hardware/hardware.h>
#include <hardware/zhx_print.h>

/*log打印信息头  同时宏定义LOG_TAG也是属于log.h打印信息中的定义,
* LOG_TAG必须在log.h前定义*/

#include <utils/Log.h>

#include <stdio.h>

/*函数声明*/
int print_get_val(JNIEnv *env,jobject obj);
int print_set_val(JNIEnv *env,jobject obj,jint val);
int print_init(JNIEnv *env,jobject obj);



/*定义全局变量*/
struct print_device_t *device_dev = NULL;
struct print_module_t *module_dev = NULL;

namespace android {

/*读取数值*/
int print_get_val(JNIEnv *env,jobject obj)
{
    int ret = -1;
    int val = 0;

    ret = device_dev->get_val(device_dev,&val);
    if(ret == 0)
    {
        LOGI("get val sucessfully");
        return val;
    }

    else
    {
        LOGE("fail to get val");
        return ret;
    }
    return val;
}

/*设置数值  sucess = 0 fail < 0*/
int print_set_val(JNIEnv *env,jobject obj,jint val)
{
    int ret = -1;
    ret = device_dev->set_val(device_dev,val);

    if(ret == 0)
    {
        LOGI("set val sucessfully.");
    }
    else
    {
        LOGE("error to set val");
    }

    return ret;
}


int zhx_print_open(struct hw_module_t*dev)
{
    int ret = -1;

    /*调用HAl打开函数*/
    ret = dev->methods->open(dev,"zhx_print",
            (struct hw_device_t**)&device_dev);

    if(ret == 0)
    {
        LOGI("Found device sucessfully!");
    }
    else
    {
        LOGE("ERROR : not Found device");
    }

    return ret;

}

/**/
int print_init(JNIEnv *env,jobject obj)
{
    int ret = -1;
    if(!hw_get_module("zhx_print",(conststruct hw_module_t **)&module_dev))    
    {
        LOGI("Found the HAL module");
        ret = zhx_print_open(&(module_dev->common));
        return ret;
    }

    return ret;
}


/*jni映射方法*/
static const JNINativeMethod method_table[] = 
{
    {"zhx_print_get_val","()I",(void*)print_get_val},
    {"zhx_print_set_val","(I)I",(void*)print_set_val},
    {"zhx_print_init","()I",(void*)print_init},
};

int register_android_server_zhx_Print_Service(JNIEnv*env)
{
    return jniRegisterNativeMethods(env,
            "com/android/server/zhx_Print_Service",
            method_table,
            NELEM(method_table));
}

};
 
编写好jni文件后,我们还需要修改frameworks/hase/services/jni目录下的onload.cpp文件,在里面添加register_android_server_zhx_print_service函数声明和调用。添加内容如下:
 
frameworks/base/services/jni/onload.cpp
 
namespace android
{
    。。。
    int register_android_server_zhx_print_service(JNIEnv* env);
}
。。。
extern "C" jint JNI_OnLoad(JavaVM *vm,void*reserved)
{
    。。。
    register_android_server_zhx_print_service(env);
    
    return JNI_VERSION_1_4;   
}
 
然后,进入到frameworks/base/service/jni目录中,打开里面的Android.mk文件,修改变量LOCALSRC_FILES的值。
 
LOCAL_SRC_FILE += \
。。。
com_android_server_zhx_print_service.cpp \
onload.cpp
 
修改好后,我们在执行如下命令:
ics/frameworks/base/services/jni$ mm
 
 
编译好后,得到的libandroid_servers.so文件包中就包含,print_get_val,print_set_val,prnt_init这三个JNI方法了!
到这里,硬件访问服务zhx_print_service就实现了,下面我们来介绍如何在系统进程system中启动它。
 
(4)启动硬件访问服务
 
在这里,我们把硬件访问服务运行在系统进程System中,就实现开机自动启动!!
 
首先,进入frameworks/base/services/java/com/android/server目录中,打开里面的SystemServer.java文件,修改
ServerThread类的成员函数run的实现,如下所示。
 
class ServerThread extends Thread {
。。。。
@Override 
public void run() {
 。。。。

if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
    ...
    try
    { 
        Slog.i(TAG,"zhx_print_service");
         //在系统开机启动的时候就创建zhx_Print_service
        ServiceManager.addService("zhx_print",new zhx_Print_Service());   
    }catch(Throwable e)
    {
        Slog.e(TAG,"Failure starting zhx_print_Service");

    }

}
 
最后,我们需要执行如下命令来重新编译services模块:
 
ics/frameworks/base/services/java$ mm
 
并以好后,得到services.jar 文件就包含有硬件访问服务zhx_print_service,并在系统启动时,将他运行在系统进程System中。
 
到这里,我们在重新打包Android系统镜像文件system.img.
/ics$ make snod
 
到这里,整个系统的硬件访问服务就编译完成了!!!
接下来我们在编译一个系统的应用程序来使用这个硬件访问服务!
 
(5)Android应用程序来实现硬件访问服务
 
由于这个应用程序是实验性质,所有我们将他放在packages/experimental目录中!!!对应的文件夹名字为
Zhx_Print 在这里,我提供一个该应用程序的压缩包,
读者只需要直接把压缩包解压到packages/experimental目录中即可!
 
 
当在packages/experimental创建了工程Zhx_Print后,我们还需要执行以下命令:
ics/packages/experimental/Zhx_Print$     mm
android/ics$                             make snod
 
打包好后,在Android系统镜像文件system.img中就包含有应用程序zhx_print了!
 
(6) 运行Android模拟器:
USER-NAME@MACHINE-NAME:~/Android$ emulator-kernel kernel/common/arch/arm/boot/zImage&
 
 
在Home Screen中就可以看到zhx_print应用程序了!!!!!!!
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值