5. Android10增加硬件抽象层(HAL)模块访问内核驱动程序

本文是在上文4. 编写Android内置C可执行程序访问Linux内核驱动程序的基础上进行的,虚拟机环境就是上文结束时的环境。

代码

在aosp10/hardware/libhardware/include/hardware/目录下新建hello.h文件

#ifndef ANDROID_INCLUDE_HARDWARE_HELLO_H
#define ANDROID_INCLUDE_HARDWARE_HELLO_H
 
#include <stdbool.h>
#include <stdint.h>
#include <sys/cdefs.h>
#include <sys/types.h>
 
#include <hardware/hardware.h>
#include <hardware/hw_auth_token.h>
 
#define HELLO_HARDWARE_MODULE_ID "hello"
#define VAL_LENGTH 100
 
struct hello_module_t {
    struct hw_module_t common;
 
};
 
struct hello_device_t {
    struct hw_device_t common;  
    int fd;  
    int (*write_string)(struct hello_device_t* dev, const char *str);
    int (*read_string)(struct hello_device_t* dev, char* str);
};
 
 
#endif  // ANDROID_INCLUDE_HARDWARE_HELLO_H

 在aosp10/hardware/libhardware/modules/目录下新建hello文件夹,并在hello文件夹里新建hello.c和Android.mk两个文件

hello.c

/*
 * Copyright (C) 2012 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.
 */
 
#define LOG_TAG "Legacy HelloHAL"
 
#include <malloc.h>
#include <stdint.h>
#include <string.h>
#include <log/log.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <cutils/atomic.h>
#include <stdlib.h>
#include <unistd.h>
#include <hardware/hardware.h>
#include <hardware/hello.h>
 
#define DEVICE_NAME "/dev/hello" 
#define MODULE_NAME "Default Hello HAL" 
#define MODULE_AUTHOR "The Android Open Source Project"
 
static int hello_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device);
static int hello_device_close(struct hw_device_t* device);
 
static int hello_write_string(struct hello_device_t* dev, const char * str);
static int hello_read_string(struct hello_device_t* dev, char* str);
 
static struct hw_module_methods_t hello_module_methods = {
    .open = hello_device_open,
};
 
struct hello_module_t HAL_MODULE_INFO_SYM = {
    .common = {
        .tag = HARDWARE_MODULE_TAG,
        .module_api_version = 1,
        .hal_api_version = 1,
        .id = HELLO_HARDWARE_MODULE_ID,
        .name = MODULE_NAME,
        .author = MODULE_AUTHOR,
        .methods = &hello_module_methods,
    },
};
 
static int hello_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device) {
 
	struct hello_device_t *dev = malloc(sizeof(struct hello_device_t));
    memset(dev, 0, sizeof(struct hello_device_t));
	
	ALOGE("Hello: hello_device_open name = %s",name);
    dev->common.tag = HARDWARE_DEVICE_TAG;
    dev->common.version = 0;
    dev->common.module = (hw_module_t*)module;
    dev->common.close = hello_device_close;
    dev->write_string = hello_write_string;
    dev->read_string = hello_read_string;
 
    if((dev->fd = open(DEVICE_NAME, O_RDWR)) == -1) {
		ALOGE("Hello: open /dev/hello fail-- %s.", strerror(errno));free(dev);
        return -EFAULT;
    }
    *device = &(dev->common);
	ALOGE("Hello: open /dev/hello successfully.");
    return 0;
}
static int hello_device_close(struct hw_device_t* device) {
    struct hello_device_t* hello_device = (struct hello_device_t*)device;
 
    if(hello_device) {
        close(hello_device->fd);
        free(hello_device);
    }
    return 0;
}
 
static int hello_write_string(struct hello_device_t* dev,const char * str) {
	ALOGE("Hello:write string: %s", str);
    write(dev->fd, str, strlen(str)+1);
    return 0;
}
 
static int hello_read_string(struct hello_device_t* dev, char* str) {
	ALOGE("Hello:read hello_read_string");
    read(dev->fd,str, VAL_LENGTH-1);    // Ensure that the memory space of str is greater than 100!!!
    return 0;
}

 Android.mk

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_SHARED_LIBRARIES := liblog
LOCAL_SRC_FILES := hello.c
LOCAL_MODULE := hello.default
include $(BUILD_SHARED_LIBRARY)

权限设置

由于设备文件是在内核驱动里面通过device_create创建的,而device_create创建的设备文件默认只有root用户可读写,而hello_device_open一般是由上层APP来调用的,这些APP一般不具有root权限,这时候就导致打开设备文件失败。解决办法是类似于Linux的udev规则,打开Android源代码工程目录下,进入到system/core/rootdir目录,里面有一个名为ueventd.rc文件,往里面添加一行:

/dev/hello 0666 root root

 

 第二步配置selinux,需要修改的文件一共有10个,可以分为5组,每组有三个文件file_contexts、system_server.te、device.te

aosp10/system/sepolicy/private/file_contexts
aosp10/system/sepolicy/private/system_server.te
aosp10/system/sepolicy/public/device.te

aosp10/system/sepolicy/prebuilts/api/26.0/private/file_contexts
aosp10/system/sepolicy/prebuilts/api/26.0/private/system_server.te
aosp10/system/sepolicy/prebuilts/api/26.0/public/device.te

aosp10/system/sepolicy/prebuilts/api/27.0/private/file_contexts
aosp10/system/sepolicy/prebuilts/api/27.0/private/system_server.te
aosp10/system/sepolicy/prebuilts/api/27.0/public/device.te

aosp10/system/sepolicy/prebuilts/api/28.0/private/file_contexts
aosp10/system/sepolicy/prebuilts/api/28.0/private/system_server.te
aosp10/system/sepolicy/prebuilts/api/28.0/public/device.te

aosp10/system/sepolicy/prebuilts/api/29.0/private/file_contexts
aosp10/system/sepolicy/prebuilts/api/29.0/private/system_server.te
aosp10/system/sepolicy/prebuilts/api/29.0/public/device.te

 在每一个file_contexts文件中都增加一行

/dev/hello		u:object_r:hello_device:s0

 在每一个system_server.te文件中都增加一行

allow system_server hello_device:chr_file rw_file_perms;

 在每一个device.te文件中都增加一行

type hello_device, dev_type, mlstrustedobject;

编译

cd ~/Documents/aosp10
export TARGET_PREBUILT_KERNEL=/home/test/Documents/msm/arch/arm64/boot/Image.lz4-dtb
source build/envsetup.sh
lunch
aosp_walleye-userdebug
mmm ./hardware/libhardware/modules/hello

 可以看到生成的hello.default.so 

本文涉及到的知识主要和Android架构中的linux内核层、硬件抽象层相关

参考

Android应用程序访问linux驱动第二步:实现并测试hardware层_阳光玻璃杯-CSDN博客

在Ubuntu上为Android增加硬件抽象层(HAL)模块访问Linux内核驱动程序_老罗的Android之旅-CSDN博客

AndroidQ 从app到驱动 第二章 添加HAL层,先打通JNI层到驱动的访问 | 码农家园

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值