第四章:Android灯光系统(1)-总体框架

通过前面的学习,我们知道 Android系统框架大致如下图所示
在这里插入图片描述
总的来说可以分为四个层次

系统框架

1. app应用层:(主要由java语言编写)
2. Framework层:该层主要是实现的是JNI,让APP具有调用C语言的能力(涉及java,c++,c语言)
3. 硬件操控层:一般都是操作硬件的封装库,其实就是相当于llinux系统中的应用层(一般由C语言编写,少数也可以使用C++)
4. linux驱动:和linux系统中基本一(由C语言编写)

在第二章的讲解中,为我们操控LED,我们也实现了以下四个部分:
1.app:就是我们的AS工程,主要涉及文件为MainActivity.java
2.JNI:向上(APP)提供访问硬件的接口,向下访问HAL主要涉及文件为com_android_server_LedService.cpp
3.HAL:具体硬件操作,主要涉及文件led_hal.c
4.底层驱动:主要涉及文件led_drv.c
这样我们就能通过android系统的硬件访问服务操控LED了,但是这里存在一个问题,com_android_server_LedService.cpp文件,是由我们根据硬件设计编写的,那么,也只有我们自己才知道怎么使用,或者说,我们需要告诉别人怎么使用,别人根据我们的规定,调用我们的接口才能点亮LED,这样通用性就变得十分的低下了,别人以前编写的点灯APP很难适用于我们的开发板,那么下面我们就开始讲解灯光系统,我们使用系统给我们提供的com_android_server_xxxService.cpp去编写HAL文件,这样达成统一标准,在其他手机或者开发板运行APP不用做修改,就能直接在我们的开发板上运行并且操控LED了

灯光系统框架
灯管系统框架也和我们之前的一样,如果需要通过APP操控LED,他也仍然要实现之前的四个层次:

1.  APP(电池灯,通知灯,背光灯:根据客户需求进行编写)
2.  com_android_server_LightsService.cpp(系统已经完成)
3. HAL,需要我们自己编写light.c
4. led_gec3399_drv.c:之前的led_drv已经不再适用,需要进行修改

JNI需求分析

既然了解了整体框架,我们分析一下看看JNI,即com_android_server_lights_LightsService.cpp文件,只有我们知道这个框架需要什么,我们才能很好的去编写 HAL以及硬件驱动,打开文件:

static const JNINativeMethod method_table[] = {
    { "init_native", "()J", (void*)init_native },
    { "finalize_native", "(J)V", (void*)finalize_native },
    { "setLight_native", "(JIIIIII)V", (void*)setLight_native },
};

可以看到为java程序提供了3个接口,以后我们的java程序则可以通过这3个接口调用C函数,达到访问硬件的目的。在第二张的时候,我们已经讲解了JNI通过hw_get_module等,去访问HAL文件,在com_android_server_lights_LightsService.cpp中由类似代码:

    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);
    }

其中hw_get_module函数返回一个hw_module_t结构体,那么我们在HAL文件中,就需要实现一个hw_module_t结构体。其中get_device函数的实现如下:

static light_device_t* get_device(hw_module_t* module, char const* name)
{
    int err;
    hw_device_t* device;
    err = module->methods->open(module, name, &device);
    if (err == 0) {
        return (light_device_t*)device;
    } else {
        return NULL;
    }
}

其作用是从hw_module_t根据传入的名字 name获取不同的light_device_t结构体,在后续中,我们只需要实现LIGHT_ID_BACKLIGHT以及LIGHT_ID_BATTERY对应的light_device_t结构体,其余的返回NULL即可。
根据我们分析com_android_server_lights_LightsService.cpp文件之后,我们大致知道,HAL文件编写的需求

1. 实现一个hw_module_t结构体
2. 实现一个open函数,他会根据传入的name返回不同light_device_t

light_device_t结构体定义如下:

struct light_device_t {
    struct hw_device_t common;

    /**
     * Set the provided lights to the provided values.
     *
     * Returns: 0 on succes, error code on failure.
     */
    int (*set_light)(struct light_device_t* dev,
            struct light_state_t const* state);
};

很显然。对于不同的灯,对应的set_light函数也不一样,所以我需要为背光灯,通知灯,电池灯等实现不同的set_light函数,然后在该函数内去操控驱动程序。

那么对于驱动程序应该怎么编写呢,实现那些功能呢?

1.对于RGB灯:实现亮,灭,闪烁三个功能
2.对于背光灯:一般实现PWM。

小节结语

该小节主要讲解了灯光系统的框架,以及对应的JNI文件com_android_server_lights_LightsService.cpp的需求分析,在接下来的几个小节,我们会讲解1.写驱动,2.写HAL,3.分析电池灯的使用过程,4.分析通知灯使用过程,5.分析背光灯使用过程。

猜你喜欢

转载自blog.csdn.net/weixin_43013761/article/details/86776222