实现自己的HAL2 HAL helloworld 之HAL层代码的编写

实现自己的HAL2 HAL helloworld 之HAL层代码的编写

编写目标

  • 编写一个实现简单功能(加法运算)的HAL代码,不涉及驱动操作
  • 编译通过,并打包到vendor.img中

编写头文件helloworld.h

  • 在Z:\itop-3399_8.1\hardware\libhardware\include\hardware 下创建helloworld.h
#define ANDROID_HELLOWORLD_INTERFACE_H
#include <hardware/hardware.h>

__BEGIN_DECLS

//定义模块ID
#define HELLOWORLD_HARDWARE_MODULE_ID "helloworld"

//硬件模块结构

struct helloworld_module_t
{
    struct hw_module_t common;
    char * description;
    int methodsNum;
};

//硬件接口结构体

struct helloworld_device_t
{
    struct  hw_device_t common;
    int (*helloworld_add) (struct helloworld_device_t *dev, int a , int b, int *c);
};


__END_DECLS

编写helloworld.c

  • 在系统源码的这个路径 Z:\itop-3399_8.1\hardware\libhardware\modules ,下新建helloworld 文件夹
  • 在helloworld文件夹下创建helloworld.c文件
    代码
#define LOG_TAG "HelloWorld"

#include <hardware/hardware.h>
#include <malloc.h>
#include <fcntl.h>
#include <errno.h>
#include <cutils/log.h>
#include <hardware/helloworld.h>

#define MODULE_NAME "helloworld"
#define MODULE_DES "HelloWorld : Implement Add function"
#define MODULE_AUTHOR "963416867@qq.com"

static int helloworld_open(const struct hw_module_t* module, const char* id, struct hw_device_t** device);
static int helloworld_close(struct hw_device_t* device);
static int helloworld_add(struct helloworld_device_t *dev, int a , int b, int *c);
static int  helloworld_open(const struct hw_module_t* module, const char* id, struct hw_device_t** device){

    struct helloworld_device_t *dev;
    
    dev = (struct helloworld_device_t *)malloc(sizeof(*dev));
    if(!dev){
        ALOGE("Helloworld open: faild to alloc device space");
        return -EFAULT;
    }

    memset(dev, 0, sizeof(*dev));
    dev->common.tag = HARDWARE_MODULE_TAG;
    dev->common.version = 0;
    dev->common.module = module;
    dev->common.close = helloworld_close;
    dev->helloworld_add = helloworld_add;
    
    * device = &(dev->common);
    ALOGI("helloworld open: driver file successfully");
   
    return 0;
    }

static struct  hw_module_methods_t helloworld_module_methods_t = {
    .open = helloworld_open
};

//module struct  注意这里必须是 HAL_MODULE_INFO_SYM 变量名

struct helloworld_module_t HAL_MODULE_INFO_SYM = {

    .common = {
        .tag = HARDWARE_MODULE_TAG,
        .module_api_version = 1,
        .hal_api_version = 0,
        .id = HELLOWORLD_HARDWARE_MODULE_ID,
        .name = MODULE_NAME,
        .author = MODULE_AUTHOR,
        .methods = &helloworld_module_methods_t
    },

    .description = MODULE_DES,
    .methodsNum = 3

};

static int helloworld_close(struct hw_device_t* device){
    struct helloworld_device_t* helloworld_device= (struct helloworld_device_t *)device;
    if(helloworld_device){
        free(helloworld_device);
    }

    return 0;
}

static int helloworld_add(struct helloworld_device_t *dev, int a , int b, int *c){
    ALOGI("helloworld add: success %d + %d", a, b);
    *c = a + b;
    return 0;
}

编写Android.mk 编译文件

  • Android.mk
# Copyright (C) 2008 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.


LOCAL_PATH := $(call my-dir)

# HAL module implemenation stored in
# hw/<OVERLAY_HARDWARE_MODULE_ID>.<ro.product.board>.so
include $(CLEAR_VARS)

#用于打印的库
LOCAL_LDLIBS := -llog

LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_PROPRIETARY_MODULE := true
LOCAL_SRC_FILES := helloworld.c
LOCAL_HEADER_LIBRARIES := libhardware_headers
LOCAL_MODULE := helloworld.default
LOCAL_CFLAGS:= -DLOG_TAG=\"helloworld\"
LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)
  • 此时的 Z:\itop-3399_8.1\hardware\libhardware\modules\helloworld 目录结构

在这里插入图片描述

编译自己写的helloworld hal

  • 在编译这个模块前先将系统源码编译通过,为编译系统源码会生成好多工具,这些工具可以用来单独模块编译
  • 配置执行文件

source build//envsetup.sh

  • 选择在什么环境编译

lunch

在这里插入图片描述

  • 编译自己编写的模块

mmm hardware/libhardware/modules/helloworld/

  • 编译成功后会生成一个.so 文件
    在这里插入图片描述
  • 我这里生成的是helloworld.default.so 文件
  • helloworld.default.so 该文件在 Z:\itop-3399_8.1\out\target\product\rk3399_mid\vendor\lib64\hw 目录
  • 文件在vendor\lib64 目录 说明 该.so 文件最后会打包在vendor.img 镜像中
  • 打包vendor.img 镜像

