Android 8.1 关机充电动画(一)模式选择
system:Android 8.1
platform:RK3326/PX30
uboot
kernel
Android 8.1 关机充电动画(一)模式选择
Android 8.1 关机充电动画(二)Uboot模式
Android 8.1 关机充电动画(三)Android模式
前言
关机充电的动画可以在u-boot或者Android的charger模式工作,这是两个相互独立的部分,RK平台上需要在设备树进行配置。顾名思义u-boot下的charger模式,系统仍然运行在loader下,并未启动内核。
Android的charger模式下,在引导程序运行期间会传递参数给内核,则会启动内核并加载内核模块,同时安卓系统也不会启动,系统最终只工作charger模式。这里简单记录一下,在uboot中都做了哪些工作,根据什么条件选择工作的模式。
配置
设备树要增加节点charge-animation,这个rk的文档里有相应的说明,在配置下面设备树的配置中,我已经加上了注释,对照这个看就行,不过所有属性只适用u-boot下的关机充电,而不适用用Android下的关机充电,这个具体会在后面加以说明。
这里暂时把已经启动内核之后再进入charger的模式称作Android下的关机充电,可能有些不妥,但是先这样区分吧
具体的配置如下;
rockchip,uboot-charge-on = <0>; ,rockchip,android-charge-on = <1>; 这两个属性用于选择后续的程序会进入到哪一种模式工作,后面在代码中会加以区分。
charge-animation {
compatible = "rockchip,uboot-charge";
rockchip,uboot-charge-on = <0>; // 是否在U-Boot进行充电
rockchip,android-charge-on = <1>; // 是否在Android进行充电
rockchip,uboot-exit-charge-level = <5>; // U-Boot充电时,允许开机的最低电量
rockchip,uboot-exit-charge-voltage = <3600>; // U-Boot充电时,允许开机的最低电压
rockchip,screen-on-voltage = <3400>; // U-Boot充电时,允许点亮屏幕的最低电压
rockchip,uboot-low-power-voltage = <3350>; // U-Boot无条件强制进入充电模式的最低电压
rockchip,system-suspend = <0>; // 灭屏时进入trust进行低功耗待机
rockchip,auto-off-screen-interval = <10>;// 亮屏超时后自动灭屏,单位秒。(如果没有这个属性,则默认15s)
rockchip,auto-wakeup-interval = <0>; // 休眠自动唤醒时间,单位秒。(如果值为0或没有这个属性,则禁止休眠自动唤醒)
rockchip,auto-wakeup-screen-invert = <0>; // 休眠自动唤醒的时候,是否让屏幕产生亮/灭效果
status = "okay";
};
代码分析
可以定位到u-boot/drivers/power/charge_animation.c,目前只分析一下函数static int charge_animation_show(struct udevice *dev),具体代码见最后的附录
这个函数会在启动内核之前进行一个简单的检测;
1. Extrem low power charge?
2. Preboot cmd?
3. Valid boot mode?
4. U-Boot charge enabled by dts config?
5. Screen off before charge?
6. Enter charge !
分别是1 检测低电量,2 检测启动命令,3 检测启动模式,4 检测设备树配置,这四项检测如果不符合会直接return,然后无法成功进入6 Enter charge的状态。具体的可以在代码里面慢慢看,至于第五点,不太清楚了。这里先把第四点的部分相关的代码抠出来,如下:
/* charge mode */
pdata->uboot_charge =
dev_read_u32_default(dev, "rockchip,uboot-charge-on", 0);
pdata->android_charge =
dev_read_u32_default(dev, "rockchip,android-charge-on", 0);
/* Enter android charge, set property for kernel */
if (pdata->android_charge) {
env_update("bootargs", "androidboot.mode=charger");
}
/* Not enable U-Boot charge, exit */
if (!pdata->uboot_charge) {
debug("exit charge, due to not enable uboot charge\n");
return 0;
}
可以看到这里有两种情况
uboot_charge如果在设备树里配置为开启,则无法进入Android 关机充电模式了,然后最终程序会进入到while(1)不断循环显示充电动画,检测到相应事件动作之后才会退出充电进入系统,或者掉电关机;android_charge在设备树中设置开启,并且uboot_charge设置为关闭的情况下,会设置内核的启动参数env_update("bootargs", "androidboot.mode=charger"),之后uboot会启动内核,并传参数给内核,告诉他,要进入Android关机充电的模式。
总结
这里篇幅较短,主要分析了在u-boot下charge_animation_show的部分工作流程即如何选择最终充电的模式,下面会简单介绍uboot下关机充电和Android下关机充电的动画定制。
附录
代码可能已经更新请参考u-boot/drivers/power/charge_animation.c
static int charge_animation_show(struct udevice *dev)
{
struct charge_animation_pdata *pdata = dev_get_platdata(dev);
struct charge_animation_priv *priv = dev_get_priv(dev);
const struct charge_image *image = priv->image;
struct udevice *pmic = priv->pmic;
struct udevice *fg = priv->fg;
const char *preboot = env_get("preboot");
int image_num = priv->image_num;
bool ever_lowpower_screen_off = false;
bool screen_on = true;
ulong show_start = 0, charge_start = 0, debug_start = 0;
ulong delta;
ulong ms = 0, sec = 0;
int start_idx = 0, show_idx = -1, old_show_idx = IMAGE_SHOW_RESET;
int soc, voltage, current, key_state;
int i, charging = 1, ret;
int boot_mode;
int first_poll_fg = 1;
/*
* Check sequence:
*
* 1. Extrem low power charge?
* 2. Preboot cmd?
* 3. Valid boot mode?
* 4. U-Boot charge enabled by dts config?
* 5. Screen off before charge?
* 6. Enter charge !
*
*/
if (!fuel_gauge_bat_is_exist(fg)) {
printf("Exit charge: battery is not exist\n");
return 0;
}
/* Extrem low power charge */
ret = charge_extrem_low_power(dev);
if (ret < 0) {
printf("extrem low power charge failed, ret=%d\n", ret);
return ret;
}
/* If there is preboot command, exit */
if (preboot && !strstr(preboot, "dvfs")) {
printf("Exit charge: due to preboot cmd '%s'\n", preboot);
return 0;
}
/* Not valid charge mode, exit */
#ifdef CONFIG_RKIMG_BOOTLOADER
boot_mode = rockchip_get_boot_mode();
if ((boot_mode != BOOT_MODE_CHARGING) &&
(boot_mode != BOOT_MODE_UNDEFINE)) {
printf("Exit charge: due to boot mode\n");
return 0;
}
#endif
/* Not charger online, exit */
charging = fuel_gauge_get_chrg_online(fg);
if (charging <= 0) {
printf("Exit charge: due to charger offline\n");
return 0;
}
/* Enter android charge, set property for kernel */
if (pdata->android_charge) {
env_update("bootargs", "androidboot.mode=charger");
printf("Android charge mode\n");
}
/* Not enable U-Boot charge, exit */
if (!pdata->uboot_charge) {
printf("Exit charge: due to not enable uboot charge\n");
return 0;
}
voltage = fuel_gauge_get_voltage(fg);
if (voltage < 0) {
printf("get voltage failed: %d\n", voltage);
return -EINVAL;
}
/* If low power, turn off screen */
if (voltage <= pdata->screen_on_voltage + 50) {
screen_on = false;
ever_lowpower_screen_off = true;
charge_show_bmp(NULL);
}
/* Auto wakeup */
if (pdata->auto_wakeup_interval) {
printf("Auto wakeup: %dS\n", pdata->auto_wakeup_interval);
autowakeup_timer_init(dev, pdata->auto_wakeup_interval);
}
/* Give a message warning when CONFIG_IRQ is not enabled */
#ifdef CONFIG_IRQ
printf("Enter U-Boot charging mode\n");
#else
printf("Enter U-Boot charging mode(without IRQ)\n");
#endif
charge_start = get_timer(0);
delta = get_timer(0);
/* Charging ! */
while (1) {
/*
* At the most time, fuel gauge is usually a i2c device, we
* should avoid read/write all the time. We had better set
* poll seconds to update fuel gauge info.
*/
if (!first_poll_fg && get_timer(delta) < FUEL_GAUGE_POLL_MS)
goto show_images;
delta = get_timer(0);
debug("step1 (%d)... \n", screen_on);
/*
* Most fuel gauge is I2C interface, it shouldn't be interrupted
* during tansfer. The power key event depends on interrupt, so
* so we should disable local irq when update fuel gauge.
*/
local_irq_disable();
/* Step1: Is charging now ? */
charging = fuel_gauge_get_chrg_online(fg);
if (charging <= 0) {
printf("Not charging, online=%d. Shutdown...\n",
charging);
/* wait uart flush before shutdown */
mdelay(5);
/* PMIC shutdown */
pmic_shutdown(pmic);
printf("Cpu should never reach here, shutdown failed !\n");
continue;
}
debug("step2 (%d)... show_idx=%d\n", screen_on, show_idx);
/* Step2: get soc and voltage */
soc = fuel_gauge_get_soc(fg);
if (soc < 0 || soc > 100) {
printf("get soc failed: %d\n", soc);
continue;
}
voltage = fuel_gauge_get_voltage(fg);
if (voltage < 0) {
printf("get voltage failed: %d\n", voltage);
continue;
}
current = fuel_gauge_get_current(fg);
if (current == -ENOSYS) {
printf("get current failed: %d\n", current);
continue;
}
first_poll_fg = 0;
local_irq_enable();
show_images:
/*
* Just for debug, otherwise there will be nothing output which
* is not good to know what happen.
*/
if (!debug_start)
debug_start = get_timer(0);
if (get_timer(debug_start) > 20000) {
debug_start = get_timer(0);
printf("[%8ld]: soc=%d%%, vol=%dmv, c=%dma, online=%d, screen_on=%d\n",
get_timer(0)/1000, soc, voltage,
current, charging, screen_on);
}
/*
* If ever lowpower screen off, force screen_on=false, which
* means key event can't modify screen_on, only voltage higher
* then threshold can update screen_on=true;
*/
if (ever_lowpower_screen_off)
screen_on = false;
/*
* Auto turn on screen when voltage higher than Vol screen on.
* 'ever_lowpower_screen_off' means enter while loop with
* screen off.
*/
if ((ever_lowpower_screen_off) &&
(voltage > pdata->screen_on_voltage)) {
ever_lowpower_screen_off = false;
screen_on = true;
show_idx = IMAGE_SHOW_RESET;
}
/*
* IMAGE_SHOW_RESET means show_idx show be update by start_idx.
* When short key pressed event trigged, we will set show_idx
* as IMAGE_SHOW_RESET which updates images index from start_idx
* that calculate by current soc.
*/
if (show_idx == IMAGE_SHOW_RESET) {
for (i = 0; i < image_num - 2; i++) {
/* Find out which image we start to show */
if ((soc >= image[i].soc) &&
(soc < image[i + 1].soc)) {
start_idx = i;
break;
}
if (soc >= 100) {
start_idx = image_num - 2;
break;
}
}
debug("%s: show_idx=%d, screen_on=%d\n",
__func__, show_idx, screen_on);
/* Mark start index and start time */
show_idx = start_idx;
show_start = get_timer(0);
}
debug("step3 (%d)... show_idx=%d\n", screen_on, show_idx);
/* Step3: show images */
if (screen_on) {
/* Don't call 'charge_show_bmp' unless image changed */
if (old_show_idx != show_idx) {
old_show_idx = show_idx;
debug("SHOW: %s\n", image[show_idx].name);
charge_show_bmp(image[show_idx].name);
}
/* Re calculate timeout to off screen */
if (priv->auto_screen_off_timeout == 0)
priv->auto_screen_off_timeout = get_timer(0);
} else {
priv->auto_screen_off_timeout = 0;
system_suspend_enter(pdata);
}
mdelay(5);
/* Every image shows period */
if (get_timer(show_start) > image[show_idx].period) {
show_start = get_timer(0);
/* Update to next image */
show_idx++;
if (show_idx > (image_num - 2))
show_idx = IMAGE_SHOW_RESET;
}
debug("step4 (%d)... \n", screen_on);
/*
* Step4: check key event.
*
* Short key event: turn on/off screen;
* Long key event: show logo and boot system or still charging.
*/
key_state = check_key_press(dev);
if (key_state == KEY_PRESS_DOWN) {
old_show_idx = IMAGE_SHOW_RESET;
/* NULL means show nothing, ie. turn off screen */
if (screen_on)
charge_show_bmp(NULL);
/*
* Clear current image index, and show image
* from start_idx
*/
show_idx = IMAGE_SHOW_RESET;
/*
* We turn off screen by charge_show_bmp(NULL), so we
* should tell while loop to stop show images any more.
*
* If screen_on=false, means this short key pressed
* event turn on the screen and we need show images.
*
* If screen_on=true, means this short key pressed
* event turn off the screen and we never show images.
*/
if (screen_on)
screen_on = false;
else
screen_on = true;
} else if (key_state == KEY_PRESS_LONG_DOWN) {
/* Only long pressed while screen off needs screen_on true */
if (!screen_on)
screen_on = true;
/* Is able to boot now ? */
if (soc < pdata->exit_charge_level) {
printf("soc=%d%%, threshold soc=%d%%\n",
soc, pdata->exit_charge_level);
printf("Low power, unable to boot, charging...\n");
show_idx = image_num - 1;
continue;
}
if (voltage < pdata->exit_charge_voltage) {
printf("voltage=%dmv, threshold voltage=%dmv\n",
voltage, pdata->exit_charge_voltage);
printf("Low power, unable to boot, charging...\n");
show_idx = image_num - 1;
continue;
}
/* Success exit charging */
printf("Exit charge animation...\n");
charge_show_logo();
break;
} else {
/* Do nothing */
}
debug("step5 (%d)... \n", screen_on);
/* Step5: Exit by ctrl+c */
if (ctrlc()) {
if (voltage >= pdata->screen_on_voltage)
charge_show_logo();
printf("Exit charge, due to ctrl+c\n");
break;
}
}
if (pdata->auto_wakeup_interval)
autowakeup_timer_uninit();
ms = get_timer(charge_start);
if (ms >= 1000) {
sec = ms / 1000;
ms = ms % 1000;
}
printf("charging time total: %lu.%lus, soc=%d%%, vol=%dmv\n",
sec, ms, soc, voltage);
return 0;
}
Android 8.1 关机充电动画(一)模式选择的更多相关文章
- Android 8.1 关机充电动画(三)Android模式
system:Android 8.1 platform:RK3326/PX30 uboot kernel system/core/healthd Android 8.1 关机充电动画(一)模式选择 A ...
- Android 8.1 关机充电动画(二)Uboot模式
system:Android 8.1 platform:RK3326/PX30 uboot kernel Android 8.1 关机充电动画(一)模式选择 Android 8.1 关机充电动画(二) ...
- Android MTK6580 客制化关机充电动画
1.客制化关机充电图片 vendor/mediatek/proprietary/bootable/bootloader/lk/dev/logo/xxx 找到对应分辨率替换 2.调整显示图片位置.大小 ...
- Android9.0 MTK 平板横屏方案修改(强制app横屏 + 开机logo/动画+关机充电横屏 + RecoveryUI 横屏)
文章较长建议先收藏再看 拆解步骤 1.app 强制横屏显示,无视 android:screenOrientation="portrait" 属性 2.屏幕触摸坐标修改为横屏 3.开 ...
- 【转】android 电池(二):android关机充电流程、充电画面显示
关键词:android 电池关机充电 androidboot.mode charger关机充电 充电画面显示 平台信息:内核:linux2.6/linux3.0系统:android/android4. ...
- android 关机充电流程
点击打开链接 0.主要流程 usb插入通过传递cmdline给init解析从而启动充电进程 1. LK lk\app\aboot\aboot.c update_cmdline ---------- i ...
- android 电池(二):android关机充电流程、充电画面显示【转】
本文转载自:http://blog.csdn.net/xubin341719/article/details/8498580 上一篇我们讲了锂电池的充放电的流程和电池的一些特性,这一节我们重点说一下a ...
- android关机充电
1.关机充电其实是进入adb shell很快的方式! 2.手机关机时候插入USB,手机将进入关机充电模式,那么这个模式究竟是怎么进行的,这里分析如下! (1)uboot:这里代码大概浏览了一下:u-b ...
- Android 电池关机充电
android 电池(一):锂电池基本原理篇 android 电池(二):android关机充电流程.充电画面显示 android 电池(三):android电池系统 android电池(四):电池 ...
随机推荐
- Daily Scrum 1/6/2015
Process: Zhaoyang: Complete the speech API test and do some UI upgrade. Yandong: Help zhaoyang to do ...
- Python程序设计实验报告一:熟悉IDLE和在线编程平台
安徽工程大学 Python程序设计 实验报告 班级 物流191 姓名 崔攀 学号3190505136 成绩_____ 日期 2020.3.8 指导老师 ...
- jarvisoj MISC 取证2
打开之后一个文件和一个镜像 TrueCrypt....记住他了,再看一眼那个文件,好的,TrueCrypt加密..找密码 把Truecrypt.exe直接dump下来,用efdd解密就行了
- Laravel 5.8 RCE 分析
原帖地址 : https://xz.aliyun.com/t/6059 Laravel 代码审计 环境搭建 composer create-project --prefer-dist laravel/ ...
- 推荐一个小而美的Python代码格式化工具
代码可读性是评判代码质量的标准之一,有一个衡量代码质量的标准是 Martin 提出的 “WFT” 定律,即每分钟爆出 “WTF” 的次数.你在读别人代码或者做 Code Review 的时候有没有 “ ...
- tp5命名空间补充
1.非限定名称访问方式: 直接访问当前的空间和元素 2.限定名称命名空间: 路径\方法(); 相当于相对路径 以当前的命名空间为起点,去找路径上的方法 3.完全限定名称访问方式:\路径\方法(); ...
- MySQL数据库缓存操作
安装: 启动的话: -d:以后台的方式进行: -l:选择监听指定的ip服务地址:-m:给他分配多大的内存:-p:端口号默认的端口为11211的服务端口: 另一个: 安装:telnet 这个可以用来测试 ...
- 2019-2020-1 20199303 《Linux内核原理与分析》 第十一周作业
缓冲区溢出漏洞实验 安装一些用于编译C程序的32位软件包 sudo apt-get install -y lib32z1 libc6-dev-i386 sudo apt-get install -y ...
- JAVA企业级应用TOMCAT实战(三)
JVM优化涉及到两大方面我个人的理解 .如何分配JVM的内存空间 .我应该使用什么垃圾回收器 JVM产生的垃圾需要回收.回收有不同的回收器. JVM的调优需要了解各个垃圾回收机制的原理. 终极目标:降 ...
- eclipse自动补全导致变量会跟上String后缀的问题解决
https://blog.csdn.net/feinifi/article/details/103665860