一、基础数据信息
首先看一下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; }; // 系统拥有的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; }