make vendorimage
将vendor.img 刷入设备中,查看设备中的helloworld.default.so(需要root)

//进入设备
adb shell   
//获取root权限
su

如图

  • 在设备中查看我们的.so

ls vendor/lib64/hw

如图
在这里插入图片描述

系统生成的.so 库

  • 系统生成的.so库可能会出现在 system.img 和 vendor.img 中
  • 看编译后生成的.so 在那个目录
  1. 如果在 XX/XX/vendor/lib64,lib/ 中那就是上面的编译模式
  2. 如果在 XX/XX/syetem/lib64,lib/ 中那就安装下面的方式打包镜像
  • 打包system.img 镜像

make snod

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
好的,下面我将为你提供一个完整的示例代码,以实现HAL接口,打印Hello World,并通过JNI回调给Framework,最后给APP调用使用。 1. 实现HAL接口 首先,我们需要实现一个简单的HAL接口,用于打印字符串。具体而言,我们可以在HAL接口中定义一个printString函数,用于打印字符串。 代码如下: ``` // HAL接口,用于打印字符串 void printString(const char* str) { printf("%s\n", str); } ``` 2. 生成动态链接库 接下来,我们需要将HAL接口封装成一个动态链接库,并在JNI中调用。具体而言,我们可以使用Android NDK来编译生成这个动态链接库。 代码如下: ``` // Android.mk文件,用于编译生成动态链接库 LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := hal LOCAL_SRC_FILES := hal.c include $(BUILD_SHARED_LIBRARY) ``` 3. 实现JNI接口 接下来,我们需要在JNI实现一个Java方法,用于调用HAL接口。具体而言,我们可以使用JNI提供的函数,将Java方法映射到C/C++函数上。然后,在C/C++函数中,我们可以通过调用HAL接口的函数,来实现打印字符串的功能。 代码如下: ``` // JNI接口,用于调用HAL接口 JNIEXPORT void JNICALL Java_com_example_hal_HalInterface_printString(JNIEnv* env, jobject thiz, jstring str) { const char* cstr = (*env)->GetStringUTFChars(env, str, NULL); printString(cstr); (*env)->ReleaseStringUTFChars(env, str, cstr); } ``` 4. 生成JNI动态链接库 接下来,我们需要将JNI方法封装成一个动态链接库,并在Android应用中加载这个动态链接库。 代码如下: ``` // Android.mk文件,用于编译生成JNI动态链接库 LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := jni LOCAL_SRC_FILES := jni.c include $(BUILD_SHARED_LIBRARY) ``` 5. 在Android应用中调用JNI方法 最后,我们可以在Android应用中调用JNI方法,从而实现HAL接口的调用。具体而言,我们需要在Java代码中使用System.loadLibrary()方法,来加载JNI动态链接库。然后,我们可以通过JNI方法调用HAL接口,来实现打印字符串的功能。 代码如下: ``` // MainActivity.java文件,用于调用JNI方法 public class MainActivity extends AppCompatActivity { static { System.loadLibrary("jni"); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); HalInterface.printString("Hello World!"); } } ``` 完整的示例代码如下: hal.c ``` #include <stdio.h> #include "com_example_hal_HalInterface.h" // HAL接口,用于打印字符串 void printString(const char* str) { printf("%s\n", str); } JNIEXPORT void JNICALL Java_com_example_hal_HalInterface_printString(JNIEnv* env, jobject thiz, jstring str) { const char* cstr = (*env)->GetStringUTFChars(env, str, NULL); printString(cstr); (*env)->ReleaseStringUTFChars(env, str, cstr); } ``` com_example_hal_HalInterface.h ``` /* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_example_hal_HalInterface */ #ifndef _Included_com_example_hal_HalInterface #define _Included_com_example_hal_HalInterface #ifdef __cplusplus extern "C" { #endif /* * Class: com_example_hal_HalInterface * Method: printString * Signature: (Ljava/lang/String;)V */ JNIEXPORT void JNICALL Java_com_example_hal_HalInterface_printString (JNIEnv *, jobject, jstring); #ifdef __cplusplus } #endif #endif ``` com_example_hal_HalInterface.java ``` package com.example.hal; public class HalInterface { static { System.loadLibrary("jni"); } public static native void printString(String str); } ``` jni.c ``` #include <jni.h> JNIEXPORT void JNICALL Java_com_example_hal_HalInterface_printString(JNIEnv* env, jobject thiz, jstring str); JNIEXPORT void JNICALL Java_com_example_hal_HalInterface_printString(JNIEnv* env, jobject thiz, jstring str) { const char* cstr = (*env)->GetStringUTFChars(env, str, NULL); printString(cstr); (*env)->ReleaseStringUTFChars(env, str, cstr); } ``` Android.mk ``` LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := hal LOCAL_SRC_FILES := hal.c include $(BUILD_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := jni LOCAL_SRC_FILES := jni.c include $(BUILD_SHARED_LIBRARY) ``` 最后,你可以将这些文件放到一个Android Studio工程中,并且在Android设备上运行,即可看到控制台输出了Hello World!
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值