大佬# Android HAL 编程实战:从零实现专属 HAL 模块与底层探索
1. HAL 基础概念与架构解析
1.1 Android HAL 的作用与定位 "夏哉ke": itazs点fun/4706/
Android HAL(Hardware Abstraction Layer)是连接Android框架与Linux内核驱动的重要桥梁,它定义了标准的接口规范,让OEM厂商能够在不修改上层框架的情况下实现硬件功能。
1.2 HAL 的主要类型
- Binderized HAL (Android 8.0+): 基于Binder IPC
- Passthrough HAL: 旧版兼容模式
- Legacy HAL: 传统HAL(已废弃)
2. 开发环境搭建
2.1 环境要求
# 安装必要工具
sudo apt-get install git-core gnupg flex bison build-essential \
zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 \
libncurses5 lib32ncurses5-dev x11proto-core-dev libx11-dev \
lib32z1-dev libgl1-mesa-dev libxml2-utils xsltproc unzip fontconfig
2.2 AOSP 源码下载
mkdir ~/aosp
cd ~/aosp
repo init -u https://android.googlesource.com/platform/manifest -b android-13.0.0_r3
repo sync -j8
3. 实战:实现自定义 LED HAL 模块
3.1 定义 HAL 接口
hardware/interfaces/led/1.0/ILed.hal
package android.hardware.led@1.0;
interface ILed {
/**
* 打开LED
*/
setOn() generates (bool success);
/**
* 关闭LED
*/
setOff() generates (bool success);
/**
* 设置LED亮度
* @param brightness 亮度值 0-255
*/
setBrightness(uint8_t brightness) generates (bool success);
/**
* 获取LED状态
*/
getState() generates (LedState state);
};
enum LedColor : uint32_t {
RED = 0,
GREEN = 1,
BLUE = 2
};
struct LedState {
bool isOn;
uint8_t brightness;
LedColor color;
};
3.2 实现 HAL Service
hardware/interfaces/led/1.0/default/Led.cpp
#define LOG_TAG "LedHAL"
#include <log/log.h>
#include <hardware/hardware.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>
#include "Led.h"
namespace android {
namespace hardware {
namespace led {
namespace V1_0 {
namespace implementation {
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
// 设备节点路径
constexpr char LED_DEVICE_NODE[] = "/sys/class/leds/user_led/brightness";
constexpr char LED_MAX_BRIGHTNESS_NODE[] = "/sys/class/leds/user_led/max_brightness";
Led::Led() {
ALOGI("Led HAL initialized");
// 初始化设备节点
mMaxBrightness = readMaxBrightness();
}
Return<bool> Led::setOn() {
ALOGD("Turning LED on");
return writeBrightness(mMaxBrightness);
}
Return<bool> Led::setOff() {
ALOGD("Turning LED off");
return writeBrightness(0);
}
Return<bool> Led::setBrightness(uint8_t brightness) {
if (brightness > 100) {
ALOGW("Brightness value %d out of range, clamping to 100", brightness);
brightness = 100;
}
// 将百分比转换为实际亮度值
uint32_t actualBrightness = (brightness * mMaxBrightness) / 100;
ALOGD("Setting LED brightness to %d%% (actual: %d)", brightness, actualBrightness);
return writeBrightness(actualBrightness);
}
Return<LedState> Led::getState() {
LedState state = {};
state.isOn = readCurrentBrightness() > 0;
state.brightness = static_cast<uint8_t>((readCurrentBrightness() * 100) / mMaxBrightness);
state.color = LedColor::RED; // 假设为红色LED
return state;
}
// 私有辅助方法
bool Led::writeBrightness(uint32_t brightness) {
std::ofstream file(LED_DEVICE_NODE);
if (!file.is_open()) {
ALOGE("Failed to open LED device node");
return false;
}
file << brightness;
file.close();
return true;
}
uint32_t Led::readCurrentBrightness() {
std::ifstream file(LED_DEVICE_NODE);
if (!file.is_open()) {
ALOGE("Failed to open LED device node for reading");
return 0;
}
uint32_t brightness;
file >> brightness;
file.close();
return brightness;
}
uint32_t Led::readMaxBrightness() {
std::ifstream file(LED_MAX_BRIGHTNESS_NODE);
if (!file.is_open()) {
ALOGW("Failed to read max brightness, using default 255");
return 255;
}
uint32_t maxBrightness;
file >> maxBrightness;
file.close();
return maxBrightness;
}
ILed* HIDL_FETCH_ILed(const char* /* name */) {
return new Led();
}
} // namespace implementation
} // namespace V1_0
} // namespace led
} // namespace hardware
} // namespace android
3.3 实现 HAL 入口点
hardware/interfaces/led/1.0/default/service.cpp
#define LOG_TAG "android.hardware.led@1.0-service"
#include <android-base/logging.h>
#include <hidl/HidlTransportSupport.h>
#include "Led.h"
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
using android::hardware::led::V1_0::ILed;
using android::hardware::led::V1_0::implementation::Led;
int main() {
android::sp<ILed> ledService = new Led();
configureRpcThreadpool(1, true);
if (ledService->registerAsService() != android::OK) {
LOG(ERROR) << "Failed to register LED HAL service";
return 1;
}
LOG(INFO) << "LED HAL service started successfully";
joinRpcThreadpool();
return 0;
}
4. 内核驱动开发
4.1 LED 设备驱动
kernel/drivers/leds/leds-user.c
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/leds.h>
#include <linux/slab.h>
#include <linux/of.h>
struct user_led {
struct led_classdev cdev;
uint32_t brightness;
};
static struct user_led *user_led;
static void user_led_set(struct led_classdev *led_cdev,
enum led_brightness brightness)
{
struct user_led *led = container_of(led_cdev, struct user_led, cdev);
led->brightness = brightness;
pr_info("User LED brightness set to %u\n", brightness);
}
static enum led_brightness user_led_get(struct led_classdev *led_cdev)
{
struct user_led *led = container_of(led_cdev, struct user_led, cdev);
return led->brightness;
}
static int __init user_led_init(void)
{
int ret;
user_led = kzalloc(sizeof(*user_led), GFP_KERNEL);
if (!user_led)
return -ENOMEM;
user_led->cdev.name = "user_led";
user_led->cdev.brightness_set = user_led_set;
user_led->cdev.brightness_get = user_led_get;
user_led->cdev.max_brightness = 255;
user_led->cdev.brightness = 0;
ret = led_classdev_register(NULL, &user_led->cdev);
if (ret < 0) {
kfree(user_led);
return ret;
}
pr_info("User LED driver initialized\n");
return 0;
}
static void __exit user_led_exit(void)
{
led_classdev_unregister(&user_led->cdev);
kfree(user_led);
pr_info("User LED driver removed\n");
}
module_init(user_led_init);
module_exit(user_led_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("User LED Driver");
5. 构建配置
5.1 HAL 模块 Android.bp
hardware/interfaces/led/1.0/default/Android.bp
cc_library_shared {
name: "android.hardware.led@1.0-impl",
relative_install_path: "hw",
proprietary: true,
srcs: ["Led.cpp"],
shared_libs: [
"liblog",
"libhidlbase",
"libhidltransport",
"libutils",
"android.hardware.led@1.0",
],
}
cc_binary {
name: "android.hardware.led@1.0-service",
defaults: ["hidl_defaults"],
relative_install_path: "hw",
proprietary: true,
init_rc: ["android.hardware.led@1.0-service.rc"],
srcs: ["service.cpp"],
shared_libs: [
"liblog",
"libcutils",
"libdl",
"libbase",
"libutils",
"libhardware",
"libhidlbase",
"libhidltransport",
"android.hardware.led@1.0",
],
}
5.2 Service 启动配置
hardware/interfaces/led/1.0/default/android.hardware.led@1.0-service.rc
service vendor.led-hal-1-0 /vendor/bin/hw/android.hardware.led@1.0-service
class hal
user system
group system
capabilities SYS_RAWIO
seclabel u:r:hal_led_default:s0
6. 系统集成与测试
6.1 设备树配置
kernel/arch/arm64/boot/dts/vendor/led-device.dts
/ {
leds {
compatible = "gpio-leds";
user_led: user-led {
label = "user_led";
gpios = <&gpio1 12 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "none";
default-state = "off";
};
};
};
6.2 SELinux 策略
device/vendor/common/sepolicy/hal_led_default.te
type hal_led_default, domain;
type hal_led_default_exec, exec_type, file_type;
init_daemon_domain(hal_led_default)
allow hal_led_default sysfs_leds:file { open read write getattr };
allow hal_led_default kernel:system { sysfs_leds };
6.3 测试应用开发
packages/apps/LedTest/app/src/main/java/com/example/ledtest/MainActivity.java
public class MainActivity extends AppCompatActivity {
private ILed mLedService;
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mLedService = ILed.Stub.asInterface(service);
Log.i("LedTest", "LED service connected");
}
@Override
public void onServiceDisconnected(ComponentName name) {
mLedService = null;
Log.i("LedTest", "LED service disconnected");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bindLedService();
setupButtons();
}
private void bindLedService() {
Intent intent = new Intent();
intent.setClassName("android.hardware.led",
"android.hardware.led.ILed/default");
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
private void setupButtons() {
findViewById(R.id.btn_on).setOnClickListener(v -> turnOnLed());
findViewById(R.id.btn_off).setOnClickListener(v -> turnOffLed());
findViewById(R.id.btn_brightness).setOnClickListener(v -> setBrightness());
}
private void turnOnLed() {
if (mLedService != null) {
try {
boolean success = mLedService.setOn();
Toast.makeText(this, "LED turned on: " + success,
Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
Log.e("LedTest", "Error turning on LED", e);
}
}
}
private void setBrightness() {
if (mLedService != null) {
try {
SeekBar seekBar = findViewById(R.id.seekbar_brightness);
int brightness = seekBar.getProgress();
boolean success = mLedService.setBrightness((byte) brightness);
Toast.makeText(this, "Brightness set to " + brightness +
"%: " + success, Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
Log.e("LedTest", "Error setting brightness", e);
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(mConnection);
}
}
7. 调试与优化
7.1 常用调试命令
# 检查HAL服务是否运行
adb shell ps -A | grep led
# 查看HAL服务注册状态
adb shell lshal | grep led
# 手动启动HAL服务
adb shell start vendor.led-hal-1-0
# 查看内核日志
adb shell dmesg | grep led
# 测试设备节点
adb shell "echo 128 > /sys/class/leds/user_led/brightness"
7.2 性能优化建议
- 异步操作: 耗时操作使用异步回调
- 资源管理: 及时释放文件描述符
- 错误处理: 完善的错误码和异常处理
- 日志优化: 合理使用日志级别
8. 进阶主题
8.1 实现 AIDL HAL (Android 11+)
// frameworks/hardware/interfaces/led/aidl/android/hardware/led/ILed.aidl
package android.hardware.led;
interface ILed {
boolean setOn();
boolean setOff();
boolean setBrightness(in byte brightness);
LedState getState();
}
parcelable LedState;
8.2 添加 HAL 测试用例
#include <gtest/gtest.h>
#include <hidl/GtestPrinter.h>
#include <hidl/ServiceManagement.h>
using android::hardware::led::V1_0::ILed;
using android::hardware::led::V1_0::LedState;
class LedHidlTest : public ::testing::TestWithParam<std::string> {
public:
virtual void SetUp() override {
led = ILed::getService(GetParam());
ASSERT_NE(led, nullptr);
}
sp<ILed> led;
};
TEST_P(LedHidlTest, TestOnOff) {
bool result = led->setOn();
EXPECT_TRUE(result);
LedState state = led->getState();
EXPECT_TRUE(state.isOn);
result = led->setOff();
EXPECT_TRUE(result);
state = led->getState();
EXPECT_FALSE(state.isOn);
}
通过这个完整的实战指南,你可以深入理解Android HAL的开发流程,从接口定义到内核驱动,再到系统集成和测试验证,全面掌握HAL模块的开发技能。