安卓4.4添加LED灯接口应用层到驱动层详解

简介: 笔记

最近项目中需要添加LED灯接口,该LED灯当作手电筒使用。

我们从驱动层到应用层的顺序逐步添加接口,具体为什么要在某一文件中添加请参考我的另外两篇文章

Android4.4 LightsService使用笔记

Android4.4移植-LED灯驱动适配


1 添加LED灯驱动


1.1 添加驱动文件

在vendor或者kernel目录下添加驱动文件,本项目中存放路径为kernel/drivers/leds/flashlight.c

具体内容后续补充


1.2 配置该驱动文件参加编译

...后续补充


2. HAL层接口适配


对于不同厂商的LED驱动,安卓进行了统一接口操作,本项目中文件目录为vendor/***/open-source/libs/liblights/lights.c,安卓默认路径hardware/qcom/display/***/liblight/lights.c

本项目中lights.c具体修改内容如下:


//1 定义枚举类型
//all lights
enum {
    RED_LED,
    GREEN_LED,
    FLASHLIGHT,  //添加FLASHLIGHT灯的枚举
    BLUE_LED,
    LCD_BACKLIGHT,
    BUTTONS_LED,
    NUM_LEDS,
};
//2 定义节点路径
//light nodes
struct led leds[NUM_LEDS] = {
    [RED_LED] = {
        .brightness = { "/sys/class/leds/red/brightness", 0}, //正常亮度
        .delay_on = { "/sys/class/leds/red/delay_on", 0},   //LED闪烁熄灭时长
        .delay_off = { "/sys/class/leds/red/delay_off", 0}, //LED闪烁点亮时长
        .triggers = { "/sys/class/leds/red/triggers", 0},     //LED闪烁时的亮度
    },
    [GREEN_LED] = {
        .brightness = { "/sys/class/leds/green/brightness", 0},
        .delay_on = { "/sys/class/leds/green/delay_on", 0},
        .delay_off = { "/sys/class/leds/green/delay_off", 0},
        .triggers = { "/sys/class/leds/green/triggers", 0},
    },
    //该路径与驱动中生成节点的路径需要一致
    [FLASHLIGHT] = {
        .brightness = { "/sys/class/leds/flashlight/brightness", 0},
    },
    [BLUE_LED] = {
    },
    [LCD_BACKLIGHT] = {
        .brightness = { "/sys/class/backlight/sprd_backlight/brightness", -1},
    },
    [BUTTONS_LED] = {
        .brightness = {"/sys/class/leds/keyboard-backlight/brightness", -1},
    },
};
//3 添加操作函数
static int set_light_flashlight(struct light_device_t *dev,
                                    struct light_state_t const *state)
{
        ALOGE("file:%s, func:%s, light!\n", __FILE__, __func__);
        int on = is_lit(state);
        ALOGD("file:%s, func:%s, on=%d\n", __FILE__, __func__, on);
        if(NULL==leds[FLASHLIGHT].brightness.filename) {
            ALOGE("file:%s, func:%s, unsupported light!\n", __FILE__, __func__);
            return -EINVAL;
        }
        pthread_mutex_lock(&g_lock);
        int err = write_int(&leds[FLASHLIGHT].brightness, on?(on&0xff):0);
        pthread_mutex_unlock(&g_lock);
        return err;
}
//5 函数指针赋值
static int open_lights(const struct hw_module_t *module, char const *name,
                       struct hw_device_t **device)
{
        int (*set_light)(struct light_device_t *dev,
                         struct light_state_t const *state);
        ALOGV("file:%s, func:%s name=%s\n", __FILE__, __func__, name);
        if (0 == strcmp(LIGHT_ID_BACKLIGHT, name))
                set_light = set_light_backlight;
        else if (0 == strcmp(LIGHT_ID_KEYBOARD, name))
                set_light = set_light_keyboard;
        else if (0 == strcmp(LIGHT_ID_BUTTONS, name))
                set_light = set_light_buttons;
        else if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name))
                set_light = set_light_leds_notifications;
        else if (0 == strcmp(LIGHT_ID_ATTENTION, name))
                set_light = set_light_leds_attention;
        else if (0 == strcmp(LIGHT_ID_BATTERY,name))
                set_light = set_light_leds_notifications;
        //add flashlight,set_light函数入口指向前面定义的set_light_flashlight函数
        else if (0 == strcmp(LIGHT_ID_FLASHLIGHT,name))
                set_light = set_light_flashlight;
        else
                return -EINVAL;
        ...
}

