1. 上层处理
PowerManagerService.java (frameworks\base\services\java\com\android\server)
private LightsService.Light mLcdLight;
private void setLightBrightness(int mask, int value) {
int brightnessMode = (mAutoBrightessEnabled
? LightsService.BRIGHTNESS_MODE_SENSOR
: LightsService.BRIGHTNESS_MODE_USER);
if ((mask & SCREEN_BRIGHT_BIT) != 0) {
if (DEBUG_SCREEN_ON) {
RuntimeException e = new RuntimeException("here");
e.fillInStackTrace();
Slog.i(TAG, "Set LCD brightness: " + value, e);
}
mLcdLight.setBrightness(value, brightnessMode);
}
if ((mask & BUTTON_BRIGHT_BIT) != 0) {
mButtonLight.setBrightness(value);
}
if ((mask & KEYBOARD_BRIGHT_BIT) != 0) {
mKeyboardLight.setBrightness(value);
}
}
LightsService.java (frameworks\base\services\java\com\android\server)
public void setBrightness(int brightness, int brightnessMode) {
synchronized (this) {
int color = brightness & 0x000000ff;
color = 0xff000000 | (color << 16) | (color << 8) | color;
setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, brightnessMode);
}
}
private void setLightLocked(int color, int mode, int onMS, int offMS, int brightnessMode) {
if (color != mColor || mode != mMode || onMS != mOnMS || offMS != mOffMS) {
if (DEBUG) Slog.v(TAG, "setLight #" + mId + ": color=#"
+ Integer.toHexString(color));
mColor = color;
mMode = mode;
mOnMS = onMS;
mOffMS = offMS;
setLight_native(mNativePointer, mId, color, mode, onMS, offMS, brightnessMode);
}
}
2. JNI 处理
com_android_server_LightsService.cpp(/framework/base/services/jni/)
static JNINativeMethod method_table[] = {
{ "init_native", "()I", (void*)init_native },
{ "finalize_native", "(I)V", (void*)finalize_native },
{ "setLight_native", "(IIIIIII)V", (void*)setLight_native },
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 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);
}
3. 底层处理
Lights.c (device\marvell\***\lights)
const char * const LCD_BACKLIGHT = "/sys/class/backlight/pwm-backlight.2/brightness";
static int lights_device_open(const struct hw_module_t *module,
const char *name, struct hw_device_t **device);
static struct hw_module_methods_t lights_module_methods = {
.open = lights_device_open
};
struct light_module_t
{
struct hw_module_t common;
};
const struct light_module_t HAL_MODULE_INFO_SYM = {
common: {
tag : HARDWARE_MODULE_TAG,
version_major : 1,
version_minor : 0,
id : LIGHTS_HARDWARE_MODULE_ID,
name : "lights module",
author : "",
methods : &lights_module_methods,
}
};
int lights_set(struct light_device_t* dev, struct light_state_t const* state, const char* brightness_node) {
struct light_state_t const *light_state = (struct light_state_t const*)state;
unsigned char brightness = 0;
int fd = -1;
struct my_light_device_t *mydev = (struct my_light_device_t*)dev;
if( light_state ) {
unsigned int color = light_state->color;
brightness = (color & 0xff) * mydev->max_brightness / 0xff;
} else {
LOGE("lights_set_brightness failed: light state is null\n");
return -EINVAL;
}
fd = open(brightness_node, O_RDWR);
if( fd >= 0 ) {
char buffer[20];
int bytes = sprintf(buffer, "%d", brightness);
int rlt = write(fd, buffer, bytes);
if( rlt < 0 ){
LOGE("lights_set_brightness %s, fail to set brightness to:%s, errno:%d\n", brightness_node, buffer, errno);
close(fd);
return -1;
}
close(fd);
} else {
static int already_warned = 0;
if (already_warned < 5) {
LOGE("lights_set_brightness failed to open %s, errno:%d\n", brightness_node, errno);
already_warned++;
}
return -1;
}
return 0;
}
int lights_set_lcd(struct light_device_t* dev, struct light_state_t const* state)
{
return lights_set( dev, state, LCD_BACKLIGHT);
}
static int lights_device_open(const struct hw_module_t *module,
const char *name, struct hw_device_t **device)
{
int status = -EINVAL;
int ret;
#ifdef LIGHTS_DEBUG
LOGD("lights_device_open: device name: %s\n", name);
#endif
struct light_device_t *dev = NULL;
struct my_light_device_t *mydev = NULL;
mydev = (struct my_light_device_t *)calloc(sizeof(struct my_light_device_t), 1);
dev = &(mydev->dev);
dev->common.tag = HARDWARE_DEVICE_TAG;
dev->common.version = 0;
dev->common.module = (struct hw_module_t *)(module);
dev->common.close = lights_device_close;
mydev->max_brightness = 0xff;//default max brightness is 255
*device = &dev->common;
if (!strcmp(name, LIGHT_ID_BACKLIGHT)) {
dev->set_light = lights_set_lcd;
readIntFromFile( LCD_MAX_BACKLIGHT, &mydev->max_brightness);
ret = access(LCD_BACKLIGHT, F_OK);
if (ret != 0)
return status;
} else if (!strcmp(name, LIGHT_ID_KEYBOARD)) {
dev->set_light = lights_set_keyboard;
readIntFromFile( KEYBOARD_MAX_BACKLIGHT, &mydev->max_brightness);
ret = access(KEYBOARD_BACKLIGHT, F_OK);
if (ret != 0)
return status;
} else if (!strcmp(name, LIGHT_ID_BUTTONS)) {
dev->set_light = lights_set_button;
ret = access(BUTTON_BACKLIGHT, F_OK);
if (ret != 0)
return status;
} else if (!strcmp(name, LIGHT_ID_BATTERY)) {
dev->set_light = lights_set_battery;
ret = access(BATTERY_BACKLIGHT, F_OK);
if (ret != 0)
return status;
} else if (!strcmp(name, LIGHT_ID_NOTIFICATIONS)) {
dev->set_light = lights_set_notifications;
ret = access(NOTIFICATIONS_BACKLIGHT, F_OK);
if (ret != 0)
return status;
} else if (!strcmp(name, LIGHT_ID_ATTENTION)) {
dev->set_light = lights_set_attention;
ret = access(ATTENTION_BACKLIGHT, F_OK);
if (ret != 0)
return status;
} else
return status;
return 0;
}
ps:
节点创建位置:
configs/XXX/init/copyfiles/root/init.pxa988.rc
chown system system /sys/class/backlight/pwm-backlight.4/brightness