1. 关机充电图标修改项目概述
在Android系统开发中,关机充电界面是一个特殊的系统组件,它负责在设备完全关机状态下显示充电状态和电量信息。这个看似简单的功能实际上涉及到底层驱动、图形显示、电源管理等多个子系统的协同工作。
作为一名有多年Android系统开发经验的工程师,我最近完成了一个关机充电图标修改项目。这个项目的核心目标是替换默认的充电图标和动画效果,同时调整电量显示的位置和样式。下面我将详细分享这个项目的技术实现细节和注意事项。
2. 关机充电系统架构解析
2.1 关机充电流程分析
关机充电流程主要分为以下几个阶段:
- 插入充电器后,PMIC(电源管理IC)检测到电源输入
- Bootloader阶段显示初始充电logo
- 进入charger模式,加载充电动画
- 持续显示充电状态直至开机或拔掉充电器
关键代码路径:
vendor/mediatek/proprietary/external/charger/ vendor/mediatek/proprietary/external/libshowlogo/2.2 充电动画实现原理
充电动画主要通过以下核心组件实现:
charging_control():主控制函数,负责创建和管理充电相关线程draw_thread_routine():动画绘制线程,控制动画帧率bootlogo_show_charging():充电状态显示入口fill_animation_battery_by_ver():根据版本选择不同动画实现
3. 图标修改具体实现步骤
3.1 图片资源准备与替换
关机充电界面使用的图片资源主要包括:
- 数字图片(0-9):
fhd_num_0.bmp~fhd_num_9.bmp - 百分号图片:
fhd_mun_percent.bmp - 背景图片:
fhd_bat_bg.bmp - 动画帧图片:
fhd_bat_animation_01.bmp~fhd_bat_animation_10.bmp - 特殊状态图片:低电量、过压等警告图片
替换步骤:
- 确认设备分辨率(如1080x1920)
- 准备相同尺寸的BMP格式图片
- 替换
device/[vendor]/[project]/logo/目录下对应文件
注意:图片必须使用24位BMP格式,且命名必须与原始文件完全一致
3.2 图片打包脚本修改
图片资源通过update_logo.sh脚本打包成RAW格式:
#!/bin/bash ${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp0.raw ${logo_path}/$p/"${boot_logo}_uboot".bmp ${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp1.raw ${logo_path}/$p/"${boot_logo}_battery".bmp ... ${product_path}/vendor/jrdcom/build/jrdtools/zpipe -l 9 ${output_path}/"${p}".raw ${output_path}/temp*.raw如果新增图片(如无电量状态图),需要在脚本中添加对应的转换命令。
3.3 显示位置调整
显示位置定义在cust_display.h中:
// 电量数字位置 #define NUMBER_LEFT (512) #define NUMBER_TOP (1097) #define NUMBER_RIGHT (540) #define NUMBER_BOTTOM (1137) // 百分号位置 #define PERCENT_LEFT (568) #define PERCENT_TOP (1110) #define PERCENT_RIGHT (592) #define PERCENT_BOTTOM (1137) // 电池图标位置 #define CAPACITY_LEFT (387) #define CAPACITY_TOP (802) #define CAPACITY_RIGHT (691) #define CAPACITY_BOTTOM (1292)修改这些坐标值可以调整各元素的显示位置。
4. 充电动画效果定制
4.1 动画版本控制
系统支持多种动画风格,通过show_animationm_ver变量控制:
void sync_anim_version() { #ifdef ANIMATION_NEW show_animationm_ver = VERION_NEW_ANIMATION; #else show_animationm_ver = VERION_OLD_ANIMATION; #endif }4.2 旧版动画修改
旧版动画(4格滚动效果)的核心函数:
void fill_animation_battery_old(int capacity, void *fill_addr, void * dec_logo_addr, void * logo_addr, LCM_SCREEN_T phical_screen) { // 计算电量格数 capacity_grids = (capacity * (ANIM_V0_REGIONS)) / 100; // 动画索引更新 if (version0_charging_index < capacity_grids * 2) version0_charging_index = capacity_grids * 2; // 绘制背景 fill_animation_logo(ANIM_V0_BACKGROUND_INDEX, fill_addr, dec_logo_addr, logo_addr,phical_screen); // 绘制电量格 fill_animation_prog_bar(rect_bar, BAR_OCCUPIED_COLOR, 0, version0_charging_index/2, fill_addr, phical_screen); }修改建议:
- 调整
ANIM_V0_REGIONS改变电量格数 - 修改
BAR_OCCUPIED_COLOR改变电量颜色 - 调整
ANIM_V0_SPACE_AFTER_REGION改变格子间距
4.3 新版动画修改
新版动画(波浪效果)的核心函数:
void fill_animation_battery_new(int capacity, void *fill_addr, void * dec_logo_addr, void * logo_addr, LCM_SCREEN_T phical_screen) { if (capacity >= 100) { // 显示100%电量图 fill_animation_logo(FULL_BATTERY_INDEX, fill_addr, dec_logo_addr, logo_addr,phical_screen); } else if (capacity < 10) { // 低电量动画 fill_animation_logo(LOW_BAT_ANIM_START_0 + charging_low_index, fill_addr, dec_logo_addr, logo_addr,phical_screen); } else { // 正常充电动画 fill_animation_logo(ANIM_V1_BACKGROUND_INDEX, fill_addr, dec_logo_addr, logo_addr,phical_screen); fill_animation_line(ANIM_LINE_INDEX, capacity_grids, fill_addr, logo_addr, phical_screen); } }5. 常见问题与解决方案
5.1 图片替换无效
可能原因:
- 图片未放入正确的logo目录
- 图片格式不正确(必须为24位BMP)
- 未重新编译生成logo.bin
解决方案:
- 确认
ProjectConfig.mk中的BOOT_LOGO设置 - 使用
file命令检查图片格式 - 执行
make bootimage重新生成boot镜像
5.2 动画显示异常
可能表现:
- 动画卡顿
- 显示位置偏移
- 颜色异常
调试方法:
- 检查
draw_with_interval()中的时间参数:usleep(interval_msec*1000); // 调整此值改变动画速度 - 确认
cust_display.h中的坐标值 - 检查
BAR_OCCUPIED_COLOR等颜色定义
5.3 添加新状态图片
如需添加无电量状态图:
- 添加图片到logo目录
- 在
update_logo.sh中添加转换命令 - 在
cust_display.h中定义新图片索引:#define SHOW_NO_POWER 34 - 在显示逻辑中添加判断:
if(capacity <= 0) { fill_animation_logo(SHOW_NO_POWER, fill_addr, dec_logo_addr, logo_addr,phical_screen); }
6. 优化建议与经验分享
6.1 性能优化
- 减少动画图片数量(但不少于10帧)
- 适当增大
usleep间隔降低CPU占用 - 使用硬件加速绘制(如通过FBIOBLANK控制)
6.2 调试技巧
- 增加日志输出:
KPOC_LOGI("[%s] capacity=%d", __FUNCTION__, capacity); - 使用
adb shell dumpsys battery查看实时电量 - 通过
proc/last_kmsg分析充电流程异常
6.3 兼容性考虑
- 适配不同分辨率(FHD/WQHD/HD等)
- 处理横竖屏切换
- 考虑深色/浅色模式
通过这个项目,我深刻体会到系统级UI修改需要考虑的方方面面。与应用层开发不同,系统组件的修改需要更全面地考虑性能、兼容性和稳定性问题。希望这些经验对从事类似工作的开发者有所帮助。