跳转至

Android HAL层开发实战:从零构建硬件抽象层

学习目标

完成本教程后,你将能够:

  • 理解Android HAL层的设计目的和架构
  • 掌握HAL接口规范和标准结构
  • 学会实现自定义HAL模块
  • 掌握JNI接口的编写和调用
  • 了解HAL模块的加载和初始化流程
  • 掌握HAL层的调试方法和工具
  • 能够对接Linux驱动和HAL层
  • 完成一个完整的HAL模块开发项目

前置要求

在开始学习之前,建议你具备:

知识要求: - 熟悉C/C++编程语言 - 了解Android系统架构 - 掌握Linux驱动开发基础 - 理解进程间通信机制 - 了解JNI基本概念

技能要求: - 能够编写和调试C/C++程序 - 会使用Linux命令行工具 - 熟悉Android开发环境 - 了解Makefile或Android.bp构建系统 - 能够阅读和理解系统日志

开发环境: - Ubuntu 18.04或更高版本 - AOSP源码(可选,用于参考) - Android NDK - 交叉编译工具链 - ADB调试工具

什么是Android HAL层?

HAL层的定义

**Hardware Abstraction Layer(硬件抽象层)**是Android系统中位于Linux内核驱动和Android Framework之间的一层软件接口。它为上层提供统一的硬件访问接口,隔离了底层硬件的具体实现细节。

HAL层在系统中的位置

┌─────────────────────────────────────────────────┐
│    Android Framework (Java/Kotlin)              │
│    ActivityManager, WindowManager, etc.         │
└─────────────────────────────────────────────────┘
                        ↕ JNI
┌─────────────────────────────────────────────────┐
│    Framework Native (C/C++)                      │
│    libhardware, libcamera_client, etc.          │
└─────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────┐
│    HAL Interface Layer (C/C++)                   │
│    hardware/libhardware/include/hardware/       │
│    camera.h, sensors.h, lights.h, etc.          │
└─────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────┐
│    HAL Implementation (Vendor Specific)          │
│    vendor/manufacturer/hardware/                 │
│    camera.default.so, sensors.default.so         │
└─────────────────────────────────────────────────┘
                        ↕ ioctl/read/write
┌─────────────────────────────────────────────────┐
│    Linux Kernel Drivers                          │
│    /dev/camera0, /dev/input/event0, etc.        │
└─────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────┐
│    Hardware (Camera, Sensors, Display, etc.)    │
└─────────────────────────────────────────────────┘

为什么需要HAL层?

1. 许可证隔离

问题: - Linux内核使用GPL许可证 - GPL要求衍生代码也必须开源 - 硬件厂商的驱动包含专有技术 - 不希望公开核心算法和实现

解决方案: - 将专有代码放在HAL层 - HAL层使用Apache 2.0许可证 - 不强制要求开源 - 保护厂商知识产权

2. 硬件抽象和统一接口

问题: - 不同厂商的硬件实现不同 - 相同功能的硬件接口各异 - Framework层难以适配所有硬件 - 代码维护成本高

解决方案: - HAL定义统一的接口规范 - 厂商实现各自的HAL模块 - Framework只需调用标准接口 - 硬件更换不影响上层代码

3. 模块化和可维护性

优势: - 硬件功能模块化 - 独立开发和测试 - 便于版本管理 - 降低系统复杂度

4. 安全性和稳定性

优势: - HAL运行在用户空间 - 不会导致内核崩溃 - 便于调试和问题定位 - 提高系统稳定性

HAL层的核心特点

1. 标准化接口 - 定义统一的数据结构 - 规范的函数命名 - 清晰的调用流程 - 完善的错误处理

2. 动态加载 - 运行时加载HAL模块 - 支持多个实现版本 - 按需加载,节省资源 - 便于升级和替换

3. 厂商定制 - 厂商实现具体功能 - 可以优化性能 - 添加特殊功能 - 保护专有技术

4. 版本管理 - 支持接口版本号 - 向后兼容 - 平滑升级 - 降低维护成本

HAL接口规范详解

标准HAL接口结构

Android HAL定义了一套标准的接口结构,所有HAL模块都必须遵循这个规范。

核心数据结构

1. hw_module_t - 硬件模块结构

/**
 * 每个硬件模块必须有一个名为HAL_MODULE_INFO_SYM的数据结构
 * 这个结构的字段用于标识模块的实现
 */
typedef struct hw_module_t {
    /** 标签必须初始化为HARDWARE_MODULE_TAG */
    uint32_t tag;

    /**
     * 模块API版本
     * 主版本号:major version
     * 次版本号:minor version
     */
    uint16_t module_api_version;
#define version_major module_api_version

    /**
     * HAL API版本
     */
    uint16_t hal_api_version;
#define version_minor hal_api_version

    /** 模块标识符 */
    const char *id;

    /** 模块名称 */
    const char *name;

    /** 模块作者/所有者/实现者 */
    const char *author;

    /** 模块方法 */
    struct hw_module_methods_t* methods;

    /** 模块的DSO句柄 */
    void* dso;

#ifdef __LP64__
    uint64_t reserved[32-7];
#else
    /** 填充到128字节,保留供将来使用 */
    uint32_t reserved[32-7];
#endif

} hw_module_t;

字段说明: - tag: 必须设置为HARDWARE_MODULE_TAG,用于验证模块有效性 - module_api_version: 模块API版本号 - hal_api_version: HAL API版本号 - id: 模块唯一标识符,如"camera"、"sensors" - name: 模块的可读名称 - author: 模块作者信息 - methods: 指向模块方法表的指针 - dso: 动态库句柄,由系统填充 - reserved: 保留字段,用于未来扩展

2. hw_module_methods_t - 模块方法表

/**
 * 每个模块必须实现的方法
 */
typedef struct hw_module_methods_t {
    /** 打开此模块的特定设备 */
    int (*open)(const struct hw_module_t* module, const char* id,
            struct hw_device_t** device);

} hw_module_methods_t;

方法说明: - open: 打开设备的方法,返回设备句柄 - 参数module: 指向模块结构的指针 - 参数id: 设备标识符 - 参数device: 输出参数,返回设备句柄

3. hw_device_t - 硬件设备结构

/**
 * 每个设备数据结构必须以hw_device_t开头
 * 后面跟着模块特定的公共方法和属性
 */
typedef struct hw_device_t {
    /** 标签必须初始化为HARDWARE_DEVICE_TAG */
    uint32_t tag;

    /**
     * 设备API版本
     */
    uint32_t version;

    /** 对此设备所属模块的引用 */
    struct hw_module_t* module;

#ifdef __LP64__
    uint64_t reserved[12];
#else
    /** 填充到64字节,保留供将来使用 */
    uint32_t reserved[12];
#endif

    /** 关闭此设备 */
    int (*close)(struct hw_device_t* device);

} hw_device_t;

字段说明: - tag: 必须设置为HARDWARE_DEVICE_TAG - version: 设备API版本号 - module: 指向所属模块的指针 - reserved: 保留字段 - close: 关闭设备的方法

HAL模块加载流程

1. 加载流程图

