本文是在上文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博客