android 4.4.2 亮度,androidLCD和键盘 背光亮度设置

亮度设置

应用设计

1.1 设置进度条范围

背光设置是在:设置->声音和显示->亮度,通过进度条来设置的。

文件:packages/apps/Settings/src/com/android/settings/BrightnessPreference.java

private static final int MINIMUM_BACKLIGHT =

android.os.Power.BRIGHTNESS_DIM + 10;

private static final int MAXIMUM_BACKLIGHT =

android.os.Power.BRIGHTNESS_ON;

mSeekBar.setMax(MAXIMUM_BACKLIGHT - MINIMUM_BACKLIGHT);

设置进度条的范围,BRIGHTNESS_DIM = 20 BRIGHTNESS_ON=255,它们的定义在:

frameworks/base/core/java/android/os/Power.java

1.2 设置亮度

文件:packages/apps/Settings/src/com/android/settings/BrightnessPreference.java

public void onCheckedChanged(CompoundButton buttonView, boolean

isChecked) {

setMode(isChecked ?

Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC

: Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);

if (!isChecked) {

setBrightness(mSeekBar.getProgress() + MINIMUM_BACKLIGHT);

}

}

private void setBrightness(int brightness) {

try {

IPowerManager power = IPowerManager.Stub.asInterface(

ServiceManager.getService("power"));

if (power != null) {

power.setBacklightBrightness(brightness);

}

} catch (RemoteException doe) {

}

}

由以上代码可知,brightness的范围是:20~255;代码通过服务管理器(ServiceManager)获得power服务,然后通过power服务设置亮度。

power.setBacklightBrightness的定义在:

rameworks/base/core/java/android/os/IPowerManager.aidl.java

frameworks/base/core/java/android/os/PowerManager.java

2, Power服务

文件:frameworks/base/core/java/android/os/Power.java

public

static final int BRIGHTNESS_DIM = 20;

public static final int BRIGHTNESS_ON = 255;

文件:frameworks/base/core/java/android/os/PowerManager.java

public void

setBacklightBrightness(int brightness)

{

try {

mService.setBacklightBrightness(brightness);

} catch (RemoteException e) {

}

}

电源管理器(powermager)将brightness转给电源服务,该服务位置如下:

文件:frameworks/base/services/java/com/android/server/PowerManagerService.java

public void setBacklightBrightness(int brightness) {

mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,

null);

// Don't let applications turn the screen all the way off

brightness = Math.max(brightness, Power.BRIGHTNESS_DIM);

mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BACKLIGHT,

brightness,

HardwareService.BRIGHTNESS_MODE_USER);

mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_KEYBOARD,

(mKeyboardVisible ? brightness : 0),

HardwareService.BRIGHTNESS_MODE_USER);

mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BUTTONS,

brightness,

HardwareService.BRIGHTNESS_MODE_USER);

long identity = Binder.clearCallingIdentity();

try {

mBatteryStats.noteScreenBrightness(brightness);

} catch (RemoteException e) {

Log.w(TAG, "RemoteException calling noteScreenBrightness on

BatteryStatsService", e);

} finally {

Binder.restoreCallingIdentity(identity);

}

// update our animation state

if (ANIMATE_SCREEN_LIGHTS) {

mScreenBrightness.curValue = brightness;

mScreenBrightness.animating = false;

mScreenBrightness.targetValue = -1;

}

if (ANIMATE_KEYBOARD_LIGHTS) {

mKeyboardBrightness.curValue = brightness;

mKeyboardBrightness.animating = false;

mKeyboardBrightness.targetValue = -1;

}

if (ANIMATE_BUTTON_LIGHTS) {

mButtonBrightness.curValue = brightness;

mButtonBrightness.animating = false;

mButtonBrightness.targetValue = -1;

}

}

由以上代码可知,同时设置了背光、键盘、按钮的亮度。mHardware

是硬件服务,通过该服务调用底层与设备打交道的C\C++代码,setLightBrightness_UNCHECKED原型如下:

文件:frameworks/base/services\java\com\android\server\HardwareService.java

void setLightBrightness_UNCHECKED(int light, int brightness, int

brightnessMode) {

int b = brightness & 0x000000ff;

b = 0xff000000 | (b << 16) | (b

<< 8) | b;

setLight_native(mNativePointer, light, b, LIGHT_FLASH_NONE, 0, 0,

brightnessMode);

}

参数说明:int light 表示类型,选项如下:

static final int LIGHT_ID_BACKLIGHT = 0;

static final

int LIGHT_ID_KEYBOARD = 1;

static final

int LIGHT_ID_BUTTONS = 2;

static final

int LIGHT_ID_BATTERY = 3;

