Android电源管理系统调研报告-(4)
来源:互联网 发布:python pdf下载 编辑:程序博客网 时间:2024/04/30 07:07
二、Brightness的调节
现在通过一个具体的电源管理实例来了解从andriod上层到内核驱动层的整个调用流程。
如果你使用过android操作系统,无论是模拟器还是开发板亦或手机,对里面setting这个服务一定很熟悉吧。其中有一项是用于调节显示屏亮度的:
setting/sound & display settings/brightness。
这个功能是怎么实现的呢。通过分析,我们可以清晰看到整个调用的流程,上层是如何一步一步到达驱动层,把LCD屏幕亮度改变的。
1、android层的调用流程。1)、BrightnessPreference.java
/packages/apps/Settings/src/com/android/settings/
// Backlight range is from 0 - 255. Need to make sure that user
// doesn't set the backlight to 0 and get stuck
private static final int MINIMUM_BACKLIGHT = android.os.Power.BRIGHTNESS_DIM + 10;
private static final int MAXIMUM_BACKLIGHT = android.os.Power.BRIGHTNESS_ON;
当系统检测到调节亮度的调节栏改变时,会重新设置屏幕的亮度:
public void (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) {
}
}
首先,onCheckedChanged会检查当前亮度调节的模式,如果是AUTOMATIC模式,则isChecked为1(MANUAL为0)。当isChecked为0时,即当前模式为手动调节模式,则会调用setBrightness调节亮度。
可以看到,setBrightness先会通过调用ServiceManager.getService("power")获得power manager service这个服务的对象power,获取成功后会调用power.setBacklightBrightness(brightness);我们进入PowerManagerService.java看这个方法的具体内容。
2)、PowerManagerService.java
/frameworks/base/services/java/com/android/server/
手动调用的范围是MINI到MAX。而setBrightness传进来的参数为 MINI + MINIMUM_BACKLIGHT到 MAX + MINIMUM_BACKLIGHT,以确保brightness最小为MINIMUM_BACKLIGHT。在setBrightness方法的一开始又对brightness进行了修正,从而确保应用程序不能将屏幕全部熄灭。
// Don't let applications turn the screen all the way off
brightness = Math.max(brightness, Power.BRIGHTNESS_DIM)
setBacklightBrightness这个方法会调节lcd backlight、keyboard light、和buttons light这三个设备的亮度,但都是通过调用setLightBrightness_UNCHECKED实现的。
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);
让我们先看一下第一个设备亮度的调节,注意参数LIGHT_ID_BACKLIGHT,它将决定选择操作哪一个设备。
3)、HardwareService.java
/frameworks/base/services/java/com/android/server/
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);
}
setLightBrightness_UNCHECKED调用了本地方法setLight_native,同时将brightness做了相就的处理,处理后的数据作为colorARGB传入本地方法。
4)、com_android_server_HardwareService.java
/frameworks/base/services/jni/
setLight_native函数中定义了一个类型为struct light_state_t的结构体,并对这个结构体的成员进行赋值,最后对一个函数指针进行了赋值:
devices->lights[light]->set_light(devices->lights[light],&state);
先来看看这个结构体:
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;
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;
};
再来看这个函数指针指向的函数。在Lights.c这个文件中的open_lights这个函数中,对传入参数的不同对set_light进行了赋值:
在这里,name传入的是LIGHT_ID_BACKLIGHT
if (0 == strcmp(LIGHT_ID_BACKLIGHT, name)) {
set_light = set_light_backlight;
}
set_light_backlight的函数原型如下:
static int
set_light_backlight(struct light_device_t* dev,
struct light_state_t const* state)
再对比一下函数指针的赋值:
devices->lights[light]->set_light(devices->lights[light],&state);
可见,参数devices->lights[light],&state分别传入了dev和state。
让我们来看一下set_light_backlight的内容:
5)、Lights.c
/hardware/msm7k/liblights/
这个文件已经不陌生了吧,上文刚刚提到呵。
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;
}
(1)、在这里对brightness进行了特殊的赋值:
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;
}
之所以这样赋值在struct light_state_t的注释中有解释。
(2)、write_int的参数LCD_FILE
char const*const LCD_FILE
= "/sys/class/leds/lcd-backlight/brightness";
这个路径是kernel中sysfs生成的设备节点,用户可以直接对这个设备节点进行操作。
sysfs ~~~~~
When a driver is registered, a sysfs directoryis created in its bus's directory. In this directory, the driver can export aninterface to userspace to control operation of the driver on a global basis;e.g. toggling debugging output in the driver.
A future feature of this directory will be a'devices' directory. This directory will contain symlinks to the directories ofdevices it supports.
(3)、
err = write_int(LCD_FILE, brightness);
write_int(char const* path, int value)
{
int fd;
static int already_warned = 0;
fd = open(path, O_RDWR);
if (fd >= 0) {
char buffer[20];
int bytes = sprintf(buffer, "%d/n", value);
int amt = write(fd, buffer, bytes);
close(fd);
return amt == -1 ? -errno : 0;
} else {
if (already_warned == 0) {
LOGE("write_int failed to open %s/n", path);
already_warned = 1;
}
return -errno;
}
打开设备结点后,最终通过write将brigthness写入到了设备结点。
- Android电源管理系统调研报告-(4)
- Android电源管理系统调研报告-(1)
- Android电源管理系统调研报告-(2)
- Android电源管理系统调研报告-(3)
- Android电源管理系统调研报告-(5)
- Android电源管理系统调研报告-(3)
- 2011-01-04 14:16 Android电源管理系统调研报告
- android系统电源管理
- Android系统级电源管理
- 监控系统调研报告
- Linux电源管理(一)电源管理系统架构
- Android系统--PowerManagerService电源管理分析
- Android 电源管理 (转载)
- Android电源管理(zz)
- Android电源管理(zz)
- Android电源管理(zz)
- bug管理系统调研
- 通信系统CMMB调研报告
- 中国概念股的诚信伤不起
- ASP.NET MD5加密
- 或导致后续中国公司上市推迟
- c# 正则表达式
- Android电源管理系统调研报告-(3)
- Android电源管理系统调研报告-(4)
- ASP.NET 中级
- Android电源管理系统调研报告-(5)
- JQuery 正则表达式
- 备忘录:简单的分页
- css+div+ul中向菜单
- Struts2 数据 标签 之 Action Tag
- WP7 Dev 101 【0】 开发环境的准备
- [转]简单内存泄漏检测方法 解决 Detected memory leaks! 问题