一、基础数据信息

首先看一下HAL定义的light类型:

/** * The id of this module */#define LIGHTS_HARDWARE_MODULE_ID "lights"/* * These light IDs correspond to logical lights, not physical. * So for example, if your INDICATOR light is in line with your * BUTTONS, it might make sense to also light the INDICATOR * light to a reasonable color when the BUTTONS are lit. */#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"/* * These lights aren't currently supported by the higher * layers, but could be someday, so we have the constants * here now. */#define LIGHT_ID_BLUETOOTH          "bluetooth"#define LIGHT_ID_WIFI               "wifi"
可以看到我们常用的backlight,以及我们主要分析的buttons,当然还有呼吸灯的定义。然后看下定义的一些状态:

#define LIGHT_FLASH_NONE            0/** * To flash the light at a given rate, set flashMode to LIGHT_FLASH_TIMED, * and then flashOnMS should be set to the number of milliseconds to turn * the light on, followed by the number of milliseconds to turn the light * off. */#define LIGHT_FLASH_TIMED           1/** * To flash the light using hardware assist, set flashMode to * the hardware mode. */#define LIGHT_FLASH_HARDWARE        2/** * Light brightness is managed by a user setting. */#define BRIGHTNESS_MODE_USER        0/** * Light brightness is managed by a light sensor. */#define BRIGHTNESS_MODE_SENSOR      1/** * The parameters that can be set for a given light. * * Not all lights must support all parameters.  If you * can do something backward-compatible, you should. */struct light_state_t {    /**     * The color of the LED in ARGB.     *     * Do your best here.     *   - If your light can only do red or green, if they ask for blue,     *     you should do green.     *   - If you can only do a brightness ramp, then use this formula:     *      unsigned char brightness = ((77*((color>>16)&0x00ff))     *              + (150*((color>>8)&0x00ff)) + (29*(color&0x00ff))) >> 8;     *   - If you can only do on or off, 0 is off, anything else is on.     *     * The high byte should be ignored.  Callers will set it to 0xff (which     * would correspond to 255 alpha).     */    unsigned int color;    /**     * See the LIGHT_FLASH_* constants     */    int flashMode;    int flashOnMS;    int flashOffMS;    /**     * Policy used by the framework to manage the light's brightness.     * Currently the values are BRIGHTNESS_MODE_USER and BRIGHTNESS_MODE_SENSOR.     */    int brightnessMode;};
可以看到在flashMode为LIGHT_FLASH_TIMED时是呼吸灯的工作机制,flashOnMS定义了led从亮度0% - 100%经过的时间,flashOffMS定义了led从亮度100% - 0%经过的时间,需要驱动去实现渐变,如果不能渐变就只能是亮或灭两个状态。color值定义了不同情况下的亮度,可以按照说明进行转换。brightnessMode则定义了lcd背光的调整模式。接下来定义了light的设备模型:

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为设置各个light的接口,设备模型需要继承于HAL层统一的结构hw_device_t:

/** * Every device data structure must begin with hw_device_t * followed by module specific public methods and attributes. */typedef struct hw_device_t {    /** tag must be initialized to HARDWARE_DEVICE_TAG */    uint32_t tag;    /** version number for hw_device_t */    uint32_t version;    /** reference to the module this device belongs to */    struct hw_module_t* module;    /** padding reserved for future use */    uint32_t reserved[12];    /** Close this device */    int (*close)(struct hw_device_t* device);} hw_device_t;
其中定义了一些公共接口和属性。其中hw_module_t定义了一些特殊信息:

/** * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM * and the fields of this data structure must begin with hw_module_t * followed by module specific information. */typedef struct hw_module_t {    /** tag must be initialized to HARDWARE_MODULE_TAG */    uint32_t tag;    /** major version number for the module */    uint16_t version_major;    /** minor version number of the module */    uint16_t version_minor;    /** Identifier of module */    const char *id;    /** Name of this module */    const char *name;    /** Author/owner/implementor of the module */    const char *author;    /** Modules methods */    struct hw_module_methods_t* methods;    /** module's dso */    void* dso;    /** padding to 128 bytes, reserved for future use */    uint32_t reserved[32-7];} hw_module_t;typedef struct hw_module_methods_t {    /** Open a specific device */    int (*open)(const struct hw_module_t* module, const char* id,            struct hw_device_t** device);} hw_module_methods_t;
二、代码流程分析