3 定义FLASHLIGHT模块


文件路径hardware/libhardware/include/hardware/lights.h


#define LIGHT_ID_BACKLIGHT          "backlight"
#define LIGHT_ID_KEYBOARD           "keyboard"
#define LIGHT_ID_BUTTONS            "buttons"
#define LIGHT_ID_BATTERY            "battery"
#define LIGHT_ID_NOTIFICATIONS      "notifications"
#define LIGHT_ID_ATTENTION          "attention"
//add flashlight--bianjb
#define LIGHT_ID_FLASHLIGHT         "flashlight"

4 添加JNI接口


文件路径frameworks/base/services/jni/com_android_server_LightsService.cpp


//1 定义INDEX
// These values must correspond with the LIGHT_ID constants in
// LightsService.java
enum {
    LIGHT_INDEX_BACKLIGHT = 0,
    LIGHT_INDEX_KEYBOARD = 1,
    LIGHT_INDEX_BUTTONS = 2,
    LIGHT_INDEX_BATTERY = 3,
    LIGHT_INDEX_NOTIFICATIONS = 4,
    LIGHT_INDEX_ATTENTION = 5,
    LIGHT_INDEX_BLUETOOTH = 6,
    LIGHT_INDEX_WIFI = 7,
    LIGHT_INDEX_FLASHLIGHT = 8, //按顺序添加即可,注意后面LightsService.java中定义的ID值与该值一致,为8
    LIGHT_COUNT
};
//2 FLASHLIGHT模块初始化
static jint init_native(JNIEnv *env, jobject clazz)
{
    int err;
    hw_module_t* module;
    Devices* devices;
    devices = (Devices*)malloc(sizeof(Devices));
    err = hw_get_module(LIGHTS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
    if (err == 0) {
        devices->lights[LIGHT_INDEX_BACKLIGHT]
                = get_device(module, LIGHT_ID_BACKLIGHT);
        devices->lights[LIGHT_INDEX_KEYBOARD]
                = get_device(module, LIGHT_ID_KEYBOARD);
        devices->lights[LIGHT_INDEX_BUTTONS]
                = get_device(module, LIGHT_ID_BUTTONS);
        devices->lights[LIGHT_INDEX_BATTERY]
                = get_device(module, LIGHT_ID_BATTERY);
        devices->lights[LIGHT_INDEX_NOTIFICATIONS]
                = get_device(module, LIGHT_ID_NOTIFICATIONS);
        devices->lights[LIGHT_INDEX_ATTENTION]
                = get_device(module, LIGHT_ID_ATTENTION);
        devices->lights[LIGHT_INDEX_BLUETOOTH]
                = get_device(module, LIGHT_ID_BLUETOOTH);
        devices->lights[LIGHT_INDEX_WIFI]
                = get_device(module, LIGHT_ID_WIFI);
        //初始化falshlight模块,当时忘记添加,导致死机
        devices->lights[LIGHT_INDEX_FLASHLIGHT]//add flashlight--bianjb
                = get_device(module, LIGHT_ID_FLASHLIGHT);
        ...
}

5 添加framework层java接口


文件位置frameworks/base/services/java/com/android/server/LightsService.java


//添加FLASHLIGHT定义,注意一定要与com_android_server_LightsService.cpp中定义的对应 INDEX值相同
public static final int LIGHT_ID_FLASHLIGHT = 8;

至此,接口添加完毕,下面讲如何进行调用


6 调用接口


6.1 自定义服务

LightsService是隐藏的API,该如何进行调用呢,可以添加自定义的Service类进行调用。


6.2 添加setBrightness方法

我添加了一个setBrightness方法到自定义服务中,需要修改三个地方


//1 FlyscaleService.java中添加如下方法
//0-255
public void setBrightness(int lightByte, int brightness) throws RemoteException {
    Log.d(TAG, "setBrightness,lightByte=" + lightByte + ",brightness=" + brightness);
    long l = Binder.clearCallingIdentity();
    try {
        //getLightByType方法是我自己定义的,返回LightsService.Light对象
        getLightByType(lightByte).setBrightness(brightness);
    } finally {
        Binder.restoreCallingIdentity(l);
    }
}
//2 IFlyscaleManager.aidl中添加接口方法
void setBrightness(int lightByte, int brightness);
//3 FlyscaleManager.java中添加供外部调用的方法
    public void setBrightness(int lightByte, int brightness) {
        Log.i(TAG, "setBrightness,lightByte=" + lightByte + ",brightness=" + brightness);
        try {
            this.mService.setBrightness(lightByte, brightness);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

6.3 APP中进行调用

例如使用AndroidStudio开发,需要把IFlyscaleManager.aidl文件引入,同时拷贝FlyscaleManager.java到与源码中相同的包名下,即可进行开发了。2.png

目录
相关文章
|
6月前
|
Android开发
Android MediaTek 平台增加UART接口的红外模块支持,支持NEC红外遥控
Android MediaTek 平台增加UART接口的红外模块支持,支持NEC红外遥控
124 0
|
6月前
|
Linux Android开发
Android 正常运行所需的一系列 Linux 内核接口
Android 正常运行所需的一系列 Linux 内核接口
93 0
|
3月前
|
Android开发
基于Amlogic 安卓9.0, 驱动简说(五):基于GPIO、LED子系统的LED驱动
这篇文章是关于如何在基于Amlogic T972的Android 9.0系统上,使用GPIO和LED子系统来实现LED驱动的教程,包括了DTS设备树配置、驱动源码编写以及如何在用户空间控制LED的亮度和开关。
86 0
基于Amlogic 安卓9.0, 驱动简说(五):基于GPIO、LED子系统的LED驱动
|
3月前
|
Android开发
不写一行代码(二):实现安卓基于PWM的LED设备驱动
本文介绍了在Android系统中不编写任何代码,通过设备树配置和内核支持的通用PWM LED驱动来实现基于PWM的LED设备驱动,并通过测试命令调整LED亮度级别。
43 0
不写一行代码(二):实现安卓基于PWM的LED设备驱动
|
3月前
|
Linux Android开发 C语言
不写一行代码(一):实现安卓基于GPIO的LED设备驱动
本文通过实践操作,展示了在Android系统中不编写任何代码,利用设备树(DTS)配置和内核支持的通用GPIO LED驱动来控制LED设备,并进一步通过C语言编写NDK测试APP来实现LED的闪烁效果。
137 0
不写一行代码(一):实现安卓基于GPIO的LED设备驱动
|
3月前
|
Android开发 开发者
Android项目架构设计问题之使用动态代理来增强 GoodsApi 接口的调用如何解决
Android项目架构设计问题之使用动态代理来增强 GoodsApi 接口的调用如何解决
20 0
|
3月前
|
存储 缓存 Java
Android项目架构设计问题之优化业务接口数据的加载效率如何解决
Android项目架构设计问题之优化业务接口数据的加载效率如何解决
44 0
|
6月前
|
XML JSON Java
Android App网络通信中通过okhttp调用HTTP接口讲解及实战(包括GET、表单格式POST、JSON格式POST 附源码)
Android App网络通信中通过okhttp调用HTTP接口讲解及实战(包括GET、表单格式POST、JSON格式POST 附源码)
818 0
Android-kotlin-接口与多态的表现,面经解析
Android-kotlin-接口与多态的表现,面经解析
|
6月前
|
Java 开发工具 Android开发
如何访问 android系统hide的类或接口
如何访问 android系统hide的类或接口
259 1