LED 控制全栈实现(内核驱动 → HAL → JNI → Framework → App)
以下是完整的 LED 控制功能实现,涵盖从底层硬件驱动到上层应用的全链路代码:
一、内核驱动层(LED 字符设备驱动,控制硬件)
// drivers/led/led_driver.c
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
#include <linux/gpio.h>
#include <linux/delay.h>
#define DEVICE_NAME "led_control"
#define LED_GPIO 123 // 实际硬件中LED连接的GPIO编号
#define LED_MAJOR 240 // 主设备号
static dev_t led_dev_num;
static struct cdev led_cdev;
static int led_state = 0; // 0:关闭, 1:打开
static int led_open(struct inode *inode, struct file *file) {
if (gpio_request(LED_GPIO, "led_gpio") < 0) {
printk(KERN_ERR "Failed to request GPIO %d\n", LED_GPIO);
return -EBUSY;
}
gpio_direction_output(LED_GPIO, 0);
printk(KERN_INFO "LED driver opened\n");
return 0;
}
static ssize_t led_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos) {
char cmd;
if (copy_from_user(&cmd, buf, 1)) {
return -EFAULT;
}
if (cmd == '1') {
gpio_set_value(LED_GPIO, 1);
led_state = 1;
printk(KERN_INFO "LED turned on\n");
} else if (cmd == '0') {
gpio_set_value(LED_GPIO, 0);
led_state = 0;
printk(KERN_INFO "LED turned off\n");
}
return count;
}
static ssize_t led_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos) {
char state = '0' + led_state;
if (copy_to_user(buf, &state, 1)) {
return -EFAULT;
}
return 1;
}
static int led_release(struct inode *inode, struct file *file) {
gpio_free(LED_GPIO);
printk(KERN_INFO "LED driver closed\n");
return 0;
}
static const struct file_operations led_fops = {
.owner = THIS_MODULE,
.open = led_open,
.write = led_write,
.read = led_read,
.release = led_release,
};
static int __init led_init(void) {
int ret;
led_dev_num = MKDEV(LED_MAJOR, 0);
ret = register_chrdev_region(led_dev_num, 1, DEVICE_NAME);
if (ret < 0) {
printk(KERN_ERR "Failed to register device number\n");
return ret;
}
cdev_init(&led_cdev, &led_fops);
led_cdev.owner = THIS_MODULE;
ret = cdev_add(&led_cdev, led_dev_num, 1);
if (ret < 0) {
printk(KERN_ERR "Failed to add cdev\n");
unregister_chrdev_region(led_dev_num, 1);
return ret;
}
printk(KERN_INFO "LED driver initialized\n");
return 0;
}
static void __exit led_exit(void) {
cdev_del(&led_cdev);
unregister_chrdev_region(led_dev_num, 1);
printk(KERN_INFO "LED driver exited\n");
}
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("Simple LED Driver");
二、HAL 层(硬件抽象层,只是做接口封装,便于更换硬件实现,不影响fwk调用)
// hardware/libhardware/modules/led/led_hal.h
#ifndef LED_HAL_H
#define LED_HAL_H
#include <hardware/hardware.h>
__BEGIN_DECLS
#define LED_HARDWARE_MODULE_ID "led"
struct led_module_t {
struct hw_module_t common;
};
struct led_device_t {
struct hw_device_t common;
int (*set_state)(struct led_device_t* dev, int state);
int (*get_state)(struct led_device_t* dev);
};
__END_DECLS
#endif // LED_HAL_H
// hardware/libhardware/modules/led/led_hal.c
#define LOG_TAG "LED_HAL"
#include <hardware/hardware.h>
#include <hardware/led_hal.h>
#include <fcntl.h>
#include <errno.h>
#include <cutils/log.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define DEVICE_PATH "/dev/led_control"
static int led_device_open(const struct hw_module_t* module,
const char* id,
struct hw_device_t** device);
static struct hw_module_methods_t led_module_methods = {
.open = led_device_open
};
struct led_module_t HAL_MODULE_INFO_SYM = {
.common = {
.tag = HARDWARE_MODULE_TAG,
.version_major = 1,
.version_minor = 0,
.id = LED_HARDWARE_MODULE_ID,
.name = "LED Hardware Module",
.author = "Your Name",
.methods = &led_module_methods,
}
};
static int led_set_state(struct led_device_t* dev, int state) {
if (!dev) {
ALOGE("Invalid device handle");
return -EINVAL;
}
int fd = (int)(uintptr_t)dev->common.private_data;
char cmd = (state) ? '1' : '0';
if (write(fd, &cmd, 1) != 1) {
ALOGE("Failed to write to LED device");
return -EIO;
}
return 0;
}
static int led_get_state(struct led_device_t* dev) {
if (!dev) {
ALOGE("Invalid device handle");
return -EINVAL;
}
int fd = (int)(uintptr_t)dev->common.private_data;
char state;
if (read(fd, &state, 1) != 1) {
ALOGE("Failed to read from LED device");
return -EIO;
}
return (state == '1') ? 1 : 0;
}
static int led_device_close(struct hw_device_t* device) {
if (device) {
struct led_device_t* led_dev = (struct led_device_t*)device;
int fd = (int)(uintptr_t)led_dev->common.private_data;
close(fd);
free(led_dev);
}
return 0;
}
static int led_device_open(const struct hw_module_t* module,
const char* id,
struct hw_device_t** device) {
if (strcmp(id, LED_HARDWARE_MODULE_ID) != 0) {
return -EINVAL;
}
struct led_device_t* dev = malloc(sizeof(struct led_device_t));
if (!dev) {
ALOGE("Failed to allocate memory for LED device");
return -ENOMEM;
}
memset(dev, 0, sizeof(struct led_device_t));
dev->common.tag = HARDWARE_DEVICE_TAG;
dev->common.version = 1;
dev->common.module = (struct hw_module_t*)module;
dev->common.close = led_device_close;
dev->set_state = led_set_state;
dev->get_state = led_get_state;
// 打开设备节点
int fd = open(DEVICE_PATH, O_RDWR);
if (fd < 0) {
ALOGE("Failed to open LED device: %s", strerror(errno));
free(dev);
return -EIO;
}
dev->common.private_data = (void*)(uintptr_t)fd;
*device = &dev->common;
ALOGI("LED device opened successfully");
return 0;
}
三、JNI 层(连接 HAL 与 Framework,由于java无法直接调用.c文件,只能用jni去调用hal的接口)
// frameworks/base/services/core/jni/com_android_server_LedService.cpp
#define LOG_TAG "LedServiceJNI"
#include "jni.h"
#include "android_runtime/AndroidRuntime.h"
#include <hardware/hardware.h>
#include <hardware/led_hal.h>
#include <utils/Log.h>
namespace android {
static struct led_device_t* led_device = NULL;
static jint ledOpen(JNIEnv* env, jobject clazz) {
int ret;
struct hw_module_t* module;
ret = hw_get_module(LED_HARDWARE_MODULE_ID, (const struct hw_module_t**)&module);
if (ret == 0) {
ret = led_device_open(module, LED_HARDWARE_MODULE_ID,
(struct hw_device_t**)&led_device);
if (ret != 0) {
ALOGE("Failed to open LED device: %d", ret);
return -1;
}
} else {
ALOGE("Failed to get LED module: %d", ret);
return -1;
}
ALOGI("LED JNI: opened successfully");
return 0;
}
static void ledSetState(JNIEnv* env, jobject clazz, jint state) {
if (!led_device) {
ALOGE("LED device not opened");
return;
}
led_device->set_state(led_device, state);
}
static jint ledGetState(JNIEnv* env, jobject clazz) {
if (!led_device) {
ALOGE("LED device not opened");
return -1;
}
return led_device->get_state(led_device);
}
static const JNINativeMethod method_table[] = {
{"nativeOpen", "()I", (void*)ledOpen},
{"nativeSetState", "(I)V", (void*)ledSetState},
{"nativeGetState", "()I", (void*)ledGetState},
};
int register_android_server_LedService(JNIEnv* env) {
return jniRegisterNativeMethods(env, "com/android/server/LedService",
method_table, NELEM(method_table));
}
} // namespace android
四、Framework 层(系统服务,通过jni调用hal的接口实现对硬件的控制)
// frameworks/base/services/core/java/com/android/server/LedService.java
package com.android.server;
import android.os.ILedService;
import android.util.Log;
public class LedService extends ILedService.Stub {
private static final String TAG = "LedService";
static {
System.loadLibrary("ledservice_jni");
}
private native int nativeOpen();
private native void nativeSetState(int state);
private native int nativeGetState();
public LedService() {
int ret = nativeOpen();
Log.i(TAG, "LedService initialized, ret=" + ret);
}
@Override
public void setLedState(boolean on) throws android.os.RemoteException {
nativeSetState(on ? 1 : 0);
}
@Override
public boolean getLedState() throws android.os.RemoteException {
return nativeGetState() == 1;
}
}
// frameworks/base/core/java/android/os/ILedService.aidl
package android.os;
interface ILedService {
void setLedState(boolean on);
boolean getLedState();
}
五、应用层(App 调用)
// app/src/main/java/com/example/ledcontrol/LedManager.java
package com.example.ledcontrol;
import android.content.Context;
import android.os.ILedService;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
public class LedManager {
private static final String TAG = "LedManager";
private static ILedService sService;
private static ILedService getService() {
if (sService == null) {
sService = ILedService.Stub.asInterface(
ServiceManager.getService("led"));
}
return sService;
}
public static void setLedState(boolean on) {
try {
ILedService service = getService();
if (service != null) {
service.setLedState(on);
} else {
Log.e(TAG, "Led service not available");
}
} catch (RemoteException e) {
Log.e(TAG, "Remote exception: " + e.getMessage());
}
}
public static boolean getLedState() {
try {
ILedService service = getService();
if (service != null) {
return service.getLedState();
}
} catch (RemoteException e) {
Log.e(TAG, "Remote exception: " + e.getMessage());
}
return false;
}
}
// app/src/main/java/com/example/ledcontrol/MainActivity.java
package com.example.ledcontrol;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private TextView mStateTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mStateTextView = findViewById(R.id.state_text);
Button onButton = findViewById(R.id.on_button);
Button offButton = findViewById(R.id.off_button);
onButton.setOnClickListener(v -> {
LedManager.setLedState(true);
updateState();
});
offButton.setOnClickListener(v -> {
LedManager.setLedState(false);
updateState();
});
updateState();
}
private void updateState() {
boolean state = LedManager.getLedState();
mStateTextView.setText("LED State: " + (state ? "ON" : "OFF"));
}
}
整体流程说明
- 驱动层:实现对LED硬件的直接控制,通过
/dev/led_control
设备节点提供接口 - HAL层:封装驱动接口,提供标准硬件抽象,使Framework无需关心具体硬件实现
- JNI层:连接HAL的C接口与Framework的Java接口,实现跨语言调用
- Framework层:提供系统服务和API,管理LED设备并对外提供访问接口
- 应用层:通过Framework API间接控制LED,无需了解底层实现细节
这种分层架构是Android系统的典型设计,每层只与相邻层交互,降低了耦合性,便于维护和扩展。