static final

int LIGHT_ID_NOTIFICATIONS = 4;

static final int LIGHT_ID_ATTENTION = 5;

int brightness 表示亮度值

int brightnessMode 表示亮度的控制模式,选项如下:

static final

int BRIGHTNESS_MODE_USER = 0;

static final int BRIGHTNESS_MODE_SENSOR = 1;

由代码:

int b = brightness & 0x000000ff;

b = 0xff000000 | (b << 16) | (b

<< 8) | b;

可知,亮度值在此进行了修改,即亮度值的格式变成:FFRRGGBB,FF是没有的,RR、GG、BB分别是256色的红绿蓝,并且红绿蓝的值都是一样的亮度值。

3 硬件调用

3.1获取硬件

文件:frameworks/base/services/jni/com_android_server_HardwareService.cpp

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_COUNT

};

#define LIGHTS_HARDWARE_MODULE_ID "lights"

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

} else {

memset(devices, 0, sizeof(Devices));

}

return

(jint)devices;

}

用hw_get_module获取ID为LIGHTS_HARDWARE_MODULE_ID的硬件模块,该模块含有6个不同类型的亮度控制。

hw_get_module 的实现原理,如下:

文件:hardware/libhardware/Hardware.c

#define HAL_LIBRARY_PATH "/system/lib/hw"

static const char *variant_keys[] = {

"ro.hardware",

"ro.product.board",

"ro.board.platform",

"ro.arch"

};

static const int HAL_VARIANT_KEYS_COUNT =

(sizeof(variant_keys)/sizeof(variant_keys[0]));

int hw_get_module(const char *id, const struct hw_module_t

**module)

{

int

status;

int i;

const struct

hw_module_t *hmi = NULL;

char

prop[PATH_MAX];

char

path[PATH_MAX];

for (i=0 ;

i

if (i < HAL_VARIANT_KEYS_COUNT) {

if (property_get(variant_keys[i], prop, NULL) == 0) {

continue;

}

snprintf(path, sizeof(path), "%s/%s.%s.so",

HAL_LIBRARY_PATH, id, prop);

} else {

snprintf(path, sizeof(path), "%s/%s.default.so",

HAL_LIBRARY_PATH, id);

}

if (access(path, R_OK)) {

continue;

}

break;

}

status =

-ENOENT;

if (i

< HAL_VARIANT_KEYS_COUNT+1) {

status = load(id, path, module);

}

return

status;

}

property_get(variant_keys[i], prop, NULL)

会按如下顺序去获取如下变量所对应的值,然后返回给prop:

"ro.hardware",

"ro.product.board",

"ro.board.platform",

"ro.arch"

它们对应的变量为:

"ro.product.board=$TARGET_BOOTLOADER_BOARD_NAME"

"ro.board.platform=$TARGET_BOARD_PLATFORM"

如vendor/htc/dream-open/BoardConfig.mk里定义的TARGET_BOARD_PLATFORM :=

msm7k,则prop返回” msm7k ”,所以path = /system/lib/hw/lights.

msm7k.so,也就是说要获取的硬件模块为lights. msm7k.so。

3.2调用硬件

setLight_native对应的jni C/C++代码是:

文件:frameworks/base/services/jni/com_android_server_HardwareService.cpp

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

}

通过light标识找到对应的light设备,然后再设置亮度。

3.3 硬件原型

msm7k的lights对应的硬件原型是在:hardware/msm7k/liblights

文件:hardware/msm7k/liblights/Android.mk

LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw

LOCAL_MODULE := lights.$(TARGET_BOARD_PLATFORM)

也就是生成模块:/system/lib/hw/lights. msm7k.so

文件:hardware/msm7k/liblights/lights.c

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_KEYBOARD, name)) {

set_light = set_light_keyboard;

}

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 {

return -EINVAL;

}

pthread_once(&g_init, init_globals);

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,

};

以上代码对应的是:

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

也就是说,对不同的亮度设置给予了不同的设置函数。

举例,背光设置,背光对应的代码如下:

char const*const LCD_FILE

= "/sys/class/leds/lcd-backlight/brightness";

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_backlight(struct light_device_t* dev,

struct light_state_t const* state)

{

int err =

0;

int

brightness = rgb_to_brightness(state);

pthread_mutex_lock(&g_lock);

g_backlight

= brightness;

err =

write_int(LCD_FILE, brightness);

if

(g_haveTrackballLight) {

handle_trackball_light_locked(dev);

}

pthread_mutex_unlock(&g_lock);

return

err;

}

也就是往文件/sys/class/leds/lcd-backlight/brightness写入亮度值,然后驱动会根据该文件更改背光的亮度。LCD_FILE的路径根据实际情况更改,同时需要在init.rc

