探索Android FrameWork底层开发视频全套

38 阅读5分钟

大佬# 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 性能优化建议

  1. 异步操作: 耗时操作使用异步回调
  2. 资源管理: 及时释放文件描述符
  3. 错误处理: 完善的错误码和异常处理
  4. 日志优化: 合理使用日志级别

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模块的开发技能。