1, kernel command line: androidboot.mode = charger
2, command line androidboot.xxx 转换成 ro.boot.xxx
/system/core/init/init.cppmain() -> process_kernel_cmdline() -> import_kernel_cmdline() -> import_kernel_nv()
androidboot.mode => ro.boot.mode
3, ro.boot.mode => ro.bootmode
/system/core/init/init.cppmain() -> export_kernel_boot_props()
4, /system/core/init/init.cpp: main()
// Don't mount filesystems or start core system services in charger mode.std::string bootmode = property_get("ro.bootmode");
if (bootmode == "charger") {
am.QueueEventTrigger("charger");
} else if (strncmp(bootmode.c_str(), "ffbm", 4) == 0) {
NOTICE("Booting into ffbm mode\n");
am.QueueEventTrigger("ffbm");
} else {
am.QueueEventTrigger("late-init");
}
5, /system/core/rootdir/init.rc
on charger# Change cpu0 and cpu1 cpufreq governor from performance to interactive
write /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor interactive
write /sys/devices/system/cpu/cpu1/cpufreq/scaling_governor interactive
# Enable the lpm
write /sys/module/lpm_levels/parameters/sleep_disabled 0
class_start charger
6, /device/qcom/common/rootdir/etc/init.qcom.rc
service charger /chargerclass charger
group system graphics
seclabel u:r:healthd:s0
7, $ ls -al out/target/product/aione/root/charger
lrwxrwxrwx 1 jasonfu jasonfu 13 1月 10 17:07 out/target/product/aione/root/charger -> /sbin/healthd软连接
8, /system/core/healthd/healthd.cpp:main()
healthd_mode_ops->heartbeat()-> system/core/healthd/healthd_mode_charger.cpp: healthd_mode_charger_heartbeat()
-> : handle_power_supply_state()
-> device/qcom/common/healthd/healthd_board_msm.cpp: healthd_board_mode_charger_battery_update()
-> : set_tricolor_led()
#define RED_LED_PATH "/sys/class/leds/red/brightness"
#define GREEN_LED_PATH "/sys/class/leds/green/brightness"
#define BLUE_LED_PATH "/sys/class/leds/blue/brightness"
#define RED_LED_BLINK_PATH "/sys/class/leds/red/blink"
#define GREEN_LED_BLINK_PATH "/sys/class/leds/green/blink"
#define BACKLIGHT_PATH "/sys/class/leds/lcd-backlight/brightness"
struct soc_led_color_mapping soc_leds[3] = {
{15, RED_LED},
{90, RED_LED | GREEN_LED},
{100, GREEN_LED},
};
以上基于高通8996 android7.1代码, 仅供参考
--------------------------------------------
开机充电的部分
1. 充电三色灯控制
1.1 关机充电三色灯控制
相关文件:system\core\healthd\healthd_mode_charger.cpp
当前电量不等于之前电量时,调用handle_power_supply_state()--->set_battery_soc_leds()来控制三色灯,先来看其中用到的全局数组
#define RED_LED_PATH "/sys/class/leds/red/brightness"
#define GREEN_LED_PATH "/sys/class/leds/green/brightness"
#define BLUE_LED_PATH "/sys/class/leds/blue/brightness"
struct led_ctl leds[3] =
{{RED_LED, RED_LED_PATH},
{GREEN_LED, GREEN_LED_PATH},
{BLUE_LED,BLUE_LED_PATH}};
struct soc_led_color_mapping soc_leds[3] ={
{15, RED_LED},
{90, RED_LED | GREEN_LED},
{100, GREEN_LED},
};
高通的设计思路是:
红色:低电量,电量低于15%
蓝色:充电,电量在15%到90%之间
绿色:电量在90%到100%
比如对于/sys/class/leds/chg_red/brightness,设置为0为红色,1为绿色,255也是绿色
/green/brightness,设置为0为关闭绿色,设置为1为打开绿灯
static int set_battery_soc_leds(int soc)
{
int i, color;
static int old_color = 0;
int fd;
char buffer[10];
fd = open("/sys/class/leds/chg_red/brightness", O_RDWR);
snprintf(buffer, sizeof(int), "%d\n", 0);
write(fd, buffer, strlen(buffer));
close(fd);
for (i = 0; i < (int)ARRAY_SIZE(soc_leds); i++) {
if (soc <= soc_leds[i].soc)
break;
}
color = soc_leds[i].color;
if (old_color != color) {
set_tricolor_led(0, old_color);
set_tricolor_led(1, color);
old_color = color;
LOGV("soc = %d, set led color 0x%x\n", soc,soc_leds[i].color);
}
return 0;
}
这是高通默认的设计,但对于我们的硬件设计来说存在一个问题,就是电量>15%的时候,红色和绿色灯都是亮的,为了解决这个问题,且我们关机充电是在电量<95%是红灯,>=95%为绿灯,修改后如下:
struct led_ctl leds[2] =
{{RED_LED, RED_LED_PATH},
{GREEN_LED, GREEN_LED_PATH}};
struct soc_led_color_mapping soc_leds[2] ={
{15, RED_LED},
{95, GREEN_LED},
};
static int set_battery_soc_leds(int soc)
{
int i, color;
static int old_color = 0;
int fd;
char buffer[10];
fd = open("/sys/class/leds/chg_red/brightness", O_RDWR);
snprintf(buffer, sizeof(int), "%d\n", 0);//red on
write(fd, buffer, strlen(buffer));
close(fd);
for (i = 0; i < (int)ARRAY_SIZE(soc_leds); i++) {
if (soc <= soc_leds[i].soc)
break;
}
if(old_color != color) {
if(soc>=soc_leds[1].soc)
{
fd =open("/sys/class/leds/chg_red/brightness", O_RDWR);
snprintf(buffer,sizeof(int), "%d\n", 255);//red off
write(fd,buffer, strlen(buffer));
close(fd);
fd= open("/sys/class/leds/red/brightness", O_RDWR);
snprintf(buffer,sizeof(int), "%d\n", 0);
write(fd,buffer, strlen(buffer));
close(fd);
set_tricolor_led(1,GREEN_LED);
}
else
{
set_tricolor_led(1,RED_LED);
}
old_color = color;
LOGV("soc = %d, set led color0x%x\n", soc, soc_leds[i].color);
}
return 0;
}
1.2 开机充电三色灯控制
frameworks/base/services/core/java/com/android/server/BatteryService.java
public void updateLightsLocked()
/**
* Synchronize on BatteryService.
*/
public void updateLightsLocked() {
final int level = mBatteryProps.batteryLevel;
final int status = mBatteryProps.batteryStatus;
if (level < mLowBatteryWarningLevel) {
if (status ==BatteryManager.BATTERY_STATUS_CHARGING) {
// Solid red when batteryis charging
mBatteryLight.setColor(mBatteryLowARGB);
} else {
// Flash red when batteryis low and not charging
mBatteryLight.setFlashing(mBatteryLowARGB, Light.LIGHT_FLASH_TIMED,
mBatteryLedOn,mBatteryLedOff);
}
} else if (status == BatteryManager.BATTERY_STATUS_CHARGING
|| status ==BatteryManager.BATTERY_STATUS_FULL) {
if (status ==BatteryManager.BATTERY_STATUS_FULL || level >=95) {//kandi change from 99 to95
// Solid green when full orcharging and nearly full
mBatteryLight.setColor(mBatteryFullARGB);
} else {
// Solid orange whencharging and halfway full
mBatteryLight.setColor(mBatteryLowARGB);
}
} else {
// No lights if not charging andnot low
mBatteryLight.turnOff();
}
}
2. 放电三色灯控制
2.1 电量<15%
低电量红色闪烁也是采用上面的updateLightsLocked()来控制的。