Framework层调用
hw_get_module(id, &module)
查找HAL模块库文件
dlopen()加载动态库
dlsym()获取HAL_MODULE_INFO_SYM符号
验证模块有效性
返回模块指针
调用module->methods->open()
返回设备句柄
使用设备接口
调用device->close()

2. 模块查找路径

HAL模块库文件的查找顺序:

// 查找路径(按优先级)
1. /odm/lib64/hw/
2. /vendor/lib64/hw/
3. /system/lib64/hw/

// 文件命名规则
<module_id>.<variant>.so
<module_id>.default.so

// 示例
camera.msm8996.so      // 特定平台
camera.default.so      // 默认实现
sensors.qcom.so        // 厂商特定
lights.default.so      // 默认实现

variant变量来源: - ro.hardware: 硬件平台名称 - ro.product.board: 产品板型 - ro.board.platform: 芯片平台 - ro.arch: 架构类型

3. 加载函数实现

/**
 * 加载HAL模块
 * @param id 模块ID,如"camera"、"sensors"
 * @param module 输出参数,返回模块指针
 * @return 0表示成功,负数表示错误
 */
int hw_get_module(const char *id, const struct hw_module_t **module)
{
    return hw_get_module_by_class(id, NULL, module);
}

/**
 * 按类加载HAL模块
 * @param class_id 模块类ID
 * @param inst 实例名称
 * @param module 输出参数
 */
int hw_get_module_by_class(const char *class_id, const char *inst,
                           const struct hw_module_t **module)
{
    int i = 0;
    char prop[PATH_MAX] = {0};
    char path[PATH_MAX] = {0};
    char name[PATH_MAX] = {0};
    char prop_name[PATH_MAX] = {0};

    // 构造模块名称
    if (inst)
        snprintf(name, PATH_MAX, "%s.%s", class_id, inst);
    else
        strlcpy(name, class_id, PATH_MAX);

    // 尝试不同的variant
    const char *variant_keys[] = {
        "ro.hardware",
        "ro.product.board",
        "ro.board.platform",
        "ro.arch"
    };

    // 遍历查找路径
    for (i=0; i<HAL_VARIANT_KEYS_COUNT; i++) {
        if (property_get(variant_keys[i], prop, NULL) == 0) {
            continue;
        }
        snprintf(path, sizeof(path), "%s/%s.%s.so",
                 HAL_LIBRARY_PATH, name, prop);
        if (access(path, R_OK) == 0) break;
    }

    // 尝试默认实现
    if (i >= HAL_VARIANT_KEYS_COUNT) {
        snprintf(path, sizeof(path), "%s/%s.default.so",
                 HAL_LIBRARY_PATH, name);
    }

    // 加载动态库
    void *handle = dlopen(path, RTLD_NOW);
    if (handle == NULL) {
        return -ENOENT;
    }

    // 获取HAL_MODULE_INFO_SYM符号
    const char *sym = HAL_MODULE_INFO_SYM_AS_STR;
    struct hw_module_t *hmi = (struct hw_module_t *)dlsym(handle, sym);
    if (hmi == NULL) {
        dlclose(handle);
        return -EINVAL;
    }

    // 验证模块标签
    if (hmi->tag != HARDWARE_MODULE_TAG) {
        dlclose(handle);
        return -EINVAL;
    }

    // 保存DSO句柄
    hmi->dso = handle;

    // 返回模块指针
    *module = hmi;

    return 0;
}

实战项目:开发LED HAL模块

现在我们通过一个完整的实例来学习HAL模块的开发。我们将实现一个LED灯控制的HAL模块。

项目需求

功能需求: 1. 打开/关闭LED灯 2. 设置LED亮度(0-255) 3. 设置LED闪烁模式 4. 获取LED状态

系统架构

Java应用
    ↓ JNI
Native Service
    ↓ HAL接口
LED HAL模块
    ↓ ioctl
LED驱动
LED硬件

步骤1:定义HAL接口

首先定义LED HAL的接口头文件。

文件:hardware/libhardware/include/hardware/led.h

#ifndef ANDROID_LED_INTERFACE_H
#define ANDROID_LED_INTERFACE_H

#include <stdint.h>
#include <sys/cdefs.h>
#include <sys/types.h>

#include <hardware/hardware.h>

__BEGIN_DECLS

/**
 * LED硬件模块ID
 */
#define LED_HARDWARE_MODULE_ID "led"

/**
 * LED设备ID
 */
#define LED_HARDWARE_LED0 "led0"

/**
 * LED闪烁模式
 */
enum led_flash_mode {
    LED_FLASH_MODE_NONE = 0,      // 不闪烁
    LED_FLASH_MODE_SLOW = 1,      // 慢闪(1Hz)
    LED_FLASH_MODE_FAST = 2,      // 快闪(5Hz)
    LED_FLASH_MODE_BREATH = 3,    // 呼吸灯
};

/**
 * LED状态结构
 */
struct led_state {
    uint8_t on;                   // 开关状态:0=关,1=开
    uint8_t brightness;           // 亮度:0-255
    enum led_flash_mode flash_mode; // 闪烁模式
};

/**
 * LED设备接口
 * 必须以hw_device_t开头
 */
struct led_device_t {
    struct hw_device_t common;

    /**
     * 设置LED状态
     * @param dev LED设备指针
     * @param state LED状态
     * @return 0表示成功,负数表示错误
     */
    int (*set_led)(struct led_device_t* dev, struct led_state *state);

    /**
     * 获取LED状态
     * @param dev LED设备指针
     * @param state 输出参数,返回LED状态
     * @return 0表示成功,负数表示错误
     */
    int (*get_led)(struct led_device_t* dev, struct led_state *state);

    /**
     * 设置LED亮度
     * @param dev LED设备指针
     * @param brightness 亮度值(0-255)
     * @return 0表示成功,负数表示错误
     */
    int (*set_brightness)(struct led_device_t* dev, uint8_t brightness);

    /**
     * 设置LED闪烁模式
     * @param dev LED设备指针
     * @param mode 闪烁模式
     * @return 0表示成功,负数表示错误
     */
    int (*set_flash_mode)(struct led_device_t* dev, enum led_flash_mode mode);
};

__END_DECLS

#endif  // ANDROID_LED_INTERFACE_H

步骤2:实现HAL模块

接下来实现LED HAL模块的具体功能。

文件:hardware/libhardware/modules/led/led.c

#define LOG_TAG "LED-HAL"

#include <errno.h>
#include <fcntl.h>
#include <malloc.h>
#include <pthread.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>

#include <log/log.h>
#include <hardware/hardware.h>
#include <hardware/led.h>

/**
 * LED设备节点路径
 */
#define LED_DEVICE_PATH "/dev/led0"

/**
 * LED驱动ioctl命令
 */
#define LED_IOC_MAGIC  'L'
#define LED_IOC_SET_STATE    _IOW(LED_IOC_MAGIC, 1, struct led_state)
#define LED_IOC_GET_STATE    _IOR(LED_IOC_MAGIC, 2, struct led_state)
#define LED_IOC_SET_BRIGHTNESS _IOW(LED_IOC_MAGIC, 3, uint8_t)
#define LED_IOC_SET_FLASH_MODE _IOW(LED_IOC_MAGIC, 4, uint32_t)

/**
 * LED设备上下文
 */