修改其权限,使其可写rgb_to_brightness也根据实际更改,比如要直接亮度值控制,那只要获取r,g,b其中的一个值就行了,如:

static int

rgb_to_brightness(struct light_state_t const* state)

{

int color =

state->color & 0x000000ff;

return

color;

}

4,led类驱动

4.1,驱动创建leds类,系统启动时执行leds_init在目录/sys/class/创建子目录leds

kernel\drivers\leds\Led-class.c

static int __init leds_init(void)

{

leds_class = class_create(THIS_MODULE,

"leds");

if (IS_ERR(leds_class))

return

PTR_ERR(leds_class);

leds_class->suspend =

led_suspend;

leds_class->resume =

led_resume;

return 0;

}

4.2,led_classdev_register,调用这个函数就在目录/sys/class/leds创建子目录led_cdev->name和属性文件brightness

对brightness文件写就执行led_brightness_store,对brightness文件读就执行led_brightness_show,为下面的lcd,led注册做好准备

kernel\drivers\leds\Led-class.c

static ssize_t led_brightness_show(struct device *dev,struct device_attribute *attr,

char *buf)

{

struct led_classdev *led_cdev =

dev_get_drvdata(dev);

led_update_brightness(led_cdev);

return sprintf(buf, "%u\n",

led_cdev->brightness);

}

static ssize_t led_brightness_store(struct device *dev,

struct device_attribute *attr,

const char *buf, size_t size)

{

struct led_classdev *led_cdev =

dev_get_drvdata(dev);

ssize_t ret = -EINVAL;

char *after;

unsigned long state = simple_strtoul(buf,

&after, 10);

size_t count = after - buf;

if (*after &&

isspace(*after))

count++;

if (count == size) {

ret = count;

if (state == LED_OFF)

led_trigger_remove(led_cdev);

led_set_brightness(led_cdev,

state);

}

return ret;

}

static DEVICE_ATTR(brightness, 0644, led_brightness_show,

led_brightness_store);

int led_classdev_register(struct device *parent, struct

led_classdev *led_cdev)

{

int rc;

led_cdev->dev =

device_create(leds_class, parent, 0, led_cdev,

"%s", led_cdev->name);

if (IS_ERR(led_cdev->dev))

return

PTR_ERR(led_cdev->dev);

rc =

device_create_file(led_cdev->dev,

&dev_attr_brightness);

if (rc)

goto err_out;

#ifdef CONFIG_LEDS_TRIGGERS

init_rwsem(&led_cdev->trigger_lock);

#endif

down_write(&leds_list_lock);

list_add_tail(&led_cdev->node,

&leds_list);

up_write(&leds_list_lock);

led_update_brightness(led_cdev);

#ifdef CONFIG_LEDS_TRIGGERS

rc =

device_create_file(led_cdev->dev,

&dev_attr_trigger);

if (rc)

goto err_out_led_list;

led_trigger_set_default(led_cdev);

#endif

printk(KERN_INFO "Registered led device:

%s\n",

led_cdev->name);

return 0;

#ifdef CONFIG_LEDS_TRIGGERS

err_out_led_list:

device_remove_file(led_cdev->dev,

&dev_attr_brightness);

list_del(&led_cdev->node);

#endif

err_out:

device_unregister(led_cdev->dev);

return rc;

}

EXPORT_SYMBOL_GPL(led_classdev_register);

4.3,lcd驱动调用led_classdev_register,在目录/sys/class/leds创建子目录lcd-backlight和属性文件brightness

kernel\drivers\video\msm\Msm_fb.c

static int lcd_backlight_registered;

static void msm_fb_set_bl_brightness(struct led_classdev

*led_cdev,

enum

led_brightness value)

{

struct msm_fb_data_type *mfd =

dev_get_drvdata(led_cdev->dev->parent);

int bl_lvl;

if (value >

MAX_BACKLIGHT_BRIGHTNESS)

value =

MAX_BACKLIGHT_BRIGHTNESS;

bl_lvl = (2 * value *

mfd->panel_info.bl_max +

MAX_BACKLIGHT_BRIGHTNESS)

/(2 *

MAX_BACKLIGHT_BRIGHTNESS);

if (!bl_lvl &&

value)

bl_lvl = 1;

msm_fb_set_backlight(mfd, bl_lvl, 1);

}

static struct led_classdev backlight_led = {

.name =

"lcd-backlight",

.brightness =

MAX_BACKLIGHT_BRIGHTNESS,

.brightness_set =

msm_fb_set_bl_brightness,

};

