您的位置:首页 > 移动开发 > Android开发

android button light 流程分析(二) — HAL & JNI

2013-08-21 09:20 501 查看

buttonandroidkeyboard代码分析jniresources

一、基础数据信息

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

[cpp]
view plaincopy

/** 
 * 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,当然还有呼吸灯的定义。然后看下定义的一些状态:

[cpp]
view plaincopy

#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_
164db
FLASH_TIMED时是呼吸灯的工作机制,flashOnMS定义了led从亮度0% - 100%经过的时间,flashOffMS定义了led从亮度100% - 0%经过的时间,需要驱动去实现渐变,如果不能渐变就只能是亮或灭两个状态。color值定义了不同情况下的亮度,可以按照说明进行转换。brightnessMode则定义了lcd背光的调整模式。接下来定义了light的设备模型:

[cpp]
view plaincopy

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:

[cpp]
view plaincopy

/** 
 * 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定义了一些特殊信息:

[cpp]
view plaincopy

/** 
 * 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层一般采用固定格式定义一个新模块:

[cpp]
view plaincopy

/** 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则调用如下方法获得操作接口:

[cpp]
view plaincopy

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层实现具体操作的代码如下:

[cpp]
view plaincopy

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;  
};  
// 系统拥有的light  
enum {  
    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);  
    }  
}  
// 向节点写数据控制light  
static 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;  
}  
// 设置低电light  
static 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);  
}  
// 设置通知light  
static 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;  
}  
// 设置提醒light  
static 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;  
}  
  
// 关闭light  
static 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;  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  HAL JNI Android
相关文章推荐