struct led_context_t {
    struct led_device_t device;
    int fd;                        // 设备文件描述符
    pthread_mutex_t lock;          // 互斥锁
    struct led_state current_state; // 当前状态
};

/**
 * 打开LED设备
 */
static int led_device_open(struct led_context_t *dev)
{
    if (dev->fd >= 0) {
        ALOGW("LED device already opened");
        return 0;
    }

    dev->fd = open(LED_DEVICE_PATH, O_RDWR);
    if (dev->fd < 0) {
        ALOGE("Failed to open LED device: %s", strerror(errno));
        return -errno;
    }

    ALOGI("LED device opened successfully");
    return 0;
}

/**
 * 关闭LED设备
 */
static int led_device_close_internal(struct led_context_t *dev)
{
    if (dev->fd >= 0) {
        close(dev->fd);
        dev->fd = -1;
    }
    return 0;
}

/**
 * 设置LED状态
 */
static int led_set_led(struct led_device_t* dev, struct led_state *state)
{
    struct led_context_t *ctx = (struct led_context_t *)dev;
    int ret;

    if (!state) {
        ALOGE("Invalid state pointer");
        return -EINVAL;
    }

    pthread_mutex_lock(&ctx->lock);

    // 确保设备已打开
    ret = led_device_open(ctx);
    if (ret < 0) {
        pthread_mutex_unlock(&ctx->lock);
        return ret;
    }

    // 调用驱动设置状态
    ret = ioctl(ctx->fd, LED_IOC_SET_STATE, state);
    if (ret < 0) {
        ALOGE("Failed to set LED state: %s", strerror(errno));
        pthread_mutex_unlock(&ctx->lock);
        return -errno;
    }

    // 更新当前状态
    memcpy(&ctx->current_state, state, sizeof(struct led_state));

    ALOGD("LED state set: on=%d, brightness=%d, flash_mode=%d",
          state->on, state->brightness, state->flash_mode);

    pthread_mutex_unlock(&ctx->lock);
    return 0;
}

/**
 * 获取LED状态
 */
static int led_get_led(struct led_device_t* dev, struct led_state *state)
{
    struct led_context_t *ctx = (struct led_context_t *)dev;
    int ret;

    if (!state) {
        ALOGE("Invalid state pointer");
        return -EINVAL;
    }

    pthread_mutex_lock(&ctx->lock);

    // 确保设备已打开
    ret = led_device_open(ctx);
    if (ret < 0) {
        pthread_mutex_unlock(&ctx->lock);
        return ret;
    }

    // 从驱动获取状态
    ret = ioctl(ctx->fd, LED_IOC_GET_STATE, state);
    if (ret < 0) {
        ALOGE("Failed to get LED state: %s", strerror(errno));
        pthread_mutex_unlock(&ctx->lock);
        return -errno;
    }

    ALOGD("LED state get: on=%d, brightness=%d, flash_mode=%d",
          state->on, state->brightness, state->flash_mode);

    pthread_mutex_unlock(&ctx->lock);
    return 0;
}

/**
 * 设置LED亮度
 */
static int led_set_brightness(struct led_device_t* dev, uint8_t brightness)
{
    struct led_context_t *ctx = (struct led_context_t *)dev;
    int ret;

    pthread_mutex_lock(&ctx->lock);

    // 确保设备已打开
    ret = led_device_open(ctx);
    if (ret < 0) {
        pthread_mutex_unlock(&ctx->lock);
        return ret;
    }

    // 调用驱动设置亮度
    ret = ioctl(ctx->fd, LED_IOC_SET_BRIGHTNESS, &brightness);
    if (ret < 0) {
        ALOGE("Failed to set LED brightness: %s", strerror(errno));
        pthread_mutex_unlock(&ctx->lock);
        return -errno;
    }

    // 更新当前状态
    ctx->current_state.brightness = brightness;

    ALOGD("LED brightness set to %d", brightness);

    pthread_mutex_unlock(&ctx->lock);
    return 0;
}

/**
 * 设置LED闪烁模式
 */
static int led_set_flash_mode(struct led_device_t* dev, enum led_flash_mode mode)
{
    struct led_context_t *ctx = (struct led_context_t *)dev;
    int ret;
    uint32_t mode_value = (uint32_t)mode;

    pthread_mutex_lock(&ctx->lock);

    // 确保设备已打开
    ret = led_device_open(ctx);
    if (ret < 0) {
        pthread_mutex_unlock(&ctx->lock);
        return ret;
    }

    // 调用驱动设置闪烁模式
    ret = ioctl(ctx->fd, LED_IOC_SET_FLASH_MODE, &mode_value);
    if (ret < 0) {
        ALOGE("Failed to set LED flash mode: %s", strerror(errno));
        pthread_mutex_unlock(&ctx->lock);
        return -errno;
    }

    // 更新当前状态
    ctx->current_state.flash_mode = mode;

    ALOGD("LED flash mode set to %d", mode);

    pthread_mutex_unlock(&ctx->lock);
    return 0;
}

/** * 关闭LED设备(HAL接口) */ static int led_device_close(struct hw_device_t *dev) { struct led_context_t *ctx = (struct led_context_t *)dev;

if (ctx) {
    led_device_close_internal(ctx);
    pthread_mutex_destroy(&ctx->lock);
    free(ctx);
}

ALOGI("LED device closed");
return 0;

}

/** * 打开LED设备(HAL接口) / static int led_device_open_hal(const struct hw_module_t module, const char* name, struct hw_device_t** device) { struct led_context_t *dev;

ALOGI("Opening LED device: %s", name);

// 检查设备名称
if (strcmp(name, LED_HARDWARE_LED0) != 0) {
    ALOGE("Unknown LED device: %s", name);
    return -EINVAL;
}

// 分配设备上下文
dev = (struct led_context_t *)calloc(1, sizeof(struct led_context_t));
if (!dev) {
    ALOGE("Failed to allocate LED device context");
    return -ENOMEM;
}

// 初始化设备结构
dev->device.common.tag = HARDWARE_DEVICE_TAG;
dev->device.common.version = 0;
dev->device.common.module = (struct hw_module_t *)module;
dev->device.common.close = led_device_close;

// 初始化设备方法
dev->device.set_led = led_set_led;
dev->device.get_led = led_get_led;
dev->device.set_brightness = led_set_brightness;
dev->device.set_flash_mode = led_set_flash_mode;

// 初始化设备上下文
dev->fd = -1;
pthread_mutex_init(&dev->lock, NULL);
memset(&dev->current_state, 0, sizeof(struct led_state));

// 返回设备指针
*device = (struct hw_device_t *)dev;

ALOGI("LED device opened successfully");
return 0;

}

/** * HAL模块方法表 */ static struct hw_module_methods_t led_module_methods = { .open = led_device_open_hal, };

/** * HAL模块信息 * 必须命名为HAL_MODULE_INFO_SYM */ struct hw_module_t HAL_MODULE_INFO_SYM = { .tag = HARDWARE_MODULE_TAG, .module_api_version = 1, .hal_api_version = 0, .id = LED_HARDWARE_MODULE_ID, .name = "LED HAL Module", .author = "Embedded Platform", .methods = &led_module_methods, };