if (!lcd_backlight_registered) {

if

(led_classdev_register(&pdev->dev,

&backlight_led))

printk(KERN_ERR

"led_classdev_register failed\n");

else

lcd_backlight_registered

= 1;

}

就在目录/sys/class/leds创建子目录 lcd-backlight和属性文件brightness

当按键或者来的或者改变lcd亮度时,上层对属性文件/sys/class/leds/lcd-backlight/brightness写入背光的亮度数值就

调用led_brightness_store

调用simple_strtoul(buf, &after,

10);将输入的字符串转换为10进制的数字

执行led_set_brightness

执行led_cdev->brightness_set(led_cdev, value

调用msm_fb_set_bl_brightness

,因为 .brightness_set =

msm_fb_set_bl_brightness,

bl_lvl = (2 * value *

mfd->panel_info.bl_max +

MAX_BACKLIGHT_BRIGHTNESS) /(2 *

MAX_BACKLIGHT_BRIGHTNESS);

将输入的0--255转换为IC的0--bl_max

调用 msm_fb_set_backlight(mfd, bl_lvl, 1);

最终改变LCD的背光驱动电路的设置,调节LCD的背光的亮度

4.4 键盘背光灯

上层对属性文件/sys/class/leds/keyboard-backlight/brightness写入背光的亮度数值

(kernel\drivers\leds\Leds-msm-pmic.c

#define MAX_KEYPAD_BL_LEVEL 16

static void msm_keypad_bl_led_set(struct led_classdev

*led_cdev,

enum led_brightness value)

{

int ret;

ret = pmic_set_led_intensity(LED_KEYPAD, value /

MAX_KEYPAD_BL_LEVEL);

if (ret)

dev_err(led_cdev->dev,

"can't set keypad backlight\n");

}

static struct led_classdev msm_kp_bl_led = {

.name =

"keyboard-backlight",

.brightness_set =

msm_keypad_bl_led_set,

.brightness =

LED_OFF,

};

static int msm_pmic_led_probe(struct platform_device *pdev)

{

int rc;

rc =

led_classdev_register(&pdev->dev,

&msm_kp_bl_led);

if (rc) {

dev_err(&pdev->dev,

"unable to register led class driver\n");

return rc;

}

msm_keypad_bl_led_set(&msm_kp_bl_led,

LED_OFF);

return rc;

}

static int __devexit msm_pmic_led_remove(struct platform_device

*pdev)

{

led_classdev_unregister(&msm_kp_bl_led);

return 0;

}

#ifdef CONFIG_PM

static int msm_pmic_led_suspend(struct platform_device *dev,

pm_message_t state)

{

led_classdev_suspend(&msm_kp_bl_led);

return 0;

}

static int msm_pmic_led_resume(struct platform_device *dev)

{

led_classdev_resume(&msm_kp_bl_led);

return 0;

}

#else

#define msm_pmic_led_suspend NULL

#define msm_pmic_led_resume NULL

#endif

static struct platform_driver msm_pmic_led_driver = {

.probe =

msm_pmic_led_probe,

.remove =

__devexit_p(msm_pmic_led_remove),

.suspend =

msm_pmic_led_suspend,

.resume =

msm_pmic_led_resume,

.driver =

{

.name =

"pmic-leds",

.owner =

THIS_MODULE,

},

};

static int __init msm_pmic_led_init(void)

{

return

platform_driver_register(&msm_pmic_led_driver);

}

module_init(msm_pmic_led_init);

static void __exit msm_pmic_led_exit(void)

{

platform_driver_unregister(&msm_pmic_led_driver);

}

module_exit(msm_pmic_led_exit);

MODULE_DESCRIPTION("MSM PMIC LEDs driver");

MODULE_LICENSE("GPL v2");

MODULE_ALIAS("platform:p

系统行动执行msm_pmic_led_init(void)

调用 platform_driver_register(&msm_pmic_led_driver);

调用msm_pmic_led_probe

调用 led_classdev_register(&pdev->dev,

&msm_kp_bl_led);

就在目录/sys/class/leds创建子目录 keyboard-backlight和属性文件brightness

当按键时,上层对属性文件/sys/class/leds/keyboard-backlight/brightness写入背光的亮度数值就

调用led_brightness_store

调用simple_strtoul(buf, &after,

10);将输入的字符串转换为10进制的数字

执行led_set_brightness

执行led_cdev->brightness_set(led_cdev, value

调用msm_keypad_bl_led_set

,因为 .brightness_set =

msm_keypad_bl_led_set,

调用 ret = pmic_set_led_intensity(LED_KEYPAD, value

/ MAX_KEYPAD_BL_LEVEL);

最终改变LED驱动电路的设置,调节LED的亮度

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值