在HAL层一般采用固定格式定义一个新模块:

/** Open a new instance of a lights device using name */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);    if (0 == strcmp(LIGHT_ID_BACKLIGHT, name)) {  // 根据名称设置相应的接口        set_light = set_light_backlight;    }    else if (0 == strcmp(LIGHT_ID_BUTTONS, name)) {        set_light = set_light_buttons;    }    else if (0 == strcmp(LIGHT_ID_BATTERY, name)) {        set_light = set_light_battery;    }    else if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name)) {        set_light = set_light_notifications;    }    else if (0 == strcmp(LIGHT_ID_ATTENTION, name)) {        set_light = set_light_attention;    }    else {        LOGE("name %s\n", name);        return -EINVAL;    }    pthread_once(&g_init, init_globals);    // 创建light_device_t    struct light_device_t *dev = malloc(sizeof(struct light_device_t));    memset(dev, 0, sizeof(*dev));    dev->common.tag = HARDWARE_DEVICE_TAG;    dev->common.version = 0;    dev->common.module = (struct hw_module_t*)module;    // 关闭接口    dev->common.close = (int (*)(struct hw_device_t*))close_lights;    dev->set_light = set_light;    *device = (struct hw_device_t*)dev;    return 0;}static struct hw_module_methods_t lights_module_methods = {    .open =  open_lights,};/* * The lights Module */const struct hw_module_t HAL_MODULE_INFO_SYM = {    .tag = HARDWARE_MODULE_TAG,       // 规定的tag    .version_major = 1,    .version_minor = 0,    .id = LIGHTS_HARDWARE_MODULE_ID,  // 模块id    .name = "atxx lights Module",     // 名称    .author = "xxx",    .methods = &lights_module_methods,// 方法};
JNI则调用如下方法获得操作接口:
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_COUNT};struct Devices {    light_device_t* lights[LIGHT_COUNT];};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;    }}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);    } else {        memset(devices, 0, sizeof(Devices));    }    return (jint)devices;}static void finalize_native(JNIEnv *env, jobject clazz, int ptr){    Devices* devices = (Devices*)ptr;    if (devices == NULL) {        return;    }    free(devices);}static void setLight_native(JNIEnv *env, jobject clazz, int ptr,        int light, int colorARGB, int flashMode, int onMS, int offMS, int brightnessMode){    Devices* devices = (Devices*)ptr;    light_state_t state;    if (light < 0 || light >= LIGHT_COUNT || devices->lights[light] == NULL) {        return ;    }    memset(&state, 0, sizeof(light_state_t));    state.color = colorARGB;    state.flashMode = flashMode;    state.flashOnMS = onMS;    state.flashOffMS = offMS;    state.brightnessMode = brightnessMode;    devices->lights[light]->set_light(devices->lights[light], &state);}static JNINativeMethod method_table[] = {    { "init_native", "()I", (void*)init_native },    { "finalize_native", "(I)V", (void*)finalize_native },    { "setLight_native", "(IIIIIII)V", (void*)setLight_native },};int register_android_server_LightsService(JNIEnv *env){    return jniRegisterNativeMethods(env, "com/android/server/LightsService",            method_table, NELEM(method_table));}
HAL层实现具体操作的代码如下:
static pthread_once_t g_init = PTHREAD_ONCE_INIT;static pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER;// 操作led的名称以及句柄struct led_prop {    const char *filename;    int fd;};// 3个操作的集合struct led {    struct led_prop brightness;    struct led_prop flash_on_ms;    struct led_prop flash_off_ms;};// 系统拥有的lightenum {    RED_LED,    GREEN_LED,    BLUE_LED,    LCD_BACKLIGHT,    BUTTONS_LED,    NUM_LEDS,};// 操作各light的节点struct led leds[NUM_LEDS] = {    [RED_LED] = {        .brightness = { "/sys/class/leds/red/brightness", -1},        .flash_on_ms = { "/sys/class/leds/red/delay_on", -1},        .flash_off_ms = { "/sys/class/leds/red/delay_off", -1},    },    [GREEN_LED] = {        .brightness = { "/sys/class/leds/green/brightness", -1},        .flash_on_ms = { "/sys/class/leds/green/delay_on", -1},        .flash_off_ms = { "/sys/class/leds/green/delay_off", -1},    },    [BLUE_LED] = {        .brightness = { "/sys/class/leds/blue/brightness", -1},        .flash_on_ms = { "/sys/class/leds/blue/delay_on", -1},        .flash_off_ms = { "/sys/class/leds/blue/delay_off", -1},    },    [LCD_BACKLIGHT] = {        .brightness = { "/sys/class/backlight/backlight/brightness", -1},    },    [BUTTONS_LED] = {        .brightness = {"/sys/class/leds/button-backlight/brightness", -1},    },};static int is_battery_light_on = 0;/** * device methods */// 初始化单个节点static int init_prop(struct led_prop *prop){    int fd;    prop->fd = -1;    if (!prop->filename)        return 0;    fd = open(prop->filename, O_RDWR);    if (fd < 0) {        LOGE("init_prop: %s cannot be opened (%s)\n", prop->filename,             strerror(errno));        return -errno;    }    prop->fd = fd;    return 0;}// 关闭节点static void close_prop(struct led_prop *prop){    int fd;    if (prop->fd > 0)        close(prop->fd);    return;}// 初始化全部节点void init_globals(void){    int i;    pthread_mutex_init(&g_lock, NULL);    for (i = 0; i < NUM_LEDS; ++i) {        init_prop(&leds[i].brightness);        init_prop(&leds[i].flash_on_ms);        init_prop(&leds[i].flash_off_ms);    }}// 向节点写数据控制lightstatic int write_int(struct led_prop *prop, int value){    char buffer[20];    int bytes;    int amt;    if (prop->fd < 0)        return 0;    LOGV("%s %s: 0x%x\n", __func__, prop->filename, value);    bytes = snprintf(buffer, sizeof(buffer), "%d\n", value);    while (bytes > 0) {        amt = write(prop->fd, buffer, bytes);        if (amt < 0) {            if (errno == EINTR)                continue;            return -errno;        }        bytes -= amt;    }    return 0;}// 用于呼吸灯控制static int set_speaker_light(struct light_device_t* dev,        struct light_state_t const* state){    int len;    int value;    unsigned int colorRGB;    unsigned int colorR;    unsigned int colorG;    unsigned int colorB;    colorRGB = state->color & 0xFFFFFF;    if (colorRGB == 0xFFFFFF) { /* white */        colorRGB = 0x0;    }    colorR = (colorRGB >> 16) & 0x00ff;    colorG = (colorRGB >> 8) & 0x00ff;    colorB = colorRGB & 0x00ff;    pthread_mutex_lock(&g_lock);    switch (state->flashMode) {        case LIGHT_FLASH_TIMED:        case LIGHT_FLASH_HARDWARE:            if (colorR) {                write_int(&leds[RED_LED].flash_on_ms, state->flashOnMS);                write_int(&leds[RED_LED].flash_off_ms, state->flashOffMS);            } else {  /*off*/                write_int(&leds[RED_LED].flash_on_ms, 0);            }            if (colorG) {                write_int(&leds[GREEN_LED].flash_on_ms, state->flashOnMS);                write_int(&leds[GREEN_LED].flash_off_ms, state->flashOffMS);            } else {  /*off*/                write_int(&leds[GREEN_LED].flash_on_ms, 0);            }            if (colorB) {                write_int(&leds[BLUE_LED].flash_on_ms, state->flashOnMS);                write_int(&leds[BLUE_LED].flash_off_ms, state->flashOffMS);            } else {  /*off*/                write_int(&leds[BLUE_LED].flash_on_ms, 0);            }            break;        case LIGHT_FLASH_NONE:            if (colorR) {                write_int(&leds[RED_LED].flash_on_ms, 255);                write_int(&leds[RED_LED].flash_off_ms, 0);            } else {  /*off*/                write_int(&leds[RED_LED].flash_on_ms, 0);            }            if (colorG) {                write_int(&leds[GREEN_LED].flash_on_ms, 255);                write_int(&leds[GREEN_LED].flash_off_ms, 0);            } else {  /*off*/                write_int(&leds[GREEN_LED].flash_on_ms, 0);            }            if (colorB) {                write_int(&leds[BLUE_LED].flash_on_ms, 255);                write_int(&leds[BLUE_LED].flash_off_ms, 0);            } else {  /*off*/                write_int(&leds[BLUE_LED].flash_on_ms, 0);            }            break;        default:            LOGE("set_led_state colorRGB=%08X, unknown mode %d\n",                  colorRGB, state->flashMode);    }    pthread_mutex_unlock(&g_lock);    return 0;}// rgb数据转换成背光值static int rgb_to_brightness(struct light_state_t const* state){    int color = state->color & 0x00ffffff;    return ((77*((color>>16)&0x00ff))                        + (150*((color>>8)&0x00ff)) + (29*(color&0x00ff))) >> 8;}// 设置按键灯亮度static int set_light_buttons(struct light_device_t* dev,        struct light_state_t const* state){    int err = 0;    int brightness = rgb_to_brightness(state);    LOGE("%s brightness=%d color=0x%08x",            __func__, brightness, state->color);    err = write_int(&leds[BUTTONS_LED].brightness, brightness);return err;}// 设置lcd背光亮度static int set_light_backlight(struct light_device_t* dev,        struct light_state_t const* state){    int err = 0;    int brightness = rgb_to_brightness(state);    LOGV("%s brightness=%d color=0x%08x",            __func__, brightness, state->color);    err = write_int(&leds[LCD_BACKLIGHT].brightness, brightness);    return err;}// 设置低电lightstatic int set_light_battery(struct light_device_t* dev,        struct light_state_t const* state){    int colorRGB = state->color & 0xFFFFFF;    LOGD("%s flashMode %d, flashOnMs %d, flashOffMs %d, color=0x%08x\n",            __func__, state->flashMode, state->flashOnMS, state->flashOffMS, state->color);    if (colorRGB != 0x0 && colorRGB != 0xFFFFFF) {        is_battery_light_on = 1;    } else  {        is_battery_light_on = 0;    }    return set_speaker_light(dev, state);}// 设置通知lightstatic int set_light_notifications(struct light_device_t* dev,        struct light_state_t const* state){    LOGD("%s flashMode %d, flashOnMs %d, flashOffMs %d, color=0x%08x\n",            __func__, state->flashMode, state->flashOnMS, state->flashOffMS, state->color);    if (!is_battery_light_on) {        set_speaker_light(dev, state);    }    return 0;}// 设置提醒lightstatic int set_light_attention(struct light_device_t* dev,        struct light_state_t const* state){    LOGD("%s flashMode %d, flashOnMs %d, flashOffMs %d, color=0x%08x\n",            __func__, state->flashMode, state->flashOnMS, state->flashOffMS, state->color);    if (!is_battery_light_on) {        set_speaker_light(dev, state);    }    return 0;}// 关闭lightstatic int close_lights(struct light_device_t *dev){    int i;    for (i = 0; i < NUM_LEDS; ++i) {        close_prop(&leds[i].brightness);        close_prop(&leds[i].flash_on_ms);        close_prop(&leds[i].flash_off_ms);    }    if (dev) {        free(dev);    }    return 0;}

更多相关文章

  1. 安卓-开发常见问题之android:onClick未定义
  2. android 点击空白处收起键盘和自定义EditText实现右下角计数控件
  3. Android ProgressBar 自定义样式(六),仿真QQ pad版加载(位置居中)
  4. Android Display buffer_handle_t的定义
  5. android 之Dialog的多种Dialog对话框(以及反射在自定义对话框的
  6. Android改变图片颜色的自定义控件(十)

随机推荐

  1. Android免安装应用对所有开发者开放
  2. Android原生(Native)C开发之三:鼠标事件篇
  3. Android简易订机票系统
  4. 使用新的 Android(安卓)Studio 加速你的
  5. Android开发问题记录(二)——Eclipse不显示
  6. Android基础教程之----简单拨打电话程序!
  7. Android(安卓)LinearLayout中元素按比例
  8. Android(安卓)ListView item中有按钮(But
  9. Android(安卓)总结:进阶之路(资源与方法)
  10. [转]Android(安卓)Service