**代码说明**:

1. **设备上下文**:`led_context_t`包含设备状态和文件描述符
2. **线程安全**:使用互斥锁保护并发访问
3. **错误处理**:完善的错误检查和日志记录
4. **资源管理**:正确的打开/关闭和内存管理
5. **标准接口**:严格遵循HAL接口规范



### 步骤3:编写构建文件

**文件:hardware/libhardware/modules/led/Android.bp**

```bp
// LED HAL模块
cc_library_shared {
    name: "led.default",
    relative_install_path: "hw",
    proprietary: true,

    srcs: ["led.c"],

    shared_libs: [
        "liblog",
        "libcutils",
        "libhardware",
    ],

    header_libs: [
        "libhardware_headers",
    ],

    cflags: [
        "-Wall",
        "-Werror",
        "-Wextra",
    ],
}

或使用Android.mk(旧版本)

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := led.default
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_PROPRIETARY_MODULE := true

LOCAL_SRC_FILES := led.c

LOCAL_SHARED_LIBRARIES := \
    liblog \
    libcutils \
    libhardware

LOCAL_C_INCLUDES := \
    hardware/libhardware/include

LOCAL_CFLAGS := -Wall -Werror -Wextra

include $(BUILD_SHARED_LIBRARY)

构建说明: - name: 模块名称,格式为<module_id>.default - relative_install_path: 安装到/vendor/lib/hw/ - proprietary: 标记为厂商专有模块 - shared_libs: 依赖的共享库 - cflags: 编译选项

步骤4:编写JNI接口

为了让Java层能够调用HAL,需要编写JNI接口。

文件:frameworks/base/services/core/jni/com_android_server_LedService.cpp

#define LOG_TAG "LedService-JNI"

#include <nativehelper/JNIHelp.h>
#include <android_runtime/AndroidRuntime.h>
#include <utils/Log.h>
#include <hardware/hardware.h>
#include <hardware/led.h>

namespace android {

// LED设备指针
static led_device_t* sLedDevice = NULL;

/**
 * 初始化LED HAL
 */
static jboolean nativeInit(JNIEnv* env, jobject /* clazz */)
{
    ALOGI("Initializing LED HAL");

    // 加载HAL模块
    const hw_module_t* module;
    int err = hw_get_module(LED_HARDWARE_MODULE_ID, &module);
    if (err != 0) {
        ALOGE("Failed to load LED HAL module: %d", err);
        return JNI_FALSE;
    }

    // 打开LED设备
    hw_device_t* device;
    err = module->methods->open(module, LED_HARDWARE_LED0, &device);
    if (err != 0) {
        ALOGE("Failed to open LED device: %d", err);
        return JNI_FALSE;
    }

    sLedDevice = (led_device_t*)device;
    ALOGI("LED HAL initialized successfully");
    return JNI_TRUE;
}

/**
 * 设置LED状态
 */
static jboolean nativeSetLed(JNIEnv* env, jobject /* clazz */,
                            jboolean on, jint brightness, jint flashMode)
{
    if (sLedDevice == NULL) {
        ALOGE("LED device not initialized");
        return JNI_FALSE;
    }

    struct led_state state;
    state.on = on ? 1 : 0;
    state.brightness = (uint8_t)brightness;
    state.flash_mode = (enum led_flash_mode)flashMode;

    int err = sLedDevice->set_led(sLedDevice, &state);
    if (err != 0) {
        ALOGE("Failed to set LED state: %d", err);
        return JNI_FALSE;
    }

    return JNI_TRUE;
}

/**
 * 获取LED状态
 */
static jobject nativeGetLed(JNIEnv* env, jobject /* clazz */)
{
    if (sLedDevice == NULL) {
        ALOGE("LED device not initialized");
        return NULL;
    }

    struct led_state state;
    int err = sLedDevice->get_led(sLedDevice, &state);
    if (err != 0) {
        ALOGE("Failed to get LED state: %d", err);
        return NULL;
    }

    // 创建Java对象返回状态
    jclass ledStateClass = env->FindClass("com/android/server/LedState");
    if (ledStateClass == NULL) {
        ALOGE("Failed to find LedState class");
        return NULL;
    }

    jmethodID constructor = env->GetMethodID(ledStateClass, "<init>", "(ZII)V");
    if (constructor == NULL) {
        ALOGE("Failed to find LedState constructor");
        return NULL;
    }

    jobject ledState = env->NewObject(ledStateClass, constructor,
                                     state.on ? JNI_TRUE : JNI_FALSE,
                                     (jint)state.brightness,
                                     (jint)state.flash_mode);

    return ledState;
}

/**
 * 设置LED亮度
 */
static jboolean nativeSetBrightness(JNIEnv* env, jobject /* clazz */, jint brightness)
{
    if (sLedDevice == NULL) {
        ALOGE("LED device not initialized");
        return JNI_FALSE;
    }

    int err = sLedDevice->set_brightness(sLedDevice, (uint8_t)brightness);
    if (err != 0) {
        ALOGE("Failed to set LED brightness: %d", err);
        return JNI_FALSE;
    }

    return JNI_TRUE;
}

/**
 * 设置LED闪烁模式
 */
static jboolean nativeSetFlashMode(JNIEnv* env, jobject /* clazz */, jint mode)
{
    if (sLedDevice == NULL) {
        ALOGE("LED device not initialized");
        return JNI_FALSE;
    }

    int err = sLedDevice->set_flash_mode(sLedDevice, (enum led_flash_mode)mode);
    if (err != 0) {
        ALOGE("Failed to set LED flash mode: %d", err);
        return JNI_FALSE;
    }

    return JNI_TRUE;
}

/**
 * 释放LED HAL
 */
static void nativeFinalize(JNIEnv* env, jobject /* clazz */)
{
    if (sLedDevice != NULL) {
        sLedDevice->common.close((hw_device_t*)sLedDevice);
        sLedDevice = NULL;
        ALOGI("LED HAL finalized");
    }
}

// JNI方法注册表
static const JNINativeMethod sMethods[] = {
    {"nativeInit", "()Z", (void*)nativeInit},
    {"nativeSetLed", "(ZII)Z", (void*)nativeSetLed},
    {"nativeGetLed", "()Lcom/android/server/LedState;", (void*)nativeGetLed},
    {"nativeSetBrightness", "(I)Z", (void*)nativeSetBrightness},
    {"nativeSetFlashMode", "(I)Z", (void*)nativeSetFlashMode},
    {"nativeFinalize", "()V", (void*)nativeFinalize},
};

// 注册JNI方法
int register_android_server_LedService(JNIEnv* env)
{
    return jniRegisterNativeMethods(env, "com/android/server/LedService",
                                   sMethods, NELEM(sMethods));
}

} // namespace android

JNI代码说明

  1. 模块加载:使用hw_get_module()加载HAL模块
  2. 设备打开:调用module->methods->open()打开设备
  3. 方法映射:将HAL方法映射为JNI方法
  4. 类型转换:Java类型和C类型之间的转换
  5. 错误处理:完善的错误检查和日志
  6. 资源管理:正确的初始化和清理

步骤5:编写Java服务

文件:frameworks/base/services/core/java/com/android/server/LedService.java

package com.android.server;

import android.content.Context;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Slog;

/**
 * LED系统服务
 */
public class LedService extends SystemService {
    private static final String TAG = "LedService";

    private final Context mContext;
    private final Handler mHandler;
    private final HandlerThread mHandlerThread;

    // Native方法声明
    private static native boolean nativeInit();
    private static native boolean nativeSetLed(boolean on, int brightness, int flashMode);
    private static native LedState nativeGetLed();
    private static native boolean nativeSetBrightness(int brightness);
    private static native boolean nativeSetFlashMode(int flashMode);
    private static native void nativeFinalize();

    public LedService(Context context) {
        super(context);
        mContext = context;

        // 创建工作线程
        mHandlerThread = new HandlerThread("LedService");
        mHandlerThread.start();
        mHandler = new Handler(mHandlerThread.getLooper());
    }

    @Override
    public void onStart() {
        Slog.i(TAG, "Starting LED Service");

        // 初始化HAL
        if (!nativeInit()) {
            Slog.e(TAG, "Failed to initialize LED HAL");
            return;
        }

        // 发布服务
        publishBinderService("led", new LedServiceImpl());
        Slog.i(TAG, "LED Service started");
    }

    @Override
    public void onBootPhase(int phase) {
        if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
            Slog.i(TAG, "LED Service ready");
        }
    }

    /**
     * LED服务实现
     */
    private final class LedServiceImpl extends ILedService.Stub {

        @Override
        public boolean setLed(boolean on, int brightness, int flashMode) {
            // 权限检查
            mContext.enforceCallingOrSelfPermission(
                android.Manifest.permission.HARDWARE_TEST,
                "setLed");

            // 参数验证
            if (brightness < 0 || brightness > 255) {
                Slog.e(TAG, "Invalid brightness: " + brightness);
                return false;
            }

            // 调用HAL
            return nativeSetLed(on, brightness, flashMode);
        }

        @Override
        public LedState getLed() {
            // 权限检查
            mContext.enforceCallingOrSelfPermission(
                android.Manifest.permission.HARDWARE_TEST,
                "getLed");

            return nativeGetLed();
        }

        @Override
        public boolean setBrightness(int brightness) {
            // 权限检查
            mContext.enforceCallingOrSelfPermission(
                android.Manifest.permission.HARDWARE_TEST,
                "setBrightness");

            // 参数验证
            if (brightness < 0 || brightness > 255) {
                Slog.e(TAG, "Invalid brightness: " + brightness);
                return false;
            }

            return nativeSetBrightness(brightness);
        }

        @Override
        public boolean setFlashMode(int mode) {
            // 权限检查
            mContext.enforceCallingOrSelfPermission(
                android.Manifest.permission.HARDWARE_TEST,
                "setFlashMode");

            return nativeSetFlashMode(mode);
        }
    }

    // 加载JNI库
    static {
        System.loadLibrary("ledservice_jni");
    }
}

/**
 * LED状态类
 */
class LedState {
    public boolean on;
    public int brightness;
    public int flashMode;

    public LedState(boolean on, int brightness, int flashMode) {
        this.on = on;
        this.brightness = brightness;
        this.flashMode = flashMode;
    }
}

Java服务说明

  1. 系统服务:继承SystemService
  2. 权限检查:使用enforceCallingOrSelfPermission()
  3. 参数验证:检查参数有效性
  4. 线程管理:使用HandlerThread处理异步操作
  5. Binder接口:通过ILedService.Stub提供服务

HAL调试方法

1. 日志调试

使用logcat查看日志

# 查看所有日志
adb logcat

# 过滤LED相关日志
adb logcat | grep LED

# 查看特定标签
adb logcat -s LED-HAL:V LedService:V

# 保存日志到文件
adb logcat -v time > led_log.txt

在代码中添加日志

// C/C++代码
#include <log/log.h>

ALOGV("Verbose log");    // 详细日志
ALOGD("Debug log");      // 调试日志
ALOGI("Info log");       // 信息日志
ALOGW("Warning log");    // 警告日志
ALOGE("Error log");      // 错误日志
// Java代码
import android.util.Slog;

Slog.v(TAG, "Verbose log");
Slog.d(TAG, "Debug log");
Slog.i(TAG, "Info log");
Slog.w(TAG, "Warning log");
Slog.e(TAG, "Error log");

2. 使用strace跟踪系统调用

# 跟踪进程的系统调用
adb shell strace -p <pid>

# 跟踪特定系统调用
adb shell strace -e open,ioctl -p <pid>

# 保存到文件
adb shell strace -o /data/local/tmp/trace.txt -p <pid>
adb pull /data/local/tmp/trace.txt

示例输出

open("/dev/led0", O_RDWR) = 3
ioctl(3, LED_IOC_SET_STATE, 0x7fff1234) = 0
ioctl(3, LED_IOC_GET_STATE, 0x7fff5678) = 0
close(3) = 0

3. 使用gdb调试

准备工作

# 推送gdbserver到设备
adb push gdbserver /data/local/tmp/

# 启动gdbserver附加到进程
adb shell /data/local/tmp/gdbserver :5039 --attach <pid>

# 端口转发
adb forward tcp:5039 tcp:5039

在主机上启动gdb

# 启动gdb
gdb

# 连接到gdbserver
(gdb) target remote :5039

# 加载符号
(gdb) symbol-file led.default.so

# 设置断点
(gdb) break led_set_led

# 继续执行
(gdb) continue

# 查看变量
(gdb) print state->brightness

# 单步执行
(gdb) step
(gdb) next

# 查看调用栈
(gdb) backtrace

4. 检查HAL模块加载

查看已加载的HAL模块

# 查看HAL库文件
adb shell ls -l /vendor/lib/hw/
adb shell ls -l /vendor/lib64/hw/

# 检查模块是否存在
adb shell ls -l /vendor/lib/hw/led.*.so

# 查看模块依赖
adb shell readelf -d /vendor/lib/hw/led.default.so

# 检查符号表
adb shell nm -D /vendor/lib/hw/led.default.so | grep HAL_MODULE_INFO_SYM

测试HAL模块加载

# 使用test程序测试
adb shell /system/bin/hwservicemanager &
adb shell /vendor/bin/hw/android.hardware.led@1.0-service

5. 性能分析

使用systrace

# 捕获系统跟踪
adb shell atrace --async_start -b 16384 -c -a com.example.ledtest hal

# 停止捕获
adb shell atrace --async_stop > trace.html

# 在浏览器中打开trace.html查看

使用simpleperf

# 性能采样
adb shell simpleperf record -p <pid> -o /data/local/tmp/perf.data

# 拉取数据
adb pull /data/local/tmp/perf.data

# 生成报告
simpleperf report -i perf.data

6. 内存泄漏检测

使用AddressSanitizer(ASan)

在Android.bp中添加:

cc_library_shared {
    name: "led.default",

    sanitize: {
        address: true,
        recover: ["address"],
    },

    // ... 其他配置
}

使用Valgrind

# 推送valgrind到设备
adb push valgrind /data/local/tmp/

# 运行valgrind
adb shell /data/local/tmp/valgrind --leak-check=full \
    --log-file=/data/local/tmp/valgrind.log \
    /system/bin/app_process

# 查看报告
adb pull /data/local/tmp/valgrind.log

常见HAL模块示例

1. Lights HAL(灯光)

接口定义

// hardware/libhardware/include/hardware/lights.h

struct light_device_t {
    struct hw_device_t common;

    /**
     * 设置灯光状态
     */
    int (*set_light)(struct light_device_t* dev,
                    struct light_state_t const* state);
};

struct light_state_t {
    unsigned int color;           // ARGB格式
    int flashMode;               // 闪烁模式
    int flashOnMS;               // 亮持续时间(毫秒)
    int flashOffMS;              // 灭持续时间(毫秒)
    int brightnessMode;          // 亮度模式
};

使用场景: - 通知LED - 背光控制 - 按键灯 - 电池指示灯

2. Sensors HAL(传感器)

接口定义

// hardware/libhardware/include/hardware/sensors.h

struct sensors_module_t {
    struct hw_module_t common;

    /**
     * 获取传感器列表
     */
    int (*get_sensors_list)(struct sensors_module_t* module,
                           struct sensor_t const** list);
};

struct sensors_poll_device_t {
    struct hw_device_t common;

    /**
     * 激活/停用传感器
     */
    int (*activate)(struct sensors_poll_device_t *dev,
                   int handle, int enabled);

    /**
     * 设置采样延迟
     */
    int (*setDelay)(struct sensors_poll_device_t *dev,
                   int handle, int64_t ns);

    /**
     * 轮询传感器数据
     */
    int (*poll)(struct sensors_poll_device_t *dev,
               sensors_event_t* data, int count);
};

传感器类型: - 加速度计 - 陀螺仪 - 磁力计 - 光线传感器 - 接近传感器 - 压力传感器 - 温度传感器

3. Camera HAL(摄像头)

接口定义

// hardware/libhardware/include/hardware/camera.h

typedef struct camera_module {
    hw_module_t common;

    /**
     * 获取摄像头数量
     */
    int (*get_number_of_cameras)(void);

    /**
     * 获取摄像头信息
     */
    int (*get_camera_info)(int camera_id, struct camera_info *info);

    /**
     * 打开摄像头设备
     */
    int (*open_legacy)(const struct hw_module_t* module,
                      const char* id, uint32_t halVersion,
                      struct hw_device_t** device);
} camera_module_t;

typedef struct camera_device {
    hw_device_t common;
    camera_device_ops_t *ops;
    void *priv;
} camera_device_t;

typedef struct camera_device_ops {
    int (*set_preview_window)(struct camera_device *,
                             struct preview_stream_ops *window);

    void (*set_callbacks)(struct camera_device *,
                         camera_notify_callback notify_cb,
                         camera_data_callback data_cb,
                         camera_data_timestamp_callback data_cb_timestamp,
                         camera_request_memory get_memory,
                         void *user);

    void (*enable_msg_type)(struct camera_device *, int32_t msg_type);
    void (*disable_msg_type)(struct camera_device *, int32_t msg_type);

    int (*start_preview)(struct camera_device *);
    void (*stop_preview)(struct camera_device *);

    int (*take_picture)(struct camera_device *);
    int (*start_recording)(struct camera_device *);
    void (*stop_recording)(struct camera_device *);
} camera_device_ops_t;

主要功能: - 预览 - 拍照 - 录像 - 对焦 - 曝光控制 - 白平衡

4. Audio HAL(音频)

接口定义

// hardware/libhardware/include/hardware/audio.h

struct audio_hw_device {
    struct hw_device_t common;

    /**
     * 获取支持的设备
     */
    uint32_t (*get_supported_devices)(const struct audio_hw_device *dev);

    /**
     * 打开输出流
     */
    int (*open_output_stream)(struct audio_hw_device *dev,
                             audio_io_handle_t handle,
                             audio_devices_t devices,
                             audio_output_flags_t flags,
                             struct audio_config *config,
                             struct audio_stream_out **stream_out,
                             const char *address);

    /**
     * 关闭输出流
     */
    void (*close_output_stream)(struct audio_hw_device *dev,
                               struct audio_stream_out* stream_out);

    /**
     * 打开输入流
     */
    int (*open_input_stream)(struct audio_hw_device *dev,
                            audio_io_handle_t handle,
                            audio_devices_t devices,
                            struct audio_config *config,
                            struct audio_stream_in **stream_in,
                            audio_input_flags_t flags,
                            const char *address,
                            audio_source_t source);

    /**
     * 关闭输入流
     */
    void (*close_input_stream)(struct audio_hw_device *dev,
                              struct audio_stream_in *stream_in);
};

音频流操作

struct audio_stream_out {
    struct audio_stream common;

    /**
     * 写入音频数据
     */
    ssize_t (*write)(struct audio_stream_out *stream,
                    const void* buffer, size_t bytes);

    /**
     * 获取延迟
     */
    uint32_t (*get_latency)(const struct audio_stream_out *stream);

    /**
     * 设置音量
     */
    int (*set_volume)(struct audio_stream_out *stream,
                     float left, float right);
};

struct audio_stream_in {
    struct audio_stream common;

    /**
     * 读取音频数据
     */
    ssize_t (*read)(struct audio_stream_in *stream,
                   void* buffer, size_t bytes);

    /**
     * 获取输入帧丢失数
     */
    uint32_t (*get_input_frames_lost)(struct audio_stream_in *stream);
};

HAL开发最佳实践

1. 接口设计原则

保持接口简单: - 只暴露必要的功能 - 避免过度设计 - 接口清晰明确 - 易于理解和使用

版本兼容性

// 使用版本号管理接口变化
#define LED_MODULE_API_VERSION_1_0  HARDWARE_MODULE_API_VERSION(1, 0)
#define LED_MODULE_API_VERSION_1_1  HARDWARE_MODULE_API_VERSION(1, 1)

// 在代码中检查版本
if (module->module_api_version >= LED_MODULE_API_VERSION_1_1) {
    // 使用新功能
} else {
    // 使用旧功能
}

错误处理

// 统一的错误码
#define LED_ERROR_NONE           0
#define LED_ERROR_INVALID_PARAM  -EINVAL
#define LED_ERROR_NO_DEVICE      -ENODEV
#define LED_ERROR_IO             -EIO
#define LED_ERROR_BUSY           -EBUSY

// 详细的错误日志
if (ret < 0) {
    ALOGE("Failed to set LED state: %s (error=%d)",
          strerror(-ret), ret);
    return ret;
}

2. 线程安全

使用互斥锁保护共享资源

struct led_context_t {
    struct led_device_t device;
    pthread_mutex_t lock;
    // ... 其他字段
};

// 初始化
pthread_mutex_init(&ctx->lock, NULL);

// 使用
pthread_mutex_lock(&ctx->lock);
// 访问共享资源
pthread_mutex_unlock(&ctx->lock);

// 清理
pthread_mutex_destroy(&ctx->lock);

避免死锁: - 按固定顺序获取多个锁 - 使用超时机制 - 避免在持有锁时调用外部函数 - 使用递归锁处理重入

3. 资源管理

正确的初始化和清理

static int led_device_open(const struct hw_module_t* module,
                          const char* name,
                          struct hw_device_t** device)
{
    struct led_context_t *ctx = NULL;
    int ret = 0;

    // 分配内存
    ctx = (struct led_context_t *)calloc(1, sizeof(*ctx));
    if (!ctx) {
        ret = -ENOMEM;
        goto error;
    }

    // 初始化互斥锁
    ret = pthread_mutex_init(&ctx->lock, NULL);
    if (ret != 0) {
        goto error_free;
    }

    // 打开设备文件
    ctx->fd = open(LED_DEVICE_PATH, O_RDWR);
    if (ctx->fd < 0) {
        ret = -errno;
        goto error_mutex;
    }

    // 初始化设备结构
    ctx->device.common.tag = HARDWARE_DEVICE_TAG;
    ctx->device.common.version = 0;
    ctx->device.common.module = (struct hw_module_t *)module;
    ctx->device.common.close = led_device_close;

    *device = (struct hw_device_t *)ctx;
    return 0;

error_mutex:
    pthread_mutex_destroy(&ctx->lock);
error_free:
    free(ctx);
error:
    *device = NULL;
    return ret;
}

static int led_device_close(struct hw_device_t *dev)
{
    struct led_context_t *ctx = (struct led_context_t *)dev;

    if (ctx) {
        if (ctx->fd >= 0) {
            close(ctx->fd);
        }
        pthread_mutex_destroy(&ctx->lock);
        free(ctx);
    }

    return 0;
}

4. 性能优化

减少系统调用

// 不好的做法:每次都打开/关闭设备
int led_set_brightness_bad(struct led_device_t* dev, uint8_t brightness)
{
    int fd = open(LED_DEVICE_PATH, O_RDWR);
    if (fd < 0) return -errno;

    int ret = ioctl(fd, LED_IOC_SET_BRIGHTNESS, &brightness);
    close(fd);

    return ret;
}

// 好的做法:保持设备打开
int led_set_brightness_good(struct led_device_t* dev, uint8_t brightness)
{
    struct led_context_t *ctx = (struct led_context_t *)dev;

    // 设备已经在open时打开,直接使用
    return ioctl(ctx->fd, LED_IOC_SET_BRIGHTNESS, &brightness);
}

批量操作

// 批量设置多个参数
struct led_batch_config {
    uint8_t brightness;
    enum led_flash_mode flash_mode;
    uint32_t flash_on_ms;
    uint32_t flash_off_ms;
};

int led_set_batch(struct led_device_t* dev, struct led_batch_config *config)
{
    struct led_context_t *ctx = (struct led_context_t *)dev;

    // 一次ioctl设置所有参数
    return ioctl(ctx->fd, LED_IOC_SET_BATCH, config);
}

缓存状态

struct led_context_t {
    struct led_device_t device;
    struct led_state cached_state;  // 缓存的状态
    bool state_valid;               // 状态是否有效
};

int led_get_led(struct led_device_t* dev, struct led_state *state)
{
    struct led_context_t *ctx = (struct led_context_t *)dev;

    pthread_mutex_lock(&ctx->lock);

    // 如果缓存有效,直接返回
    if (ctx->state_valid) {
        memcpy(state, &ctx->cached_state, sizeof(*state));
        pthread_mutex_unlock(&ctx->lock);
        return 0;
    }

    // 否则从驱动读取
    int ret = ioctl(ctx->fd, LED_IOC_GET_STATE, state);
    if (ret == 0) {
        memcpy(&ctx->cached_state, state, sizeof(*state));
        ctx->state_valid = true;
    }

    pthread_mutex_unlock(&ctx->lock);
    return ret;
}

5. 日志和调试

分级日志

// 开发阶段:详细日志
#ifdef DEBUG
#define LED_LOGV(fmt, ...) ALOGV(fmt, ##__VA_ARGS__)
#define LED_LOGD(fmt, ...) ALOGD(fmt, ##__VA_ARGS__)
#else
#define LED_LOGV(fmt, ...) do {} while(0)
#define LED_LOGD(fmt, ...) do {} while(0)
#endif

// 生产环境:只保留重要日志
#define LED_LOGI(fmt, ...) ALOGI(fmt, ##__VA_ARGS__)
#define LED_LOGW(fmt, ...) ALOGW(fmt, ##__VA_ARGS__)
#define LED_LOGE(fmt, ...) ALOGE(fmt, ##__VA_ARGS__)

性能跟踪

#include <cutils/trace.h>

int led_set_led(struct led_device_t* dev, struct led_state *state)
{
    ATRACE_CALL();  // 自动跟踪函数执行时间

    // ... 实现代码

    return 0;
}

// 或手动标记
ATRACE_BEGIN("led_set_brightness");
// ... 代码
ATRACE_END();

6. 安全性考虑

权限检查

// 检查调用者权限
static int check_permission(void)
{
    uid_t uid = getuid();

    // 只允许system用户或root用户
    if (uid != AID_SYSTEM && uid != AID_ROOT) {
        ALOGE("Permission denied: uid=%d", uid);
        return -EPERM;
    }

    return 0;
}

int led_set_led(struct led_device_t* dev, struct led_state *state)
{
    int ret = check_permission();
    if (ret < 0) {
        return ret;
    }

    // ... 实现代码
}

输入验证

int led_set_brightness(struct led_device_t* dev, uint8_t brightness)
{
    // 验证参数范围
    if (brightness > 255) {
        ALOGE("Invalid brightness: %d", brightness);
        return -EINVAL;
    }

    // 验证设备指针
    if (!dev) {
        ALOGE("Invalid device pointer");
        return -EINVAL;
    }

    // ... 实现代码
}

防止缓冲区溢出

// 使用安全的字符串函数
char name[32];
strncpy(name, input, sizeof(name) - 1);
name[sizeof(name) - 1] = '\0';

// 或使用strlcpy(如果可用)
strlcpy(name, input, sizeof(name));

总结

通过本教程,你应该已经掌握了:

  • ✅ Android HAL层的设计目的和架构
  • ✅ HAL接口规范和标准结构
  • ✅ HAL模块的加载和初始化流程
  • ✅ 完整的HAL模块开发流程
  • ✅ JNI接口的编写和调用
  • ✅ HAL层的调试方法和工具
  • ✅ 常见HAL模块的接口设计
  • ✅ HAL开发的最佳实践

关键要点

  1. HAL层的作用
  2. 隔离硬件差异
  3. 解决许可证问题
  4. 提供统一接口
  5. 模块化设计

  6. 标准接口结构

  7. hw_module_t:模块信息
  8. hw_module_methods_t:模块方法
  9. hw_device_t:设备基类
  10. 自定义设备结构

  11. 开发流程

  12. 定义HAL接口
  13. 实现HAL模块
  14. 编写构建文件
  15. 实现JNI接口
  16. 编写Java服务

  17. 调试技巧

  18. logcat日志
  19. strace系统调用跟踪
  20. gdb调试
  21. 性能分析工具

  22. 最佳实践

  23. 接口设计简单清晰
  24. 线程安全
  25. 资源管理
  26. 性能优化
  27. 安全性考虑

实践练习

练习1:实现Vibrator HAL

任务:实现一个振动器HAL模块

要求: 1. 定义振动器HAL接口 2. 实现振动控制功能 3. 支持振动时长设置 4. 支持振动模式(单次、重复) 5. 编写JNI接口

提示: - 设备节点:/dev/vibrator - ioctl命令:设置振动时长、启动/停止 - 参考Lights HAL的实现

练习2:扩展LED HAL

任务:为LED HAL添加RGB颜色控制

要求: 1. 扩展led_state结构,添加RGB字段 2. 实现set_color()方法 3. 支持颜色渐变效果 4. 添加预设颜色模式 5. 更新JNI接口

提示: - RGB格式:0xRRGGBB - 渐变需要定时器支持 - 考虑线程安全

练习3:实现Battery HAL

任务:实现电池状态监控HAL

要求: 1. 定义电池HAL接口 2. 读取电池电量 3. 读取充电状态 4. 读取电池温度 5. 实现状态变化通知

提示: - 使用sysfs接口:/sys/class/power_supply/battery/ - 需要轮询或使用uevent监听 - 考虑使用回调机制

下一步学习

建议按以下顺序继续学习:

1. Android驱动开发

2. Android系统定制

3. 深入学习

  • Android Framework源码分析
  • Binder通信机制详解
  • Android性能优化
  • Android安全机制

参考资料

官方文档

  1. Android HAL文档
  2. https://source.android.com/devices/architecture/hal
  3. HAL接口规范和开发指南

  4. AOSP源码

  5. https://android.googlesource.com/
  6. hardware/libhardware/
  7. hardware/interfaces/

  8. Android NDK文档

  9. https://developer.android.com/ndk
  10. JNI开发指南

推荐书籍

  1. 《深入理解Android内核设计思想》
  2. 作者:林学森
  3. HAL层详细讲解

  4. 《Android系统源代码情景分析》

  5. 作者:罗升阳
  6. HAL和驱动分析

  7. 《Embedded Android》

  8. 作者:Karim Yaghmour
  9. HAL开发实战

在线资源

  1. Android源码在线浏览
  2. https://cs.android.com/
  3. 方便查看和搜索源码

  4. XDA Developers

  5. https://www.xda-developers.com/
  6. Android开发社区

  7. Stack Overflow

  8. Android HAL标签
  9. 问题解答

开发工具

必备工具: - Android Studio - Android NDK - ADB(Android Debug Bridge) - Repo(AOSP代码管理)

调试工具: - logcat(日志查看) - strace(系统调用跟踪) - gdb(调试器) - systrace(性能分析)

构建工具: - Soong(Android构建系统) - Make - Ninja

常见问题解答

Q1: HAL层和驱动层有什么区别?

A:

驱动层(Kernel Driver): - 运行在内核空间 - 直接操作硬件寄存器 - 使用GPL许可证 - C语言编写 - 性能最高但不稳定会导致内核崩溃

HAL层(Hardware Abstraction Layer): - 运行在用户空间 - 通过驱动访问硬件 - 使用Apache许可证 - C/C++编写 - 性能略低但更安全稳定

关系

Framework → HAL → Driver → Hardware

Q2: 为什么HAL模块要使用动态加载?

A:

优势: 1. 灵活性:可以在运行时选择不同的实现 2. 可替换性:无需重新编译系统即可更换HAL 3. 节省资源:按需加载,不用的模块不占用内存 4. 版本管理:支持多个版本共存 5. 厂商定制:不同厂商可以提供不同实现

实现方式: - 使用dlopen()加载动态库 - 通过dlsym()获取符号 - 运行时查找和加载

Q3: HAL接口如何保证向后兼容?

A:

版本管理

// 使用版本号
struct hw_module_t {
    uint16_t module_api_version;
    uint16_t hal_api_version;
    // ...
};

// 检查版本
if (module->module_api_version >= HARDWARE_MODULE_API_VERSION(1, 1)) {
    // 使用新功能
} else {
    // 使用旧功能或提供默认实现
}

接口扩展: - 新增方法放在结构体末尾 - 使用reserved字段扩展 - 保持旧接口不变 - 提供默认实现

Q4: 如何调试HAL模块加载失败?

A:

检查步骤

  1. 确认文件存在

    adb shell ls -l /vendor/lib/hw/led.*.so
    

  2. 检查文件权限

    adb shell ls -l /vendor/lib/hw/led.default.so
    # 应该是可读可执行
    

  3. 查看日志

    adb logcat | grep -i "hal\|hardware"
    

  4. 检查符号

    adb shell nm -D /vendor/lib/hw/led.default.so | grep HAL_MODULE_INFO_SYM
    

  5. 检查依赖

    adb shell readelf -d /vendor/lib/hw/led.default.so
    

  6. 手动测试加载

    void* handle = dlopen("/vendor/lib/hw/led.default.so", RTLD_NOW);
    if (!handle) {
        ALOGE("dlopen failed: %s", dlerror());
    }
    

Q5: HAL层如何处理多线程并发?

A:

使用互斥锁

struct led_context_t {
    pthread_mutex_t lock;
    // ...
};

int led_set_led(struct led_device_t* dev, struct led_state *state)
{
    struct led_context_t *ctx = (struct led_context_t *)dev;

    pthread_mutex_lock(&ctx->lock);
    // 访问共享资源
    pthread_mutex_unlock(&ctx->lock);

    return 0;
}

注意事项: - 保护所有共享资源 - 避免死锁 - 锁的粒度要合适 - 考虑使用读写锁

Q6: HAL层如何实现异步通知?

A:

使用回调机制

// 定义回调类型
typedef void (*led_event_callback_t)(int event, void* user_data);

struct led_device_t {
    struct hw_device_t common;

    /**
     * 注册事件回调
     */
    int (*register_callback)(struct led_device_t* dev,
                            led_event_callback_t callback,
                            void* user_data);
};

// 实现
struct led_context_t {
    led_event_callback_t callback;
    void* callback_data;
    pthread_t event_thread;
};

// 事件线程
static void* event_thread_func(void* arg)
{
    struct led_context_t *ctx = (struct led_context_t *)arg;

    while (ctx->running) {
        // 等待事件
        int event = wait_for_event(ctx);

        // 调用回调
        if (ctx->callback) {
            ctx->callback(event, ctx->callback_data);
        }
    }

    return NULL;
}

Q7: 如何优化HAL层性能?

A:

优化策略

  1. 减少系统调用
  2. 保持设备文件打开
  3. 批量操作
  4. 使用mmap代替read/write

  5. 缓存数据

  6. 缓存频繁读取的数据
  7. 使用脏标记
  8. 延迟写入

  9. 异步处理

  10. 使用工作队列
  11. 后台线程处理
  12. 避免阻塞调用

  13. 内存优化

  14. 对象池
  15. 预分配内存
  16. 避免频繁分配/释放

  17. 使用性能分析工具

  18. systrace
  19. simpleperf
  20. 自定义性能计数器

反馈与支持

如果你在学习过程中遇到问题: - 💬 在评论区留言讨论 - 📧 发送邮件到:support@embedded-platform.com - 🐛 报告问题:GitHub Issues

贡献内容: 欢迎提交改进建议和补充内容!


版权声明:本文采用 CC BY-SA 4.0 许可协议。

最后更新:2024-01-15
文档版本:1.0