关机充电动画:流程与定制

关机充电动画:流程与定制

基于MTK平台Android 11分析

生成logo.bin

关机充电动画是由一系列的bmp图片组成的,这些图片资源存在于vendor/mediatek/proprietary/bootable/bootloader/lk/dev/logo目录下(当然不仅保护关机充电动画,还包括开机logo)。根据设备屏幕的不同,分别制作了适合不同分辨率的图片。这些图片在编译过程中会被制作成logo.bin文件刷入设备。

该目录下,存在一个子目录tool,存放了用于格式转换及压缩打包的工具。还存在名为rules.mk的文件,该文件定义了生成logo.bin文件的规则。

请添加图片描述

vendor/mediatek/proprietary/bootable/bootloader/lk/scripts下,存放了用于制作logo.bin的工具。

请添加图片描述

下面先来看一下logo.bin具体是怎么制作的。

vendor/mediatek/proprietary/bootable/bootloader/lk/dev/logo/rules.mk

LOCAL_DIR := $(GET_LOCAL_DIR)
BOOT_LOGO_DIR := $(LOCAL_DIR)#fix no boot_logo config
#LOCAL_CFLAGS += -DBOOT_LOGO=wvgaifeq ($(strip $(BOOT_LOGO)),)BOOT_LOGO = fwvga
endififeq ($(strip $(MTK_LK_CAMERA_SUPPORT)), yes)BOOT_LOGO = fhd
endif$(info BOOT_LOGO = $(BOOT_LOGO))
$(info lk/logo/dir=$(LOCAL_DIR),builddir=$(BUILDDIR))# 定义工具的位置
ifeq ($(HOST_OS),darwin)
BMP_TO_RAW := $(BOOT_LOGO_DIR)/tool/bmp_to_raw.darwin
ZPIPE := $(BOOT_LOGO_DIR)/tool/zpipe.darwin
MKIMG := $(LOCAL_DIR)/../../scripts/mkimage.darwin
else
BMP_TO_RAW := $(BOOT_LOGO_DIR)/tool/bmp_to_raw
ZPIPE := $(BOOT_LOGO_DIR)/tool/zpipe
MKIMG := $(LOCAL_DIR)/../../scripts/mkimage
endif
IMG_HDR_CFG := $(LOCAL_DIR)/img_hdr_logo.cfgEMPTY :=
UNDER_LINE := _
TEMP := $(strip $(subst $(UNDER_LINE), $(EMPTY), $(BOOT_LOGO)))
COUNT := $(words $(TEMP))
BASE_LOGO := $(word $(COUNT),$(TEMP))
EXIST := $(shell if [ -e $(BOOT_LOGO_DIR)/$(BASE_LOGO) ]; then echo "exist"; else echo "noexist"; fi;)
ifeq ($(EXIST), "noexist")BASE_LOGO := $(BOOT_LOGO)
endif# 是否支持快充
SUPPORT_PUMP_EXPRESS = no
ifeq ($(strip $(MTK_PUMP_EXPRESS_SUPPORT)), yes)SUPPORT_PUMP_EXPRESS = yes
elseifeq ($(strip $(MTK_PUMP_EXPRESS_PLUS_SUPPORT)), yes)SUPPORT_PUMP_EXPRESS = yesendif
endif# 打包后的文件
BOOT_LOGO_RESOURCE := $(BUILDDIR)/$(BOOT_LOGO_DIR)/boot_logo.raw
# 产物名
LOGO_IMAGE := $(BUILDDIR)/logo.bindefine generate_logo_executableifneq ($(strip $(MACH_TYPE)), 2701)
ifneq ($(strip $(MTK_ALPS_BOX_SUPPORT)), yes)
# 资源文件列表,有顺序,索引值从0开始
RESOURCE_OBJ_LIST +=   \$(BOOT_LOGO_DIR)/$(1)/$(1)_uboot.raw  \$(BOOT_LOGO_DIR)/$(1)/$(1)_battery.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_low_battery.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_charger_ov.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_num_0.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_num_1.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_num_2.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_num_3.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_num_4.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_num_5.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_num_6.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_num_7.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_num_8.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_num_9.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_num_percent.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_bat_animation_01.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_bat_animation_02.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_bat_animation_03.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_bat_animation_04.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_bat_animation_05.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_bat_animation_06.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_bat_animation_07.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_bat_animation_08.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_bat_animation_09.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_bat_animation_10.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_bat_10_01.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_bat_10_02.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_bat_10_03.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_bat_10_04.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_bat_10_05.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_bat_10_06.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_bat_10_07.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_bat_10_08.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_bat_10_09.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_bat_10_10.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_bat_bg.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_bat_img.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_bat_100.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_kernel.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_low_battery01.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_low_battery02.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_low_battery_remind.raw
endif
endif# 如果支持快充
ifeq ($(strip $(SUPPORT_PUMP_EXPRESS)), yes)
RESOURCE_OBJ_LIST +=   \$(BOOT_LOGO_DIR)/$(1)/$(1)_fast_charging_100.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_fast_charging_ani-01.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_fast_charging_ani-02.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_fast_charging_ani-03.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_fast_charging_ani-04.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_fast_charging_ani-05.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_fast_charging_ani-06.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_fast_charging_00.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_fast_charging_01.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_fast_charging_02.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_fast_charging_03.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_fast_charging_04.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_fast_charging_05.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_fast_charging_06.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_fast_charging_07.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_fast_charging_08.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_fast_charging_09.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_fast_charging_percent.raw
endif# 如果支持无线充电
ifeq ($(strip $(MTK_WIRELESS_CHARGER_SUPPORT)), yes)
RESOURCE_OBJ_LIST +=   \$(BOOT_LOGO_DIR)/$(1)/$(1)_wireless_num_00.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_wireless_num_01.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_wireless_num_02.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_wireless_num_03.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_wireless_num_04.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_wireless_num_05.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_wireless_num_06.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_wireless_num_07.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_wireless_num_08.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_wireless_num_09.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_wireless_num_percent.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_wireless_bat_10_0.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_wireless_bat_10_1.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_wireless_bat_10_2.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_wireless_bat_10_3.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_wireless_bat_30_0.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_wireless_bat_30_1.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_wireless_bat_30_2.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_wireless_bat_30_3.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_wireless_bat_60_0.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_wireless_bat_60_1.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_wireless_bat_60_2.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_wireless_bat_60_3.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_wireless_bat_90_0.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_wireless_bat_90_1.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_wireless_bat_90_2.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_wireless_bat_90_3.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_wireless_bat_0.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_wireless_bat_100.raw
endifendef$(foreach BASE_LOGO,$(BOOT_LOGO),$(eval $(call generate_logo_executable,$(BASE_LOGO))))GENERATED += \$(BOOT_LOGO_RESOURCE) \$(LOGO_IMAGE) \$(addprefix $(BUILDDIR)/,$(RESOURCE_OBJ_LIST))# 目标
all:: $(LOGO_IMAGE)#logo.bin具体的的制作命令
$(LOGO_IMAGE):$(MKIMG) $(BOOT_LOGO_RESOURCE)@echo "MKING $(LOGO_IMAGE) start"@echo $(MKIMG)@echo $(BOOT_LOGO_RESOURCE)@echo $(LOGO_IMAGE)$(MKIMG) $(BOOT_LOGO_RESOURCE) $(IMG_HDR_CFG) > $(LOGO_IMAGE)# 压缩打包
$(BOOT_LOGO_RESOURCE): $(addprefix $(BUILDDIR)/,$(RESOURCE_OBJ_LIST)) $(ZPIPE)@$(MKDIR)@echo "zpiping "$(ZPIPE) -l 9 $@ $(addprefix $(BUILDDIR)/,$(RESOURCE_OBJ_LIST))# 格式转换
$(BUILDDIR)/%.raw: %.bmp $(BMP_TO_RAW)@$(MKDIR)@echo "Compiling_BMP_TO_RAW $<"$(BMP_TO_RAW) $@ $<

从编译Log中可以看到更详细过程:

  • 将bmp图像格式转换成raw格式

请添加图片描述

  • 压缩raw文件,最终打包成boot_logo.raw文件

请添加图片描述

  • 生成logo.bin镜像

请添加图片描述

实际刷入机器的并不是这个logo.bin,还需要签名,形成logo-verified.bin

请添加图片描述

充电动画main()函数

充电动画的入口函数,由init进程启动。负责处理充电动画和充电期间的按键控制。

/vendor/mediatek/proprietary/external/charger/main.cpp

#include <sys/resource.h>
#include "main.h"// add prefer power and backlight keys in below arrays.
int pwrkeys[] = {KEY_POWER, KEY_END};void exit_charger(int reason)	//退出充电的几种情况
{KPOC_LOGI("exit_charger: %d \n", reason);switch(reason) {case EXIT_ALARM_BOOT:case EXIT_POWER_UP:case EXIT_REBOOT_UBOOT:reboot(RB_AUTOBOOT);break;case EXIT_CHARGING_MODE:case EXIT_ERROR_SHUTDOWN:case EXIT_NORMAL_SHUTDOWN:default:reboot(RB_POWER_OFF);break;}
}int main(__attribute__((unused))int argc, __attribute__((unused))char *argv[])
{set_draw_anim_mode(1);	//设置充电动画绘制模式(DRAW_ANIM_MODE_FB)。pthread_mutex_init(&lights_mutex, NULL); //互斥锁,与灯光控制相关。setpriority(PRIO_PROCESS, 0, -20); //设置了进程的优先级。FILE *oom_adj = fopen("/proc/self/oom_score_adj", "w");if (oom_adj) {if (fputs("-17", oom_adj) == EOF) {KPOC_LOGI("fputs error\n");}fclose(oom_adj);}health_service_init();	//初始化health服务,跟电池健康、充电状态有关。light_init();	//灯光初始化。//stop_backlight();KPOC_LOGI("stop_backlight 1\n");bootlogo_init();	//充电动画初始化。charging_control();	//充电的相关控制逻辑。unsigned int i;for (i=0; i< ARRAY_SIZE(pwrkeys); i++)KPOC_LOGI("pwrkeys[%d]:%d\n",i,pwrkeys[i]);key_control(pwrkeys, ARRAY_SIZE(pwrkeys)); //will loop inside	//充电期间的按键处理。return 0;
}

set_draw_anim_mode()函数

根据running_mode设置动画绘制模式。最终会修改vendor/mediatek/proprietary/external/libshowlogo/charging_animation.cpp中的全局变量
draw_anim_mode,由于running_mode被写死为1,所以动画绘制模式永远为DRAW_ANIM_MODE_FB

vendor/mediatek/proprietary/external/charger/bootlogo.cpp

/**  Set charging animation drawing method according to running mode:*  running IPO : using surface flinger , DRAW_ANIM_MODE_SURFACE *  running KPOC: using framebuffer     , DRAW_ANIM_MODE_FB*///传入的running_mode为1
void set_draw_anim_mode(int running_mode)
{int draw_anim_mode = DRAW_ANIM_MODE_SURFACE;KPOC_LOGD("[ChargingAnimation %s %d]kpoc flag == 1 ? : running_mode = %d \n ",__FUNCTION__,__LINE__ ,running_mode);if(running_mode == 1) {draw_anim_mode = DRAW_ANIM_MODE_FB;KPOC_LOGD("[ChargingAnimation %s %d]under kernel power off charging mode, use fb to draw animation!",__FUNCTION__,__LINE__ );} else {draw_anim_mode = DRAW_ANIM_MODE_SURFACE; }        set_draw_mode(draw_anim_mode);
//    set_draw_mode(DRAW_ANIM_MODE_SURFACE);
}

/home/mh/mediatek/proprietary/external/libshowlogo/charging_animation.cpp

...
static int draw_anim_mode = DRAW_ANIM_MODE_SURFACE;
.../** Set charging animation drawing method**/
void set_draw_mode(int draw_mode)
{if (MTK_LOG_ENABLE == 1) {SLOGD("[libshowlogo: %s %d]0 --use framebuffer, 1--use surface flinger ,draw_anim_mode =  :%d",__FUNCTION__,__LINE__ ,draw_mode);}if ((draw_mode != (DRAW_ANIM_MODE_FB)) && (draw_mode != (DRAW_ANIM_MODE_SURFACE))) {draw_anim_mode = DRAW_ANIM_MODE_SURFACE;} else {draw_anim_mode = draw_mode;}
}

bootlogo_init()函数

bootlogo_init()函数主要做了两件事情:

  1. 设置充电动画的样式
  2. 充电动画的初始化

/mediatek/proprietary/external/charger/bootlogo.cpp

/** Init charging animation version , drawing method and other parameters**/
void bootlogo_init()
{KPOC_LOGI("[ChargingAnimation: %s %d]\n",__FUNCTION__,__LINE__);sync_anim_version();anim_init();
}

sync_anim_version()函数

sync_anim_version()函数用于设置充电动画的样式。

/mediatek/proprietary/external/charger/bootlogo.cpp

/** Read charging animation feature option, and set charging animation version** version 0: show 4 recatangle growing animation without battery number * version 1: show wave animation with  battery number                   */
//这里注释少写一个version 2,是无线充电的样式。
void sync_anim_version()
{KPOC_LOGI("[ChargingAnimation: %s %d]\n",__FUNCTION__,__LINE__);if (is_wireless_charging()){set_anim_version(VERION_WIRELESS_CHARGING_ANIMATION);     } else {
#ifdef ANIMATION_NEWset_anim_version(VERION_NEW_ANIMATION);       
#elseset_anim_version(VERION_OLD_ANIMATION);KPOC_LOGI("[ChargingAnimation %s %d]not define ANIMATION_NEW:show old animation \n",__FUNCTION__,__LINE__); 
#endif }
}

vendor/mediatek/proprietary/bootable/bootloader/lk/lib/libshowlogo/cust_display.h

/* The option of new charging animation */
#define ANIMATION_NEW

vendor/mediatek/proprietary/external/charger/bootlogo.cpp

#define VERION_OLD_ANIMATION 0
#define VERION_NEW_ANIMATION 1
#define VERION_WIRELESS_CHARGING_ANIMATION  2

anim_init()函数

该函数主要有4个作用:

  1. 通过"ro.charge_animation.rotation"属性获取充电动画的方向。
  2. 初始化充电动画的UI参数。
  3. 加载充电动画资源到内存。
  4. 初始化framebuffer。

vendor/mediatek/proprietary/external/libshowlogo/charging_animation.cpp

/** Charging animation init**/void anim_init()
{    charge_animation_rotation = getValue("ro.charge_animation.rotation", "");init_charging_animation_ui_dimension();if (MTK_LOG_ENABLE == 1) {SLOGD("[libshowlogo: %s %d]\n",__FUNCTION__,__LINE__);}anim_logo_init();if (draw_anim_mode == (DRAW_ANIM_MODE_FB)) {anim_fb_init();} else {anim_surface_init();}
}
init_charging_animation_ui_dimension()函数

根据屏幕尺寸的不同,初始化charging_anim_ui_dimension结构体,其定义了充电动画界面的UI元素尺寸。

该结构体的定义在vendor/mediatek/proprietary/external/libshowlogo/show_animation_common.

struct charging_anim_ui_dimension {int cap_left;int cap_top;int cap_right;int cap_bottom;int num_left;int num_top;int num_right;int num_bottom;int percent_left;int percent_top;int percent_right;int percent_bottom;int top_anim_left;int top_anim_top;int top_anim_right;int top_anim_bottom;int bar_left;int bar_top;int bar_right;int bar_bottom;int num_width_fast;int num_height_fast;int top_margin_fast;
}  ;
struct charging_anim_ui_dimension charg_anim_ui_dimen ;
/** Fill resolution structure based on lcd size**/
void init_charging_animation_ui_dimension() {int lcm_width, lcm_height;struct fb_var_screeninfo vinfo;display_fd = open("/dev/graphics/fb0", O_RDONLY);if (display_fd < 0) {SLOGD("[show_animation_common: %s %d]open mtkfb fail...\n",__FUNCTION__,__LINE__);}if (ioctl(display_fd, FBIOGET_VSCREENINFO, &vinfo) < 0) {close(display_fd);SLOGD("[show_animation_common: %s %d]ioctl FBIOGET_VSCREENINFO failed\n",__FUNCTION__,__LINE__);}close(display_fd);lcm_width = vinfo.xres;	//实际的横向分辨率lcm_height = vinfo.yres;  //实际的纵向分辨率// int rotation = getRotation();if (MTK_LOG_ENABLE == 1) {SLOGD("[libshowlogo: %s %d]rotation = %d\n",__FUNCTION__,__LINE__, charge_animation_rotation);}if ((270 == charge_animation_rotation)|| (90 == charge_animation_rotation)){lcm_width = vinfo.yres;lcm_height = vinfo.xres;}SLOGD("[show_animation_common: %s %d] lcm_width and lcm_height= %d , %d \n",__FUNCTION__,__LINE__,lcm_width,lcm_height);if((lcm_width == 1080) && (lcm_height == 1920)) { // Special handling for FHDSLOGD("[show_animation_common: %s %d]Inside 1080*1920 \n",__FUNCTION__,__LINE__);charg_anim_ui_dimen.cap_left =387;charg_anim_ui_dimen.cap_right= 691;charg_anim_ui_dimen.num_left=395;charg_anim_ui_dimen.num_right=395+84;charg_anim_ui_dimen.percent_left=395+84+84;charg_anim_ui_dimen.percent_right=395+84+84+108;charg_anim_ui_dimen.top_anim_left=387;charg_anim_ui_dimen.top_anim_right=691;charg_anim_ui_dimen.bar_left=470;charg_anim_ui_dimen.bar_top=356;charg_anim_ui_dimen.bar_right=610;charg_anim_ui_dimen.bar_bottom=678;charg_anim_ui_dimen.cap_top= 802;charg_anim_ui_dimen.cap_bottom= 1292 ;charg_anim_ui_dimen.num_top=479;charg_anim_ui_dimen.num_bottom=600;charg_anim_ui_dimen.percent_top=479;charg_anim_ui_dimen.percent_bottom=600;charg_anim_ui_dimen.top_anim_top=100;charg_anim_ui_dimen.top_anim_bottom=152;charg_anim_ui_dimen.num_width_fast = 108;charg_anim_ui_dimen.num_height_fast = 192;charg_anim_ui_dimen.top_margin_fast = 240;}else if((lcm_width == 1080) && (lcm_height == 2160)) { // Special handling for FHD+SLOGD("[show_animation_common: %s %d]Inside 1080*2160 \n",__FUNCTION__,__LINE__);charg_anim_ui_dimen.cap_left =387;charg_anim_ui_dimen.cap_right= 691;charg_anim_ui_dimen.num_left=395;charg_anim_ui_dimen.num_right=395+84;charg_anim_ui_dimen.percent_left=395+84+84;charg_anim_ui_dimen.percent_right=395+84+84+108;charg_anim_ui_dimen.top_anim_left=387;charg_anim_ui_dimen.top_anim_right=691;charg_anim_ui_dimen.bar_left=470;charg_anim_ui_dimen.bar_top=356;charg_anim_ui_dimen.bar_right=610;charg_anim_ui_dimen.bar_bottom=678;charg_anim_ui_dimen.cap_top= 922;charg_anim_ui_dimen.cap_bottom= 1413 ;charg_anim_ui_dimen.num_top=599;charg_anim_ui_dimen.num_bottom=720;charg_anim_ui_dimen.percent_top=599;charg_anim_ui_dimen.percent_bottom=720;charg_anim_ui_dimen.top_anim_top=100;charg_anim_ui_dimen.top_anim_bottom=152;charg_anim_ui_dimen.num_width_fast = 108;charg_anim_ui_dimen.num_height_fast = 192;charg_anim_ui_dimen.top_margin_fast = 240;}else if(lcm_width==1080) {charg_anim_ui_dimen.cap_left =408;charg_anim_ui_dimen.cap_right= 671;charg_anim_ui_dimen.num_left=445;charg_anim_ui_dimen.num_right=445+45;charg_anim_ui_dimen.percent_left=445+90;charg_anim_ui_dimen.percent_right=445+90+57;charg_anim_ui_dimen.top_anim_left=408;charg_anim_ui_dimen.top_anim_right=671;charg_anim_ui_dimen.bar_left=470;charg_anim_ui_dimen.bar_top=356;charg_anim_ui_dimen.bar_right=610;charg_anim_ui_dimen.bar_bottom=678;charg_anim_ui_dimen.num_width_fast = 72;charg_anim_ui_dimen.num_height_fast = 128;charg_anim_ui_dimen.top_margin_fast = 300;if (lcm_height == 2280) {SLOGD("[show_animation_common: %s %d]Inside 1080*2280 \n",__FUNCTION__,__LINE__);charg_anim_ui_dimen.cap_top= 992;charg_anim_ui_dimen.cap_bottom= 1473 ;charg_anim_ui_dimen.num_top=659;charg_anim_ui_dimen.num_bottom=780;charg_anim_ui_dimen.percent_top=659;charg_anim_ui_dimen.percent_bottom=780;charg_anim_ui_dimen.top_anim_top=100;charg_anim_ui_dimen.top_anim_bottom=147;}else if (lcm_height == 2300) {SLOGD("[show_animation_common: %s %d]Inside 1080*2300 \n",__FUNCTION__,__LINE__);charg_anim_ui_dimen.cap_top= 1002;charg_anim_ui_dimen.cap_bottom= 1498;charg_anim_ui_dimen.num_top=669;charg_anim_ui_dimen.num_bottom=790;charg_anim_ui_dimen.percent_top=669;charg_anim_ui_dimen.percent_bottom=790;charg_anim_ui_dimen.top_anim_top=100;charg_anim_ui_dimen.top_anim_bottom=147;}else if (lcm_height == 2340) {SLOGD("[show_animation_common: %s %d]Inside 1080*2340 \n",__FUNCTION__,__LINE__);charg_anim_ui_dimen.cap_top= 1012;charg_anim_ui_dimen.cap_bottom= 1503 ;charg_anim_ui_dimen.num_top=689;charg_anim_ui_dimen.num_bottom=810;charg_anim_ui_dimen.percent_top=689;charg_anim_ui_dimen.percent_bottom=810;charg_anim_ui_dimen.top_anim_top=100;charg_anim_ui_dimen.top_anim_bottom=147;}else if (lcm_height == 2400) {SLOGD("[show_animation_common: %s %d]Inside 1080*2340 \n",__FUNCTION__,__LINE__);charg_anim_ui_dimen.cap_top= 1042;charg_anim_ui_dimen.cap_bottom= 1533 ;charg_anim_ui_dimen.num_top=729;charg_anim_ui_dimen.num_bottom=840;charg_anim_ui_dimen.percent_top=729;charg_anim_ui_dimen.percent_bottom=840;charg_anim_ui_dimen.top_anim_top=100;charg_anim_ui_dimen.top_anim_bottom=147;}else if (lcm_height == 2520) {SLOGD("[show_animation_common: %s %d]Inside 1080*2520 \n",__FUNCTION__,__LINE__);charg_anim_ui_dimen.cap_top= 1112;charg_anim_ui_dimen.cap_bottom= 1593 ;charg_anim_ui_dimen.num_top=819;charg_anim_ui_dimen.num_bottom=819+64;charg_anim_ui_dimen.percent_top=819;charg_anim_ui_dimen.percent_bottom=819+64;charg_anim_ui_dimen.top_anim_top=100;charg_anim_ui_dimen.top_anim_bottom=147;}}else if(lcm_width ==720) {charg_anim_ui_dimen.cap_left =278;charg_anim_ui_dimen.cap_right= 441;charg_anim_ui_dimen.num_left=290;charg_anim_ui_dimen.num_right=335;charg_anim_ui_dimen.percent_left=380;charg_anim_ui_dimen.percent_right=437;charg_anim_ui_dimen.top_anim_left=278;charg_anim_ui_dimen.top_anim_right=441;charg_anim_ui_dimen.bar_left=313;charg_anim_ui_dimen.bar_top=238;charg_anim_ui_dimen.bar_right=406;charg_anim_ui_dimen.bar_bottom=453;charg_anim_ui_dimen.num_width_fast = 72;charg_anim_ui_dimen.num_height_fast = 128;charg_anim_ui_dimen.top_margin_fast = 180;if(lcm_height == 1280) {SLOGD("[show_animation_common: %s %d]Inside 720*1280 \n",__FUNCTION__,__LINE__);charg_anim_ui_dimen.cap_top= 556;charg_anim_ui_dimen.cap_bottom= 817 ;charg_anim_ui_dimen.num_top=386;charg_anim_ui_dimen.num_bottom=450;charg_anim_ui_dimen.percent_top=386;charg_anim_ui_dimen.percent_bottom=450;charg_anim_ui_dimen.top_anim_top=100;charg_anim_ui_dimen.top_anim_bottom=129;}else if(lcm_height == 1440) {SLOGD("[show_animation_common: %s %d]Inside 720*1440 \n",__FUNCTION__,__LINE__);charg_anim_ui_dimen.cap_top= 636;charg_anim_ui_dimen.cap_bottom= 898 ;charg_anim_ui_dimen.num_top=465;charg_anim_ui_dimen.num_bottom=529;charg_anim_ui_dimen.percent_top=465;charg_anim_ui_dimen.percent_bottom=529;charg_anim_ui_dimen.top_anim_top=100;charg_anim_ui_dimen.top_anim_bottom=129;}else if(lcm_height == 1500) {SLOGD("[show_animation_common: %s %d]Inside 720*1500 \n",__FUNCTION__,__LINE__);charg_anim_ui_dimen.cap_top= 640;charg_anim_ui_dimen.cap_bottom= 955 ;charg_anim_ui_dimen.num_top=450;charg_anim_ui_dimen.num_bottom=515;charg_anim_ui_dimen.percent_top=450;charg_anim_ui_dimen.percent_bottom=515;charg_anim_ui_dimen.top_anim_top=100;charg_anim_ui_dimen.top_anim_bottom=129;}else if(lcm_height == 1520) {SLOGD("[show_animation_common: %s %d]Inside 720*1520 \n",__FUNCTION__,__LINE__);charg_anim_ui_dimen.cap_top= 653;charg_anim_ui_dimen.cap_bottom= 970 ;charg_anim_ui_dimen.num_top=460;charg_anim_ui_dimen.num_bottom=535;charg_anim_ui_dimen.percent_top=460;charg_anim_ui_dimen.percent_bottom=535;charg_anim_ui_dimen.top_anim_top=100;charg_anim_ui_dimen.top_anim_bottom=129;}else if(lcm_height == 1560) {SLOGD("[show_animation_common: %s %d]Inside 720*1560 \n",__FUNCTION__,__LINE__);charg_anim_ui_dimen.cap_top= 678;charg_anim_ui_dimen.cap_bottom= 1000 ;charg_anim_ui_dimen.num_top=480;charg_anim_ui_dimen.num_bottom=575;charg_anim_ui_dimen.percent_top=480;charg_anim_ui_dimen.percent_bottom=575;charg_anim_ui_dimen.top_anim_top=100;charg_anim_ui_dimen.top_anim_bottom=129;}else if(lcm_height == 1600) {SLOGD("[show_animation_common: %s %d]Inside 720*1600 \n",__FUNCTION__,__LINE__);charg_anim_ui_dimen.cap_top= 703;charg_anim_ui_dimen.cap_bottom= 1030 ;charg_anim_ui_dimen.num_top=500;charg_anim_ui_dimen.num_bottom=615;charg_anim_ui_dimen.percent_top=500;charg_anim_ui_dimen.percent_bottom=615;charg_anim_ui_dimen.top_anim_top=100;charg_anim_ui_dimen.top_anim_bottom=129;}}else if(lcm_width==1440 && lcm_height==2560) {SLOGD("[show_animation_common: %s %d]Inside 1440*2560 \n",__FUNCTION__,__LINE__);charg_anim_ui_dimen.cap_left =556;charg_anim_ui_dimen.cap_top= 1112;charg_anim_ui_dimen.cap_right= 882;charg_anim_ui_dimen.cap_bottom= 1630 ;charg_anim_ui_dimen.num_left=570;charg_anim_ui_dimen.num_top=770;charg_anim_ui_dimen.num_right=660;charg_anim_ui_dimen.num_bottom=898;charg_anim_ui_dimen.percent_left=750;charg_anim_ui_dimen.percent_top=770;charg_anim_ui_dimen.percent_right=864;charg_anim_ui_dimen.percent_bottom=898;charg_anim_ui_dimen.top_anim_left=556;charg_anim_ui_dimen.top_anim_top=100;charg_anim_ui_dimen.top_anim_right=882;charg_anim_ui_dimen.top_anim_bottom=158;charg_anim_ui_dimen.bar_left=443;charg_anim_ui_dimen.bar_top=337;charg_anim_ui_dimen.bar_right=574;charg_anim_ui_dimen.bar_bottom=641;}else if(lcm_width==480 && lcm_height==854) {SLOGD("[show_animation_common: %s %d]Inside 480*854 \n",__FUNCTION__,__LINE__);charg_anim_ui_dimen.cap_left =172;charg_anim_ui_dimen.cap_top= 357;charg_anim_ui_dimen.cap_right= 307;charg_anim_ui_dimen.cap_bottom= 573 ;charg_anim_ui_dimen.num_left=172;charg_anim_ui_dimen.num_top=213;charg_anim_ui_dimen.num_right=210;charg_anim_ui_dimen.num_bottom=267;charg_anim_ui_dimen.percent_left=248;charg_anim_ui_dimen.percent_top=213;charg_anim_ui_dimen.percent_right=296;charg_anim_ui_dimen.percent_bottom=267;charg_anim_ui_dimen.top_anim_left=172;charg_anim_ui_dimen.top_anim_top=100;charg_anim_ui_dimen.top_anim_right=307;charg_anim_ui_dimen.top_anim_bottom=124;charg_anim_ui_dimen.bar_left=184;charg_anim_ui_dimen.bar_top=227;charg_anim_ui_dimen.bar_right=294;charg_anim_ui_dimen.bar_bottom=437;}else if(lcm_width==540 && lcm_height==960) {SLOGD("[show_animation_common: %s %d]Inside 540*960 \n",__FUNCTION__,__LINE__);charg_anim_ui_dimen.cap_left =202;charg_anim_ui_dimen.cap_top= 410;charg_anim_ui_dimen.cap_right= 337;charg_anim_ui_dimen.cap_bottom= 626 ;charg_anim_ui_dimen.num_left=202;charg_anim_ui_dimen.num_top=266;charg_anim_ui_dimen.num_right=240;charg_anim_ui_dimen.num_bottom=320;charg_anim_ui_dimen.percent_left=278;charg_anim_ui_dimen.percent_top=266;charg_anim_ui_dimen.percent_right=326;charg_anim_ui_dimen.percent_bottom=320;charg_anim_ui_dimen.top_anim_left=202;charg_anim_ui_dimen.top_anim_top=100;charg_anim_ui_dimen.top_anim_right=337;charg_anim_ui_dimen.top_anim_bottom=124;charg_anim_ui_dimen.bar_left=235;charg_anim_ui_dimen.bar_top=179;charg_anim_ui_dimen.bar_right=305;charg_anim_ui_dimen.bar_bottom=340;}else if(lcm_width==480 && lcm_height==800) {SLOGD("[show_animation_common: %s %d]Inside 480*800 \n",__FUNCTION__,__LINE__);charg_anim_ui_dimen.cap_left =172;charg_anim_ui_dimen.cap_top= 330;charg_anim_ui_dimen.cap_right= 307;charg_anim_ui_dimen.cap_bottom= 546 ;charg_anim_ui_dimen.num_left=178;charg_anim_ui_dimen.num_top=190;charg_anim_ui_dimen.num_right=216;charg_anim_ui_dimen.num_bottom=244;charg_anim_ui_dimen.percent_left=254;charg_anim_ui_dimen.percent_top=190;charg_anim_ui_dimen.percent_right=302;charg_anim_ui_dimen.percent_bottom=244;charg_anim_ui_dimen.top_anim_left=172;charg_anim_ui_dimen.top_anim_top=100;charg_anim_ui_dimen.top_anim_right=307;charg_anim_ui_dimen.top_anim_bottom=124;charg_anim_ui_dimen.bar_left=209;charg_anim_ui_dimen.bar_top=149;charg_anim_ui_dimen.bar_right=271;charg_anim_ui_dimen.bar_bottom=282;}else if(lcm_width==480 && lcm_height==960) { // default wuvga 480*960SLOGD("[show_animation_common: %s %d]Inside 480*960 \n",__FUNCTION__,__LINE__);charg_anim_ui_dimen.cap_left =172;charg_anim_ui_dimen.cap_top= 410;charg_anim_ui_dimen.cap_right= 307;charg_anim_ui_dimen.cap_bottom= 626 ;charg_anim_ui_dimen.num_left=172;charg_anim_ui_dimen.num_top=266;charg_anim_ui_dimen.num_right=210;charg_anim_ui_dimen.num_bottom=320;charg_anim_ui_dimen.percent_left=248;charg_anim_ui_dimen.percent_top=266;charg_anim_ui_dimen.percent_right=296;charg_anim_ui_dimen.percent_bottom=320;charg_anim_ui_dimen.top_anim_left=172;charg_anim_ui_dimen.top_anim_top=100;charg_anim_ui_dimen.top_anim_right=307;charg_anim_ui_dimen.top_anim_bottom=124;charg_anim_ui_dimen.bar_left=184;charg_anim_ui_dimen.bar_top=227;charg_anim_ui_dimen.bar_right=294;charg_anim_ui_dimen.bar_bottom=437;}else if(lcm_width==320 && lcm_height==480) {SLOGD("[show_animation_common: %s %d]Inside 320*480 \n",__FUNCTION__,__LINE__);charg_anim_ui_dimen.cap_left =109;charg_anim_ui_dimen.cap_top= 189;charg_anim_ui_dimen.cap_right= 211;charg_anim_ui_dimen.cap_bottom= 350 ;charg_anim_ui_dimen.num_left=126;charg_anim_ui_dimen.num_top=95;charg_anim_ui_dimen.num_right=153;charg_anim_ui_dimen.num_bottom=131;charg_anim_ui_dimen.percent_left=180;charg_anim_ui_dimen.percent_top=95;charg_anim_ui_dimen.percent_right=212;charg_anim_ui_dimen.percent_bottom=131;charg_anim_ui_dimen.top_anim_left=109;charg_anim_ui_dimen.top_anim_top=100;charg_anim_ui_dimen.top_anim_right=211;charg_anim_ui_dimen.top_anim_bottom=118;charg_anim_ui_dimen.bar_left=129;charg_anim_ui_dimen.bar_top=128;charg_anim_ui_dimen.bar_right=190;charg_anim_ui_dimen.bar_bottom=245;}else if(lcm_width==240 && lcm_height==240) {SLOGD("[show_animation_common: %s %d]Inside 240*240 \n",__FUNCTION__,__LINE__);charg_anim_ui_dimen.cap_left =82;charg_anim_ui_dimen.cap_top= 62;charg_anim_ui_dimen.cap_right= 158;charg_anim_ui_dimen.cap_bottom= 179 ;charg_anim_ui_dimen.num_left=92;charg_anim_ui_dimen.num_top=8;charg_anim_ui_dimen.num_right=108;charg_anim_ui_dimen.num_bottom=31;charg_anim_ui_dimen.percent_left=124;charg_anim_ui_dimen.percent_top=8;charg_anim_ui_dimen.percent_right=144;charg_anim_ui_dimen.percent_bottom=31;charg_anim_ui_dimen.top_anim_left=82;charg_anim_ui_dimen.top_anim_top=100;charg_anim_ui_dimen.top_anim_right=158;charg_anim_ui_dimen.top_anim_bottom=113;charg_anim_ui_dimen.bar_left=97;charg_anim_ui_dimen.bar_top=96;charg_anim_ui_dimen.bar_right=140;charg_anim_ui_dimen.bar_bottom=184;}else if(lcm_width==600 && lcm_height==1024) {SLOGD("[show_animation_common: %s %d]Inside 600*1024 \n",__FUNCTION__,__LINE__);charg_anim_ui_dimen.cap_left =232;charg_anim_ui_dimen.cap_top= 442;charg_anim_ui_dimen.cap_right= 367;charg_anim_ui_dimen.cap_bottom= 658 ;charg_anim_ui_dimen.num_left=250;charg_anim_ui_dimen.num_top=300;charg_anim_ui_dimen.num_right=288;charg_anim_ui_dimen.num_bottom=354;charg_anim_ui_dimen.percent_left=326;charg_anim_ui_dimen.percent_top=300;charg_anim_ui_dimen.percent_right=374;charg_anim_ui_dimen.percent_bottom=354;charg_anim_ui_dimen.top_anim_left=232;charg_anim_ui_dimen.top_anim_top=100;charg_anim_ui_dimen.top_anim_right=367;charg_anim_ui_dimen.top_anim_bottom=124;charg_anim_ui_dimen.bar_left=260;charg_anim_ui_dimen.bar_top=190;charg_anim_ui_dimen.bar_right=338;charg_anim_ui_dimen.bar_bottom=360;}else if(lcm_width==1024 && lcm_height==600) {SLOGD("[show_animation_common: %s %d]Inside 1024*600 \n",__FUNCTION__,__LINE__);charg_anim_ui_dimen.cap_left =444;charg_anim_ui_dimen.cap_top= 230;charg_anim_ui_dimen.cap_right= 579;charg_anim_ui_dimen.cap_bottom= 446 ;charg_anim_ui_dimen.num_left=466;charg_anim_ui_dimen.num_top=90;charg_anim_ui_dimen.num_right=504;charg_anim_ui_dimen.num_bottom=144;charg_anim_ui_dimen.percent_left=542;charg_anim_ui_dimen.percent_top=90;charg_anim_ui_dimen.percent_right=590;charg_anim_ui_dimen.percent_bottom=144;charg_anim_ui_dimen.top_anim_left=444;charg_anim_ui_dimen.top_anim_top=100;charg_anim_ui_dimen.top_anim_right=579;charg_anim_ui_dimen.top_anim_bottom=124;charg_anim_ui_dimen.bar_left=414;charg_anim_ui_dimen.bar_top=186;charg_anim_ui_dimen.bar_right=608;charg_anim_ui_dimen.bar_bottom=477;}else if(lcm_width==1280 && lcm_height==800) {SLOGD("[show_animation_common: %s %d]Inside 1280*800 \n",__FUNCTION__,__LINE__);charg_anim_ui_dimen.cap_left =558;charg_anim_ui_dimen.cap_top= 265;charg_anim_ui_dimen.cap_right= 721;charg_anim_ui_dimen.cap_bottom= 525 ;charg_anim_ui_dimen.num_left=585;charg_anim_ui_dimen.num_top=95;charg_anim_ui_dimen.num_right=630;charg_anim_ui_dimen.num_bottom=159;charg_anim_ui_dimen.percent_left=675;charg_anim_ui_dimen.percent_top=95;charg_anim_ui_dimen.percent_right=732;charg_anim_ui_dimen.percent_bottom=159;charg_anim_ui_dimen.top_anim_left=558;charg_anim_ui_dimen.top_anim_top=100;charg_anim_ui_dimen.top_anim_right=721;charg_anim_ui_dimen.top_anim_bottom=129;charg_anim_ui_dimen.bar_left=525;charg_anim_ui_dimen.bar_top=250;charg_anim_ui_dimen.bar_right=755;charg_anim_ui_dimen.bar_bottom=640;}else if(lcm_width==1366 && lcm_height==768) {SLOGD("[show_animation_common: %s %d]Inside 1366*768 \n",__FUNCTION__,__LINE__);charg_anim_ui_dimen.cap_left =558;charg_anim_ui_dimen.cap_top= 265;charg_anim_ui_dimen.cap_right= 721;charg_anim_ui_dimen.cap_bottom= 525 ;charg_anim_ui_dimen.num_left=585;charg_anim_ui_dimen.num_top=95;charg_anim_ui_dimen.num_right=630;charg_anim_ui_dimen.num_bottom=159;charg_anim_ui_dimen.percent_left=675;charg_anim_ui_dimen.percent_top=95;charg_anim_ui_dimen.percent_right=732;charg_anim_ui_dimen.percent_bottom=159;charg_anim_ui_dimen.top_anim_left=558;charg_anim_ui_dimen.top_anim_top=100;charg_anim_ui_dimen.top_anim_right=721;charg_anim_ui_dimen.top_anim_bottom=129;charg_anim_ui_dimen.bar_left=525;charg_anim_ui_dimen.bar_top=250;charg_anim_ui_dimen.bar_right=755;charg_anim_ui_dimen.bar_bottom=640;}else if(lcm_width==800 && lcm_height==1280) {SLOGD("[show_animation_common: %s %d]Inside 800*1280 \n",__FUNCTION__,__LINE__);charg_anim_ui_dimen.cap_left =318;charg_anim_ui_dimen.cap_top= 556;charg_anim_ui_dimen.cap_right= 481;charg_anim_ui_dimen.cap_bottom= 815 ;charg_anim_ui_dimen.num_left=345;charg_anim_ui_dimen.num_top=385;charg_anim_ui_dimen.num_right=390;charg_anim_ui_dimen.num_bottom=449;charg_anim_ui_dimen.percent_left=435;charg_anim_ui_dimen.percent_top=385;charg_anim_ui_dimen.percent_right=492;charg_anim_ui_dimen.percent_bottom=449;charg_anim_ui_dimen.top_anim_left=318;charg_anim_ui_dimen.top_anim_top=100;charg_anim_ui_dimen.top_anim_right=481;charg_anim_ui_dimen.top_anim_bottom=129;charg_anim_ui_dimen.bar_left=348;charg_anim_ui_dimen.bar_top=238;charg_anim_ui_dimen.bar_right=453;charg_anim_ui_dimen.bar_bottom=452;}else if(lcm_width==1920 && lcm_height==1200) {SLOGD("[show_animation_common: %s %d]Inside 600*1024 \n",__FUNCTION__,__LINE__);charg_anim_ui_dimen.cap_left =806;charg_anim_ui_dimen.cap_top= 443;charg_anim_ui_dimen.cap_right= 1110;charg_anim_ui_dimen.cap_bottom= 929 ;charg_anim_ui_dimen.num_left=855;charg_anim_ui_dimen.num_top=124;charg_anim_ui_dimen.num_right=939;charg_anim_ui_dimen.num_bottom=245;charg_anim_ui_dimen.percent_left=1023;charg_anim_ui_dimen.percent_top=124;charg_anim_ui_dimen.percent_right=1131;charg_anim_ui_dimen.percent_bottom=245;charg_anim_ui_dimen.top_anim_left=806;charg_anim_ui_dimen.top_anim_top=100;charg_anim_ui_dimen.top_anim_right=1110;charg_anim_ui_dimen.top_anim_bottom=152;charg_anim_ui_dimen.bar_left=890;charg_anim_ui_dimen.bar_top=357;charg_anim_ui_dimen.bar_right=1030;charg_anim_ui_dimen.bar_bottom=678;}else if(lcm_width==1200 && lcm_height==1920) {SLOGD("[show_animation_common: %s %d]Inside 1200*1920 \n",__FUNCTION__,__LINE__);charg_anim_ui_dimen.cap_left =447;charg_anim_ui_dimen.cap_top= 803;charg_anim_ui_dimen.cap_right= 751;charg_anim_ui_dimen.cap_bottom= 1289 ;charg_anim_ui_dimen.num_left=494;charg_anim_ui_dimen.num_top=481;charg_anim_ui_dimen.num_right=578;charg_anim_ui_dimen.num_bottom=602;charg_anim_ui_dimen.percent_left=662;charg_anim_ui_dimen.percent_top=481;charg_anim_ui_dimen.percent_right=770;charg_anim_ui_dimen.percent_bottom=602;charg_anim_ui_dimen.top_anim_left=447;charg_anim_ui_dimen.top_anim_top=100;charg_anim_ui_dimen.top_anim_right=751;charg_anim_ui_dimen.top_anim_bottom=152;charg_anim_ui_dimen.bar_left=529;charg_anim_ui_dimen.bar_top=357;charg_anim_ui_dimen.bar_right=672;charg_anim_ui_dimen.bar_bottom=680;}else if(lcm_width==768 && lcm_height==1024) {SLOGD("[show_animation_common: %s %d]Inside 768*1024 \n",__FUNCTION__,__LINE__);charg_anim_ui_dimen.cap_left =316;charg_anim_ui_dimen.cap_top= 442;charg_anim_ui_dimen.cap_right= 451;charg_anim_ui_dimen.cap_bottom= 658 ;charg_anim_ui_dimen.num_left=338;charg_anim_ui_dimen.num_top=300;charg_anim_ui_dimen.num_right=376;charg_anim_ui_dimen.num_bottom=354;charg_anim_ui_dimen.percent_left=414;charg_anim_ui_dimen.percent_top=300;charg_anim_ui_dimen.percent_right=462;charg_anim_ui_dimen.percent_bottom=354;charg_anim_ui_dimen.top_anim_left=316;charg_anim_ui_dimen.top_anim_top=100;charg_anim_ui_dimen.top_anim_right=451;charg_anim_ui_dimen.top_anim_bottom=124;charg_anim_ui_dimen.bar_left=334;charg_anim_ui_dimen.bar_top=243;charg_anim_ui_dimen.bar_right=434;charg_anim_ui_dimen.bar_bottom=463;}else { // default wvga 480*800SLOGD("[show_animation_common: %s %d]default case final else \n",__FUNCTION__,__LINE__);charg_anim_ui_dimen.cap_left =172;charg_anim_ui_dimen.cap_top= 330;charg_anim_ui_dimen.cap_right= 307;charg_anim_ui_dimen.cap_bottom= 546 ;charg_anim_ui_dimen.num_left=178;charg_anim_ui_dimen.num_top=190;charg_anim_ui_dimen.num_right=216;charg_anim_ui_dimen.num_bottom=244;charg_anim_ui_dimen.percent_left=254;charg_anim_ui_dimen.percent_top=290;charg_anim_ui_dimen.percent_right=302;charg_anim_ui_dimen.percent_bottom=244;charg_anim_ui_dimen.top_anim_left=172;charg_anim_ui_dimen.top_anim_top=100;charg_anim_ui_dimen.top_anim_right=307;charg_anim_ui_dimen.top_anim_bottom=124;charg_anim_ui_dimen.bar_left=209;charg_anim_ui_dimen.bar_top=149;charg_anim_ui_dimen.bar_right=271;charg_anim_ui_dimen.bar_bottom=282;}}

请添加图片描述

anim_logo_init()

加载动画资源到内存。

vendor/mediatek/proprietary/external/libshowlogo/charging_animation.cpp

/** Charging animation logo.bin related init**/
void anim_logo_init(void)
{// read and de-compress logo data hereint fd = 0;int len = 0;Fstab fstab;if (!ReadDefaultFstab(&fstab)) {if (MTK_LOG_ENABLE == 1) {SLOGE("failed to open fstab\n");}error_flag = 1;return;}auto rec = GetEntryForMountPoint(&fstab, LOGO_MNT_POINT);	//获取logo挂载点if (rec == nullptr) {if (MTK_LOG_ENABLE == 1) {SLOGE("failed to get entry for %s\n", LOGO_MNT_POINT);}error_flag = 1;return;}// "rec->blk_device" is the pathfd = open(rec->blk_device.c_str(), O_RDONLY);	//只读方式打开rec->blk_device.c_str()文件// get logo patition from fstab endif(fd < 0){if (MTK_LOG_ENABLE == 1) {SLOGE("[libshowlogo: %s %d]open logo partition device file fail, errno = %d \n",__FUNCTION__,__LINE__ , errno);}goto error_return;}logo_addr = (unsigned int*)malloc(LOGO_BUFFER_SIZE);if(logo_addr == NULL){if (MTK_LOG_ENABLE == 1) {SLOGE("[libshowlogo: %s %d]allocate logo buffer fail, size=0x%08x \n",__FUNCTION__,__LINE__ , LOGO_BUFFER_SIZE);}goto error_return;}// (1) skip the image headerlen = read(fd, logo_addr, 512);if (len < 0){if (MTK_LOG_ENABLE == 1) {SLOGE("[libshowlogo: %s %d]read from logo addr for 512B is failed! \n",__FUNCTION__,__LINE__);}goto error_return;}// get the imagelen = read(fd, logo_addr, LOGO_BUFFER_SIZE - 512);	//获取logo数据到logo_addr指向的内存,前512字节跳过if (len < 0){if (MTK_LOG_ENABLE == 1) {SLOGE("[libshowlogo: %s %d]read from logo addr for buffer is failed! \n",__FUNCTION__,__LINE__);}goto error_return;}close(fd);if (show_animationm_ver > 0){unsigned int *pinfo = (unsigned int*)logo_addr;if (MTK_LOG_ENABLE == 1) {SLOGD("[libshowlogo: %s %d]pinfo[0]=%d, pinfo[1]=%d\n", __FUNCTION__,__LINE__, pinfo[0], pinfo[1]);}if ((show_animationm_ver == VERION_WIRELESS_CHARGING_ANIMATION) && (pinfo[0] < ANIM_V2_LOGO_NUM)){set_anim_version(VERION_NEW_ANIMATION);}if (pinfo[0] < ANIM_V1_LOGO_NUM){kernel_logo_position = ANIM_V0_LOGO_NUM - 1;set_anim_version(VERION_OLD_ANIMATION);}}if (MTK_LOG_ENABLE == 1) {SLOGD("[libshowlogo: %s %d]show_animationm_ver =  :%d",__FUNCTION__,__LINE__ ,show_animationm_ver);}return;error_return:if(fd >= 0){close(fd);}free_fstab();sleep(3);error_flag = 1;if (MTK_LOG_ENABLE == 1) {SLOGD("[libshowlogo: %s %d] error return !!!\n",__FUNCTION__,__LINE__);}// to prevent interlace operation with MD reset
}
anim_fb_init()

framebuffer初始化、设置屏幕信息等。

vendor/mediatek/proprietary/external/libshowlogo/charging_animation.cpp

/** Charging animation framebuffer related init**/
int anim_fb_init(void)
{if (MTK_LOG_ENABLE == 1) {SLOGD("[libshowlogo: %s %d]\n",__FUNCTION__,__LINE__);}fb_fd = open(FB_NODE_PATH, O_RDWR);if(fb_fd < 0){if (MTK_LOG_ENABLE == 1) {SLOGE("[libshowlogo: %s %d]open dev file fail, errno = %d \n",__FUNCTION__,__LINE__ , errno);}close(fb_fd);error_flag = 1;return -1;}#ifndef MTK_HWC_USE_DRM_DEVICE///dual add beginmemset((void *)&fb_info, 0, sizeof(fb_info));if (ioctl(fb_fd, MTKFB_GET_DISPLAY_PATH_INFO, &fb_info) < 0)SLOGD("ioctl error %s size %d\n", strerror(errno), sizeof(struct fb_display_path_info));pathcnt = fb_info.path_cnt;SLOGD("[libshowlogo: %s %d] pathcnt = %d\n",__FUNCTION__,__LINE__, pathcnt);
#endifioctl(fb_fd, FBIOGET_VSCREENINFO, &vinfo);ioctl(fb_fd, FBIOGET_FSCREENINFO, &finfo);fb_size  = finfo.line_length * vinfo.yres;dec_logo_addr = (unsigned int*) malloc(fb_size);
#ifndef MTK_HWC_USE_DRM_DEVICEif (pathcnt > 1) {lk_fb_addr =(unsigned int*)mmap(0, fb_size*6, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, 0);} else {lk_fb_addr =(unsigned int*)mmap(0, fb_size*3, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, 0);}
#elselk_fb_addr =(unsigned int*)mmap(0, fb_size*3, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, 0);
#endifcharging_fb_addr = (unsigned int*)((unsigned int)lk_fb_addr + fb_size);kernel_fb_addr = (unsigned int*)((unsigned int)charging_fb_addr + fb_size);fb_addr = lk_fb_addr;if (MTK_LOG_ENABLE == 1) {SLOGD("[libshowlogo: %s %d]vinfo:xres  = %d, yres = %d, xres_virtual =%d, bits_per_pixel = %d,red.offset = %d,blue.offset = %d\n",__FUNCTION__, __LINE__, vinfo.xres,vinfo.yres, vinfo.xres_virtual, vinfo.bits_per_pixel,vinfo.red.offset,vinfo.blue.offset);SLOGD("[libshowlogo: %s %d]fb_size =%d, fb_addr = %p,charging_fb_addr=%p\n",__FUNCTION__, __LINE__, fb_size,fb_addr, charging_fb_addr);}if(fb_addr == NULL || charging_fb_addr == NULL){if (MTK_LOG_ENABLE == 1) {SLOGE("ChargingAnimation mmap fail\n");}
#ifndef MTK_HWC_USE_DRM_DEVICEif (pathcnt > 1) {munmap(lk_fb_addr, fb_size*6);} else {munmap(lk_fb_addr, fb_size*2);}
#elsemunmap(lk_fb_addr, fb_size*2);
#endifclose(fb_fd);error_flag = 1;return -1;}phical_screen.bits_per_pixel = vinfo.bits_per_pixel;phical_screen.fill_dst_bits = vinfo.bits_per_pixel;phical_screen.red_offset = vinfo.red.offset;phical_screen.blue_offset = vinfo.blue.offset;phical_screen.width = vinfo.xres;phical_screen.height = vinfo.yres;phical_screen.allignWidth = finfo.line_length/(vinfo.bits_per_pixel/8);phical_screen.needAllign = 1;phical_screen.need180Adjust = 1;phical_screen.fb_size = fb_size;if (MTK_LOG_ENABLE == 1) {SLOGD("[libshowlogo: %s %d]MTK_LCM_PHYSICAL_ROTATION = %s\n",__FUNCTION__,__LINE__, MTK_LCM_PHYSICAL_ROTATION);}if (MTK_LOG_ENABLE == 1) {SLOGD("[libshowlogo: %s %d]charge_animation_rotation = %d\n",__FUNCTION__,__LINE__, charge_animation_rotation);}if(270 == charge_animation_rotation){//270phical_screen.rotation = 270;} else if(90 == charge_animation_rotation){//90phical_screen.rotation = 90;} else if((180 == charge_animation_rotation) && (phical_screen.need180Adjust == 1)){//180phical_screen.rotation = 180;} else {phical_screen.rotation = 0;}#ifndef MTK_HWC_USE_DRM_DEVICEif (pathcnt > 1) {for(unsigned int i = 0; i < pathcnt; i++){phical_screenArr[i].width = fb_info.xres[i];phical_screenArr[i].height = fb_info.yres[i];phical_screenArr[i].needAllign = 1;phical_screenArr[i].need180Adjust = 1;fb_addrArr[i] = (unsigned int*)((unsigned int)kernel_fb_addr + fb_size * i);phical_screenArr[i].bits_per_pixel = vinfo.bits_per_pixel;phical_screenArr[i].fill_dst_bits = vinfo.bits_per_pixel;phical_screenArr[i].red_offset = vinfo.red.offset;phical_screenArr[i].blue_offset = vinfo.blue.offset;phical_screenArr[i].allignWidth = fb_info.line_length[i]/(vinfo.bits_per_pixel/8);phical_screenArr[i].fb_size = fb_info.line_length[i] * fb_info.yres[i];dec_logo_addrArr[i] = (unsigned int*) malloc(phical_screenArr[i].fb_size);SLOGD("[libshowlogo: %s %d] x = %d, y= %d , fb_info.line_length=%d , fb_size=%d addr 0x%p\n",__FUNCTION__,__LINE__,fb_info.xres[i], fb_info.yres[i], fb_info.line_length[i], phical_screenArr[i].fb_size, fb_addrArr[i]);if(ORIENTATION_270 == charge_animation_rotation){phical_screenArr[i].rotation = 270;} else if(ORIENTATION_90 == charge_animation_rotation){phical_screenArr[i].rotation = 90;} else if((ORIENTATION_180 == charge_animation_rotation) && (phical_screen.need180Adjust == 1)){//180phical_screenArr[i].rotation = 180;} else {phical_screenArr[i].rotation = 0;}}}
#endifif (MTK_LOG_ENABLE == 1) {SLOGD("[libshowlogo]phical_screen: width= %d,height= %d,bits_per_pixel =%d,needAllign = %d,allignWidth=%d rotation =%d ,need180Adjust = %d\n",phical_screen.width, phical_screen.height,phical_screen.bits_per_pixel, phical_screen.needAllign,phical_screen.allignWidth, phical_screen.rotation, phical_screen.need180Adjust);SLOGD("[libshowlogo: %s %d]show old animtion= 1, running show_animationm_ver %d\n",__FUNCTION__,__LINE__, show_animationm_ver);SLOGD("[libshowlogo: %s %d]draw_anim_mode = 1, running mode %d\n",__FUNCTION__,__LINE__, draw_anim_mode);}return 0;
}

charging_control()函数

充电指示灯及充电动画显示的控制。

/mediatek/proprietary/external/charger/charging_control.cpp

void charging_control()
{int ret = 0;pthread_attr_t attr, attrd, attrl;pthread_t uevent_thread, draw_thread;//charging led controlif (!is_charging_source_available()) {	//return (usb_online || ac_online || wireless_online || vchr >= 2500);lights_exit();}pthread_mutex_init(&mutexlstate, NULL);pthread_mutex_init(&mutex, NULL);pthread_cond_init(&cond, NULL);pthread_attr_init(&attr);pthread_attr_init(&attrd);pthread_attr_init(&attrl);inDraw = 0;ret = pthread_create(&uevent_thread, &attr, uevent_thread_routine, NULL);	//创建处理充电事件的线程if (ret != 0){KPOC_LOGI("create uevt pthread failed.\n");exit_charger(EXIT_ERROR_SHUTDOWN);}firstTime = 1;ret = pthread_create(&draw_thread, &attrd, draw_thread_routine, NULL);	//创建处理充电动画绘制的线程if (ret != 0){KPOC_LOGI("create draw pthread failed.\n");exit_charger(EXIT_ERROR_SHUTDOWN);}
}

uevent_thread_routine()函数

监听系统事件,当事件为电池状态变化时,根据当前充电状态和电池电量调整充电指示灯的状态。

static void* uevent_thread_routine(__attribute__((unused))void *arg)
{char buf[1024];int len;if (!uevent_init()){KPOC_LOGI("uevent_init failed.\n");return 0;}while (1){len = uevent_next_event(buf, sizeof(buf) - 1);if (len > 0) {if (!on_uevent(buf, len))break;}}pthread_exit(NULL);return NULL;
}static int on_uevent(const char *buf, __attribute__((unused))int len_buf)
{
#ifdef VERBOSE_OUTPUTKPOC_LOGI("on_uevent, %s\n", buf);
#endifif (!strcasestr(buf, UEVENT_BATTERY_CHANGE))return 1;//if ac or usb onlineif (is_charging_source_available()){bc = get_capacity();if (bc >= 90) {lights_full();} else {if (nCurrentState != LIGHTS_STATE_CHGON)set_light_state(LIGHTS_CHGON);lights_on();}}elseexit_charger(EXIT_CHARGING_MODE);return 1;
}

draw_thread_routine()函数

vendor/mediatek/proprietary/external/charger/charging_control.cpp

static void* draw_thread_routine(__attribute__((unused))void *arg)
{int bc;int fd_fb, err =0;char filename[32] = {0};do {	//死循环KPOC_LOGI("draw thread working2...\n");// move here to avoid suspend when syncing with surfaceflingerif(firstTime){// make sure charging source online when in KPOC mode// add 2s toleranceif(wait_until(is_charging_source_available,charging_source_waiting_duration_ms,charging_source_waiting_interval_ms)){KPOC_LOGI("wait until charging source available\n");}else{KPOC_LOGI("charging source not available for %d ms at KPOC starup\n",charging_source_waiting_duration_ms);}firstTime = 0;}inDraw = 1;// check the bc offest valuebc = get_capacity();	//获取电池电量draw_with_interval(bootlogo_show_charging, bc, nChgAnimDuration_msec, nCbInterval_msec);	//nChgAnimDuration_msec = 6000; nCbInterval_msec = 200;stop_backlight();	//关闭背光// @@@ draw fb again to refresh ddpbootlogo_show_charging(bc, 1);/* make fb blank */err = snprintf(filename, sizeof(filename), "/dev/graphics/fb0");if (err < 0) {KPOC_LOGI("Failed at snprintf: %s\n", strerror(errno));break;}fd_fb = open(filename, O_RDWR);if (fd_fb < 0) {KPOC_LOGI("Failed to open fb0 device: %s", strerror(errno));break;}err = ioctl(fd_fb, FBIOBLANK, FB_BLANK_POWERDOWN);if (err < 0) {KPOC_LOGI("Failed to blank fb0 device: %s", strerror(errno));}if (fd_fb >= 0)close(fd_fb);request_suspend(true);inDraw = 0;pthread_mutex_lock(&mutex);pthread_cond_wait(&cond, &mutex);pthread_mutex_unlock(&mutex);} while(1);pthread_exit(NULL);return NULL;
}
draw_with_interval()函数

控制动画绘制的时长和间隔。total_time_msec = 6000; interval_msec = 200;

// total_time : ms
// interval : ms
static void draw_with_interval(void (*func)(int, int), int bc, int total_time_msec, int interval_msec)
{struct timeval start;int resume_started = 0, backlight_started = 0, cnt = 0;int fd_fb, err = 0;char filename[32] = {0};gettimeofday(&start, NULL);	//Get the current time of day, putting it into *TV.while(!time_exceed(start, total_time_msec) && !key_trigger_suspend)	//只要不超时就循环绘制{// check if need to draw animation before performing drawingif (!is_charging_source_available())return;if (!resume_started) {resume_started = 1;request_suspend(false);/* make fb unblank */err = snprintf(filename, sizeof(filename), "/dev/graphics/fb0");if (err < 0) {KPOC_LOGI("Failed at snprintf: %s\n", strerror(errno));return;}fd_fb = open(filename, O_RDWR);if (fd_fb < 0) {KPOC_LOGI("Failed to open fb0 device: %s", strerror(errno));}err = ioctl(fd_fb, FBIOBLANK, FB_BLANK_UNBLANK);if (err < 0) {KPOC_LOGI("Failed to unblank fb0 device: %s", strerror(errno));}if (fd_fb >= 0)close(fd_fb);}func(bc, ++cnt);if (!backlight_started) {backlight_started = 1;usleep(1000);start_backlight();}KPOC_LOGI("draw_with_interval... key_trigger_suspend = %d\n",key_trigger_suspend);usleep(interval_msec*1000);}
}
bool time_exceed(struct timeval start, int duration_msec)
{struct timeval now;gettimeofday(&now, NULL);if((now.tv_sec - start.tv_sec)*1000000 + now.tv_usec - start.tv_usec > duration_msec*1000)	//单位转换后再比较return true;elsereturn false;
}

timeval结构体

/* A time value that is accurate to the nearestmicrosecond but also has a range of years.  */
struct timeval
{
#ifdef __USE_TIME_BITS64__time64_t tv_sec;		/* Seconds.  */__suseconds64_t tv_usec;	/* Microseconds.  */
#else__time_t tv_sec;		/* Seconds.  */__suseconds_t tv_usec;	/* Microseconds.  */
#endif
};

bootlogo_show_charging()函数

绘制充电动画的入口函数。

vendor/mediatek/proprietary/external/charger/bootlogo.cpp

/** Show charging animation with battery capacity**/
void bootlogo_show_charging(int capacity, int cnt)
{KPOC_LOGI("[ChargingAnimation: %s %d]%d, %d\n",__FUNCTION__,__LINE__, capacity, cnt);if (get_battnotify_status()){KPOC_LOGI("[ChargingAnimation: %s %d] show_charger_error_logo, get_battnotify_status()= %d \n",__FUNCTION__,__LINE__, get_battnotify_status());show_charger_ov_logo();return;}if (showLowBattLogo){KPOC_LOGI("[ChargingAnimation: %s %d] show_low_battery , showLowBattLogo = %d \n",__FUNCTION__,__LINE__,showLowBattLogo);show_low_battery();return;}show_battery_capacity(capacity);
}
static const char *bat_notify_path[] = {"/sys/devices/platform/charger/BatteryNotify","/sys/devices/platform/mt-battery/BatteryNotify",
};/** return value:*     1: abnormal status*     0: normal status*     If path is not found, return 0*/
int get_battnotify_status()
{int i = 0;int bat_status = 0;/* Find path for battery status */for (i = 0; i < ARRAY_SIZE(bat_notify_path); i++) {bat_status = get_int_value(bat_notify_path[i]);if (bat_status != -1)break;}KPOC_LOGI("charger battStatus=%d, idx=%d\n", bat_status, i);if (bat_status > 0)return 1;return 0;
}

请添加图片描述

请添加图片描述

show_battery_capacity()函数

vendor/mediatek/proprietary/external/libshowlogo/charging_animation.cpp

/** Show charging animation with battery capacity**/
void show_battery_capacity(unsigned int capacity)
{if (MTK_LOG_ENABLE == 1) {SLOGD("[libshowlogo: %s %d]capacity =%d\n",__FUNCTION__,__LINE__, capacity);}if (draw_anim_mode == (DRAW_ANIM_MODE_FB)) {anim_fb_addr_switch();	//切换缓冲区
#if defined(MSSI_MTK_PUMP_EXPRESS_SUPPORT) || defined(MSSI_MTK_PUMP_EXPRESS_PLUS_SUPPORT) || defined(MSSI_MTK_PUMP_EXPRESS_PLUS_20_SUPPORT) //快充相关if (2 != show_animationm_ver && get_fast_charging_state()) {fill_animation_battery_fast_charging(capacity, (void *)fb_addr, dec_logo_addr, logo_addr, phical_screen, draw_anim_mode);} else {fill_animation_battery_by_ver(capacity, (void *)fb_addr, dec_logo_addr, logo_addr, phical_screen, show_animationm_ver);}
#elsefill_animation_battery_by_ver(capacity, (void *)fb_addr, dec_logo_addr, logo_addr, phical_screen, show_animationm_ver);
#endifanim_fb_disp_update(); //更新缓冲区} else {ARect tmpRect;tmpRect.left = 0;tmpRect.top = 0;tmpRect.right = phical_screen.width;tmpRect.bottom = phical_screen.height;status_t  lockResult = surface->lock(&outBuffer, &tmpRect);if (MTK_LOG_ENABLE == 1) {SLOGD("[libshowlogo: %s %d]outBuffer.bits = %d, surface->lock return =  0x%08x,\n",__FUNCTION__,__LINE__, (int)outBuffer.bits,lockResult);}if (0 == lockResult){
#if defined(MSSI_MTK_PUMP_EXPRESS_SUPPORT) || defined(MSSI_MTK_PUMP_EXPRESS_PLUS_SUPPORT) || defined(MSSI_MTK_PUMP_EXPRESS_PLUS_20_SUPPORT)if (2 != show_animationm_ver && get_fast_charging_state()) {fill_animation_battery_fast_charging(capacity, (void *)outBuffer.bits, dec_logo_addr, logo_addr, phical_screen, draw_anim_mode);} else {fill_animation_battery_by_ver(capacity, (void *)outBuffer.bits, dec_logo_addr, logo_addr, phical_screen, show_animationm_ver);}
#elsefill_animation_battery_by_ver(capacity, (void *)outBuffer.bits, dec_logo_addr, logo_addr, phical_screen, show_animationm_ver);
#endifsurface->unlockAndPost();}}
}

切换缓冲区的主要目的是在显示动画时实现平滑的画面刷新。

在双缓冲模式下,通常会使用两块帧缓冲区,一块用于显示当前画面,另一块用于准备下一帧的画面。当当前帧显示完成时,就可以立即切换到另一块缓冲区继续显示,而不必等待下一帧数据准备完毕。这样可以避免出现画面撕裂或者闪烁的现象,提高了显示的流畅度和质量。

static unsigned int *charging_fb_addr = NULL;
static unsigned int *kernel_fb_addr = NULL;
static unsigned int use_double_addr = 0;/** Charging animation framebuffer switch buffer**/
void anim_fb_addr_switch(void)
{if (MTK_LOG_ENABLE == 1) {SLOGD("[libshowlogo: %s %d]use_double_addr =%d \n",__FUNCTION__,__LINE__,use_double_addr);}if(use_double_addr == 0) {use_double_addr++;fb_addr = kernel_fb_addr;} else {use_double_addr = 0;fb_addr = charging_fb_addr;}if (MTK_LOG_ENABLE == 1) {SLOGD("[libshowlogo: %s %d]fb_addr =%d \n",__FUNCTION__,__LINE__, (int)fb_addr);}
}

fill_animation_battery_by_ver()函数

通过传入的show_animationm_ver参数选择不同的绘制样式。

VERION_OLD_ANIMATION: show 4 recatangle growing animation without battery number
VERION_NEW_ANIMATION: show wave animation with battery number
VERION_WIRELESS_CHARGING_ANIMATION: show wireless charging animation

这里show_animationm_ver = VERION_NEW_ANIMATION

vendor/mediatek/proprietary/external/libshowlogo/show_animation_common.c

/** Show charging animation by version**/
void fill_animation_battery_by_ver(int capacity, void *fill_addr, void * dec_logo_addr, void * logo_addr,LCM_SCREEN_T phical_screen, int version)
{if (MTK_LOG_ENABLE == 1) {SLOGD("[show_animation_common: %s %d]version : %d\n",__FUNCTION__,__LINE__, version);}switch (version){case VERION_OLD_ANIMATION:fill_animation_battery_old(capacity, fill_addr, dec_logo_addr, logo_addr, phical_screen);break;case VERION_NEW_ANIMATION:fill_animation_battery_new(capacity, fill_addr, dec_logo_addr, logo_addr, phical_screen);break;case VERION_WIRELESS_CHARGING_ANIMATION:fill_animation_battery_wireless_charging(capacity, fill_addr, dec_logo_addr, logo_addr, phical_screen);break;default:fill_animation_battery_old(capacity, fill_addr, dec_logo_addr, logo_addr, phical_screen);break;}
}

fill_animation_battery_new()函数

通过大量fill_animation_xxx()函数,绘制了不同的UI元素。大同小异,拿fill_animation_logo(FULL_BATTERY_INDEX, fill_addr, dec_logo_addr, logo_addr,phical_screen)举例:

index:logo的索引值。
fill_addr:填充屏幕的位置。
dec_logo_addr:解压后的logo地址。
logo_addr:原始logo地址。
phical_screen:LCM屏幕参数。

/** Show new charging animation**/
void fill_animation_battery_new(int capacity, void *fill_addr, void * dec_logo_addr, void * logo_addr, LCM_SCREEN_T phical_screen)
{if (MTK_LOG_ENABLE == 1) {SLOGD("[show_animation_common: %s %d]capacity : %d\n",__FUNCTION__,__LINE__, capacity);}//图片分配地址并初始化if (percent_pic_addr==NULL) {percent_pic_addr=(unsigned short*)malloc(((charg_anim_ui_dimen.percent_right - charg_anim_ui_dimen.percent_left)*(charg_anim_ui_dimen.percent_bottom - charg_anim_ui_dimen.percent_top)*4)*sizeof(unsigned short));memset(percent_pic_addr,0,(((charg_anim_ui_dimen.percent_right - charg_anim_ui_dimen.percent_left)*(charg_anim_ui_dimen.percent_bottom - charg_anim_ui_dimen.percent_top)*4)*sizeof(unsigned short)));}if (top_animation_addr==NULL) {top_animation_addr=(unsigned short*)malloc(((charg_anim_ui_dimen.top_anim_right - charg_anim_ui_dimen.top_anim_left)*(charg_anim_ui_dimen.top_anim_bottom - charg_anim_ui_dimen.top_anim_top)*4)*sizeof(unsigned short));memset(top_animation_addr,0,(((charg_anim_ui_dimen.top_anim_right - charg_anim_ui_dimen.top_anim_left)*(charg_anim_ui_dimen.top_anim_bottom - charg_anim_ui_dimen.top_anim_top)*4)*sizeof(unsigned short)));}RECT_REGION_T percent_location_rect = {charg_anim_ui_dimen.percent_left,charg_anim_ui_dimen.percent_top,charg_anim_ui_dimen.percent_right,charg_anim_ui_dimen.percent_bottom};if (capacity >= 100) {//show_logo(37); // battery 100fill_animation_logo(FULL_BATTERY_INDEX, fill_addr, dec_logo_addr, logo_addr,phical_screen);	//显示满电时的logo,满电logo是一个单独的图片} else if (capacity < 10) { //显示低电时logo,低电logo由橙色波浪的电量图片、单个电量数字和百分号组成if (MTK_LOG_ENABLE == 1) {SLOGD("[show_animation_common: %s %d]charging_low_index = %d\n",__FUNCTION__,__LINE__, charging_low_index);}charging_low_index ++ ;fill_animation_logo(LOW_BAT_ANIM_START_0 + charging_low_index, fill_addr, dec_logo_addr, logo_addr,phical_screen);fill_animation_number(NUMBER_PIC_START_0 + capacity, 1, fill_addr, logo_addr, phical_screen);fill_animation_dynamic(NUMBER_PIC_PERCENT, percent_location_rect, fill_addr, percent_pic_addr, logo_addr, phical_screen);if (charging_low_index >= 9) charging_low_index = 0;} else { //显示非低电时logo,非低电logo由电池背景,蓝色线条、两个电量数字和百分号组成unsigned int capacity_grids = 0;//static RECT_REGION_T battery_rect = {CAPACITY_LEFT,CAPACITY_TOP,CAPACITY_RIGHT,CAPACITY_BOTTOM};capacity_grids = charg_anim_ui_dimen.cap_bottom - (charg_anim_ui_dimen.cap_bottom - charg_anim_ui_dimen.cap_top) * (capacity - 10) / 90;  //电量格数if (MTK_LOG_ENABLE == 1) {SLOGD("[show_animation_common: %s %d]capacity_grids : %d,charging_animation_index = %d\n",__FUNCTION__,__LINE__, capacity_grids,charging_animation_index);}//backgroundfill_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);fill_animation_number(NUMBER_PIC_START_0 + (capacity/10), 0, fill_addr, logo_addr, phical_screen);fill_animation_number(NUMBER_PIC_START_0 + (capacity%10), 1, fill_addr, logo_addr, phical_screen);fill_animation_dynamic(NUMBER_PIC_PERCENT, percent_location_rect, fill_addr, percent_pic_addr, logo_addr, phical_screen);if (capacity <= 90){RECT_REGION_T top_animation_rect = {charg_anim_ui_dimen.top_anim_left, capacity_grids - (charg_anim_ui_dimen.top_anim_bottom - charg_anim_ui_dimen.top_anim_top), charg_anim_ui_dimen.top_anim_right, capacity_grids};//top_animation_rect.bottom = capacity_grids;//top_animation_rect.top = capacity_grids - top_animation_height;charging_animation_index++;//show_animation_dynamic(15 + charging_animation_index, top_animation_rect, top_animation_addr);//播放蓝色的充电波浪fill_animation_dynamic(BAT_ANIM_START_0 + charging_animation_index, top_animation_rect, fill_addr,top_animation_addr, logo_addr, phical_screen);if (charging_animation_index >= 9) charging_animation_index = 0;}}}

fill_animation_logo()函数

从屏幕左上角零点处绘制图像。

/** Fill a screen size buffer with logo content**/
void fill_animation_logo(int index, void *fill_addr, void * dec_logo_addr, void * logo_addr, LCM_SCREEN_T phical_screen)
{LOGO_PARA_T logo_info;int logo_width;int logo_height;int raw_data_size;int logo_index = index;int logo_offset = -1;g_dec_logo_addr = dec_logo_addr;logo_offset = calculate_logo_offset(index, dec_logo_addr, logo_addr, phical_screen);if(logo_offset == -1){SLOGD("[calculate_logo_offset: %s %d]Resolution not supported\n",__FUNCTION__,__LINE__);return;}logo_index = logo_index + logo_offset;//检查logo索引的有效性if(check_logo_index_valid(logo_index, logo_addr, &logo_info) != CHECK_LOGO_BIN_OK)return;//资源文件大小raw_data_size = decompress_logo((void*)logo_info.inaddr, dec_logo_addr, logo_info.logolen, phical_screen.fb_size);if (MTK_LOG_ENABLE == 1) {SLOGD("[show_animation_common: %s %d]raw_data_size = %d\n",__FUNCTION__,__LINE__, raw_data_size);}//RECT_REGION_T rect = {0, 0, phical_screen.width, phical_screen.height};logo_width =phical_screen.width;logo_height = phical_screen.height;if (phical_screen.rotation == 270 || phical_screen.rotation == 90) {logo_width = phical_screen.height;logo_height = phical_screen.width;}//单个像素点的大小(32位)if (0 == bits) {if (raw_data_size == logo_width*logo_height*4) {bits = 32;} else if (raw_data_size == logo_width*logo_height*2) {bits = 16;} else {if (MTK_LOG_ENABLE == 1) {SLOGE("[show_animation_common: %s %d]Logo data error\n",__FUNCTION__,__LINE__);}return;}if (MTK_LOG_ENABLE == 1) {SLOGD("[show_animation_common: %s %d]bits = %d\n",__FUNCTION__,__LINE__, bits);}}RECT_REGION_T rect = {0, 0, logo_width, logo_height};fill_rect_with_content(fill_addr, rect, dec_logo_addr, phical_screen, bits);
}

fill_animation_number()函数

绘制电量百分数的图像。多位数会根据number_position的不同,绘制在不同的地方。

/** Fill a rectangle  with number logo content** number_position: 0~1st number, 1~2nd number*/
void fill_animation_number(int index, unsigned int number_position, void *fill_addr,  void * logo_addr, LCM_SCREEN_T phical_screen)
{int logo_index = index;int logo_offset = -1;logo_offset = calculate_logo_offset(index, g_dec_logo_addr, logo_addr, phical_screen);if(logo_offset == -1){SLOGD("[calculate_logo_offset: %s %d]Resolution not supported\n",__FUNCTION__,__LINE__);return;}logo_index = logo_index + logo_offset;if (MTK_LOG_ENABLE == 1) {SLOGD("[show_animation_common: %s %d]index= %d, number_position = %d\n",__FUNCTION__,__LINE__, index, number_position);}//为数字图片分配内存并初始化if(number_pic_addr==NULL) {number_pic_addr= (unsigned short*)malloc(((charg_anim_ui_dimen.num_right - charg_anim_ui_dimen.num_left)*(charg_anim_ui_dimen.num_bottom - charg_anim_ui_dimen.num_top)*4)*sizeof(unsigned short));memset(number_pic_addr,0,(((charg_anim_ui_dimen.num_right - charg_anim_ui_dimen.num_left)*(charg_anim_ui_dimen.num_bottom - charg_anim_ui_dimen.num_top)*4)*sizeof(unsigned short)));}LOGO_PARA_T logo_info;int raw_data_size;//检查logo索引的有效性if(check_logo_index_valid(logo_index, logo_addr, &logo_info) != CHECK_LOGO_BIN_OK)return;number_pic_size = (charg_anim_ui_dimen.num_right-charg_anim_ui_dimen.num_left)*(charg_anim_ui_dimen.num_bottom-charg_anim_ui_dimen.num_top)*4;// draw default number rect,raw_data_size = decompress_logo((void*)logo_info.inaddr, (void*)number_pic_addr, logo_info.logolen, number_pic_size);if (MTK_LOG_ENABLE == 1) {SLOGD("[show_animation_common: %s %d]raw_data_size = %d\n",__FUNCTION__,__LINE__, raw_data_size);}//static RECT_REGION_T number_location_rect = {NUMBER_LEFT,NUMBER_TOP,NUMBER_RIGHT,NUMBER_BOTTOM};//数字可能有两个,所以要通过number_position控制个位和十位数字的位置RECT_REGION_T battery_number_rect = {charg_anim_ui_dimen.num_left + (charg_anim_ui_dimen.num_right - charg_anim_ui_dimen.num_left)*number_position,charg_anim_ui_dimen.num_top,charg_anim_ui_dimen.num_right + (charg_anim_ui_dimen.num_right - charg_anim_ui_dimen.num_left)*number_position,charg_anim_ui_dimen.num_bottom};if (0 == bits) {if (raw_data_size == (charg_anim_ui_dimen.num_right - charg_anim_ui_dimen.num_left)*(charg_anim_ui_dimen.num_bottom - charg_anim_ui_dimen.num_top)*4) {bits = 32;} else if (raw_data_size == (charg_anim_ui_dimen.num_right - charg_anim_ui_dimen.num_left)*(charg_anim_ui_dimen.num_bottom - charg_anim_ui_dimen.num_top)*2) {bits = 16;} else {if (MTK_LOG_ENABLE == 1) {SLOGE("[show_animation_common: %s %d]Logo data error\n",__FUNCTION__,__LINE__);}return;}if (MTK_LOG_ENABLE == 1) {SLOGD("[show_animation_common: %s %d]bits = %d\n",__FUNCTION__,__LINE__, bits);}}if (MTK_LOG_ENABLE == 1) {SLOGD("[show_animation_common: %s %d]bits = %d\n",__FUNCTION__,__LINE__, bits);}fill_rect_with_content(fill_addr, battery_number_rect, number_pic_addr,phical_screen, bits);
}

fill_animation_dynamic()函数

在特定位置绘制特定图像。

/** Fill a rectangle with logo content**/
void fill_animation_dynamic(int index, RECT_REGION_T rect, void *fill_addr, void * dec_logo_addr, void * logo_addr, LCM_SCREEN_T phical_screen)
{LOGO_PARA_T logo_info;int raw_data_size;int logo_index = index;int logo_offset = -1;g_dec_logo_addr = dec_logo_addr;logo_offset = calculate_logo_offset(index, dec_logo_addr, logo_addr, phical_screen);if(logo_offset == -1){SLOGD("[calculate_logo_offset: %s %d]Resolution not supported\n",__FUNCTION__,__LINE__);return;}logo_index = logo_index + logo_offset;//检查logo索引的有效性if(check_logo_index_valid(logo_index, logo_addr, &logo_info) != CHECK_LOGO_BIN_OK)return;raw_data_size = decompress_logo((void*)logo_info.inaddr, (void*)dec_logo_addr, logo_info.logolen, (rect.right-rect.left)*(rect.bottom-rect.top)*4);if (MTK_LOG_ENABLE == 1) {SLOGD("[show_animation_common: %s %d]raw_data_size = %d\n",__FUNCTION__,__LINE__, raw_data_size);}if (0 == bits) {if (raw_data_size == (rect.right-rect.left)*(rect.bottom-rect.top)*4) {bits = 32;} else if (raw_data_size == (rect.right-rect.left)*(rect.bottom-rect.top)*2) {bits = 16;} else {if (MTK_LOG_ENABLE == 1) {SLOGE("[show_animation_common: %s %d]Logo data error\n",__FUNCTION__,__LINE__);}return;}if (MTK_LOG_ENABLE == 1) {SLOGD("[show_animation_common: %s %d]bits = %d\n",__FUNCTION__,__LINE__, bits);}}if (MTK_LOG_ENABLE == 1) {SLOGD("[show_animation_common: %s %d]bits = %d\n",__FUNCTION__,__LINE__, bits);}fill_rect_with_content(fill_addr, rect, dec_logo_addr, phical_screen, bits);
}

fill_animation_line()函数

/** Fill a line with special color**/
void fill_animation_line(int index, unsigned int capacity_grids, void *fill_addr,  void * logo_addr, LCM_SCREEN_T phical_screen)
{int logo_index = index;int logo_offset = -1;logo_offset = calculate_logo_offset(index, g_dec_logo_addr, logo_addr, phical_screen);if(logo_offset == -1){SLOGD("[calculate_logo_offset: %s %d]Resolution not supported\n",__FUNCTION__,__LINE__);return;}logo_index = logo_index + logo_offset;LOGO_PARA_T logo_info;int raw_data_size;if(line_pic_addr==NULL) {line_pic_addr=(unsigned short*)malloc(((charg_anim_ui_dimen.top_anim_right - charg_anim_ui_dimen.top_anim_left)*4)*sizeof(unsigned short));memset(line_pic_addr,0,(((charg_anim_ui_dimen.top_anim_right - charg_anim_ui_dimen.top_anim_left)*4)*sizeof(unsigned short)));}if(check_logo_index_valid(logo_index, logo_addr, &logo_info) != CHECK_LOGO_BIN_OK)return;line_pic_size= (charg_anim_ui_dimen.top_anim_right - charg_anim_ui_dimen.top_anim_left)*4;raw_data_size = decompress_logo((void*)logo_info.inaddr, (void*)line_pic_addr, logo_info.logolen, line_pic_size);if (MTK_LOG_ENABLE == 1) {SLOGD("[show_animation_common: %s %d]raw_data_size = %d\n",__FUNCTION__,__LINE__, raw_data_size);}if (0 == bits) {if (raw_data_size == (charg_anim_ui_dimen.top_anim_right - charg_anim_ui_dimen.top_anim_left)*4) {bits = 32;} else if (raw_data_size == (charg_anim_ui_dimen.top_anim_right  - charg_anim_ui_dimen.top_anim_left)*2) {bits = 16;} else {if (MTK_LOG_ENABLE == 1) {SLOGE("[show_animation_common: %s %d]Logo data error\n",__FUNCTION__,__LINE__);}return;}if (MTK_LOG_ENABLE == 1) {SLOGD("[show_animation_common: %s %d]bits = %d\n",__FUNCTION__,__LINE__, bits);}}RECT_REGION_T rect = {charg_anim_ui_dimen.cap_left, charg_anim_ui_dimen.cap_top, charg_anim_ui_dimen.cap_right, charg_anim_ui_dimen.cap_bottom};int i = capacity_grids;for(; i < charg_anim_ui_dimen.cap_bottom; i++){rect.top = i;rect.bottom = i+1;fill_rect_with_content(fill_addr, rect, line_pic_addr, phical_screen, bits);}
}

fill_rect_with_content()函数

指定的矩形区域内填充具有logo内容的像素数据。

/** Draw a rectangle region  with logo content****/void fill_rect_with_content(void *fill_addr, RECT_REGION_T rect, void *src_addr, LCM_SCREEN_T phical_screen, unsigned int bits)
{if (MTK_LOG_ENABLE == 1) {SLOGD("[show_logo_common: %s %d]\n",__FUNCTION__,__LINE__);}if (check_rect_valid(rect) != CHECK_RECT_OK)return;if (bits == 32) {if (phical_screen.fill_dst_bits == 16) {fill_rect_with_content_by_16bit_argb8888((unsigned short *)fill_addr, rect, (unsigned int *)src_addr, phical_screen);} else if (phical_screen.fill_dst_bits == 32){fill_rect_with_content_by_32bit_argb8888((unsigned int *)fill_addr, rect, (unsigned int *)src_addr, phical_screen, bits);} else {if (MTK_LOG_ENABLE == 1) {SLOGD("[show_logo_common %s %d]unsupported phical_screen.fill_dst_bits =%d\n",__FUNCTION__,__LINE__, phical_screen.fill_dst_bits );}}} else {if (phical_screen.fill_dst_bits == 16) {fill_rect_with_content_by_16bit_rgb565((unsigned short *)fill_addr, rect, (unsigned short *)src_addr, phical_screen);} else if (phical_screen.fill_dst_bits == 32){fill_rect_with_content_by_32bit_rgb565((unsigned int *)fill_addr, rect, (unsigned short *)src_addr, phical_screen, bits);} else {if (MTK_LOG_ENABLE == 1) {SLOGD("[show_logo_common %s %d]unsupported phical_screen.fill_dst_bits =%d\n",__FUNCTION__,__LINE__, phical_screen.fill_dst_bits );}}}
}

fill_rect_with_content_by_32bit_argb8888()函数

在一个指定的矩形区域内填充具有logo内容的32位色彩的像素数据。

/** Draw a rectangle region (32 bits perpixel) with logo content****/
void fill_rect_with_content_by_32bit_argb8888(unsigned int *fill_addr, RECT_REGION_T rect, unsigned int *src_addr, LCM_SCREEN_T phical_screen, unsigned int bits)
{LOG_ANIM("[show_logo_common: %s %d]\n",__FUNCTION__,__LINE__);int virtual_width = phical_screen.needAllign == 0? phical_screen.width:phical_screen.allignWidth;int virtual_height = phical_screen.height;int i = 0;int j = 0;unsigned int * dst_addr = fill_addr;unsigned int * color_addr = src_addr;for(i = rect.top; i < rect.bottom; i++){for(j = rect.left; j < rect.right; j++){color_addr = (unsigned int *)src_addr;src_addr++;switch (phical_screen.rotation){case 90:dst_addr = fill_addr + (virtual_width * j  + virtual_width - i - 1);break;case 270:dst_addr = fill_addr + ((virtual_width * (virtual_height - j - 1)+ i));break;case 180:// adjust fill in addressdst_addr = fill_addr + virtual_width * (virtual_height - i)- j-1-(virtual_width-phical_screen.width);break;default:dst_addr = fill_addr + virtual_width * i + j;}fill_point_buffer(dst_addr, *color_addr, phical_screen, bits);if((i == rect.top && j == rect.left) || (i == rect.bottom - 1 && j == rect.left) ||(i == rect.top && j == rect.right - 1) || (i == rect.bottom - 1 && j == rect.right - 1)){LOG_ANIM("[show_logo_common]dst_addr= 0x%08x, color_addr= 0x%08x, i= %d, j=%d\n", *dst_addr, *color_addr, i , j);}}}
}

fill_point_buffer()函数

填充屏幕单个像素点。

/** Fill one point address with  source color and color pixel bits** @parameter**/
void fill_point_buffer(unsigned int *fill_addr, unsigned int src_color, LCM_SCREEN_T phical_screen, unsigned int bits)
{if (32 == phical_screen.bits_per_pixel) {if (32 == bits) {if(16 == phical_screen.blue_offset) {*fill_addr = ARGB8888_TO_ABGR8888(src_color);} else {*fill_addr = src_color;}} else {if(16 == phical_screen.blue_offset) {*fill_addr = RGB565_TO_ARGB8888(src_color);} else {*fill_addr = RGB565_TO_ABGR8888(src_color);}}} else {LOG_ANIM("[show_logo_common %s %d]not support bits_per_pixel = %d \n",__FUNCTION__,__LINE__,(int)phical_screen.bits_per_pixel);}
}

客户需求定制

关机充电时,在电量小于等于5%时,显示"30分钟充电后打开电源"(韩文)

  1. 预制提示语资源

制作一张带客户需求字样的bmp图片,并以“wxganl”(视项目而定)开头命名,放入对应的目录中。

vendor\mediatek\proprietary\bootable\bootloader\lk\dev\logo\wxganl\

请添加图片描述

将处理后生成的raw文件添加进RESOURCE_OBJ_LIST列表(建议放在列表末尾)。

diff --git a/vendor/mediatek/proprietary/bootable/bootloader/lk/dev/logo/rules.mk b/vendor/mediatek/proprietary/bootable/bo
otloader/lk/dev/logo/rules.mk
index ab8bb064524..837e8268b27 100644
--- a/vendor/mediatek/proprietary/bootable/bootloader/lk/dev/logo/rules.mk
+++ b/vendor/mediatek/proprietary/bootable/bootloader/lk/dev/logo/rules.mk
@@ -95,7 +95,8 @@ RESOURCE_OBJ_LIST +=   \$(BOOT_LOGO_DIR)/$(1)/$(1)_kernel.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_low_battery01.raw \$(BOOT_LOGO_DIR)/$(1)/$(1)_low_battery02.raw \
-            $(BOOT_LOGO_DIR)/$(1)/$(1)_low_battery_remind.raw
+            $(BOOT_LOGO_DIR)/$(1)/$(1)_low_battery_remind.raw \
+            $(BOOT_LOGO_DIR)/$(1)/$(1)_bat_custom.rawendifendif
  1. 定义自定义图片索引值

根据raw文件在RESOURCE_OBJ_LIST列表中的位置,定义对应的索引值。

diff --git a/vendor/mediatek/proprietary/external/libshowlogo/cust_display.h b/vendor/mediatek/proprietary/external/libshow
logo/cust_display.h
index bf26861ac45..8f8b8830a9a 100644
--- a/vendor/mediatek/proprietary/external/libshowlogo/cust_display.h
+++ b/vendor/mediatek/proprietary/external/libshowlogo/cust_display.h
@@ -140,6 +140,9 @@#define LOGOS_COUNT_FAST_CHARGING          18#define LOGOS_COUNT_WIRELESS               29-
+//added by menghui.huang    start
+// custom picture index
+#define CUSTOM_PIC_INDEX        42
+//added by menghui.huang    end
  1. 描述绘制位置

屏幕坐标系是以横屏状态下(视项目而定)左上角为零点,右侧为x轴正方向,下侧为y轴正方向。

请添加图片描述

利用Windows自带的画图工具定位图片位置。本例中,(440, 640)是一个较好的位置。

请添加图片描述

查看图片属性确定下边界和右边界。

下边界 = 起始位置纵坐标 + 图片本身高度;本例中 下边界 = 640 + 39 = 679
右边界 = 起始位置横坐标 + 图片本身宽度; 本例中 右边界 = 440 + 404 = 844

请添加图片描述

在代码中定义对应的位置信息。

diff --git a/vendor/mediatek/proprietary/external/libshowlogo/show_animation_common.h b/vendor/mediatek/proprietary/external/libshowlogo/show_animation_common.h
index c9e2ac924bb..e09e514b730 100755
--- a/vendor/mediatek/proprietary/external/libshowlogo/show_animation_common.h
+++ b/vendor/mediatek/proprietary/external/libshowlogo/show_animation_common.h
@@ -69,6 +69,14 @@ typedef struct {// version_0 animation#define ANIM_V0_REGIONS  4#define ANIM_V0_SPACE_AFTER_REGION  4
+
+//added by menghui.huang     start
+#define CUSTOM_PIC_LEFT 440
+#define CUSTOM_PIC_TOP 640
+#define CUSTOM_PIC_RIGHT 844
+#define CUSTOM_PIC_BOTTOM 679
+//added by menghui.huang     end
+

定义矩形参数

// define the rectangle parameters
typedef struct {int left, top, right, bottom;
} RECT_REGION_T;
diff --git a/vendor/mediatek/proprietary/external/libshowlogo/show_animation_common.c b/vendor/mediatek/proprietary/external/libshowlogo/show_animation_
common.c
index a57a5cafede..9c0ad346569 100755
--- a/vendor/mediatek/proprietary/external/libshowlogo/show_animation_common.c
+++ b/vendor/mediatek/proprietary/external/libshowlogo/show_animation_common.cRECT_REGION_T percent_location_rect = {charg_anim_ui_dimen.percent_left,charg_anim_ui_dimen.percent_top,charg_anim_ui_dimen.percent_right,charg_anim_ui_dimen.percent_bottom};
+    RECT_REGION_T custom_location_rect = {CUSTOM_PIC_LEFT, CUSTOM_PIC_TOP, CUSTOM_PIC_RIGHT, CUSTOM_PIC_BOTTOM};
  1. 为自定义图片分配内存并初始化
diff --git a/vendor/mediatek/proprietary/external/libshowlogo/show_animation_common.c b/vendor/mediatek/proprietary/external/libshowlogo/show_animation_common.c
index a57a5cafede..9c0ad346569 100755
--- a/vendor/mediatek/proprietary/external/libshowlogo/show_animation_common.c
+++ b/vendor/mediatek/proprietary/external/libshowlogo/show_animation_common.c
@@ -103,6 +103,7 @@ int getValue(char* key, char* defValue);
+++ b/vendor/mediatek/proprietary/external/libshowlogo/show_animation_common.c
@@ -103,6 +103,7 @@ int getValue(char* key, char* defValue);static unsigned short  *number_pic_addr;static unsigned short  *line_pic_addr;static unsigned short  *percent_pic_addr;
+static unsigned short  *custom_pic_addr;static unsigned short  *top_animation_addr;static  int number_pic_size; //size
@@ -1141,11 +1142,18 @@ void fill_animation_battery_new(int capacity, void *fill_addr, void * dec_logo_apercent_pic_addr=(unsigned short*)malloc(((charg_anim_ui_dimen.percent_right - charg_anim_ui_dimen.percent_left)*(charg_anim_ui_dimen.percent_bottom - charg_anim_ui_dimen
.percent_top)*4)*sizeof(unsigned short));memset(percent_pic_addr,0,(((charg_anim_ui_dimen.percent_right - charg_anim_ui_dimen.percent_left)*(charg_anim_ui_dimen.percent_bottom - charg_anim_ui_dimen.percent_top)*
4)*sizeof(unsigned short)));}
+    added by menghui.huang    start
+    if (custom_pic_addr==NULL) {
+        custom_pic_addr=(unsigned short*)malloc(((CUSTOM_PIC_RIGHT - CUSTOM_PIC_LEFT)*(CUSTOM_PIC_BOTTOM - CUSTOM_PIC_TOP)*4)*sizeof(unsigned short));
+        memset(custom_pic_addr,0,(((CUSTOM_PIC_RIGHT - CUSTOM_PIC_LEFT)*(CUSTOM_PIC_BOTTOM - CUSTOM_PIC_TOP)*4)*sizeof(unsigned short)));
+    }
+    //added by menghui.huang    end
  1. 在电量<=5%时,为指定内存区域填充图像数据
@@ -1160,6 +1168,12 @@ void fill_animation_battery_new(int capacity, void *fill_addr, void * dec_logo_afill_animation_logo(LOW_BAT_ANIM_START_0 + charging_low_index, fill_addr, dec_logo_addr, logo_addr,phical_screen);fill_animation_number(NUMBER_PIC_START_0 + capacity, 1, fill_addr, logo_addr, phical_screen);fill_animation_dynamic(NUMBER_PIC_PERCENT, percent_location_rect, fill_addr, percent_pic_addr, logo_addr, phical_screen);
+        //added by menghui.huang    start
+        if (capacity <= 5)
+        {
+            fill_animation_dynamic(CUSTOM_PIC_INDEX, custom_location_rect, fill_addr, custom_pic_addr, logo_addr, phical_screen);
+        }
+        //added by menghui.huang    end
  1. 效果

请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/353655.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

中医药人工智能大模型正式启动

6月15日&#xff0c;在横琴粤澳深度合作区举行的中医药广东省实验室&#xff08;以下简称横琴实验室&#xff09;第一届学术委员会第一次会议暨首届横琴中医药科技创新大会上&#xff0c;中医药横琴大模型、中药新药智能自动化融合创新平台同时启动。这也是该实验室揭牌半年来取…

Stable Diffusion WebUI 使用ControlNet:IP-Adapter保持生图的角色一致性

IP-Adapter-FaceID可以在保持人脸一致的条件下生成各种风格的图像。 下载 IP Adapter 需要的 Face ID 模型和 Lora 下载地址&#xff1a;https://huggingface.co/h94/IP-Adapter-FaceID/ 下载 ip-adapter-faceid-plusv2_sd15.bin 和 ip-adapter-faceid-plusv2_sd15_lora.saf…

瑞典农业科学大学《Nature Geoscience》(IF=18)!揭示北方森林碳汇对干旱的响应机制!

本文首发于“生态学者”微信公众号&#xff01; 北方森林覆盖了地球陆地面积的11%&#xff0c;储存了全球陆地碳储量的约三分之一。因此&#xff0c;它们被认为是减缓气候变化政策的一个重要因素。然而&#xff0c;环极寒带地区是气候变化速度最快的地区。这包括更频繁和更严重…

入门 Axure RP 9 | 原型设计基础教程

选择正确的原型设计工具并非易事&#xff0c;Axure RP 9能够快速完成原型设计。原型设计是一种经过时间考验的方法&#xff0c;可以将你的设计快速放置在用户的设备并交到他们手中。替代Axure RP 9的原型设计工具即时设计是一个完全集成的协同设计工具&#xff0c;无需使用不同…

计算机专业毕设-校园二手交易平台

1 项目介绍 基于SpringBoot的校园二手交易平台&#xff1a;前端Freemarker&#xff0c;后端 SpringBoot、Jpa&#xff0c;系统用户分为两类&#xff0c;管理员、学生&#xff0c;具体功能如下&#xff1a; 管理员&#xff1a; 基本功能&#xff1a;登录、修改个人信息、修改…

“AI引擎”澎湃动力!深圳机场携手实在智能打造民航财务数字员工

近日&#xff0c;深圳机场集团&#xff08;000089&#xff09;与实在智能达成合作&#xff0c;引入了业内领先的平台级自动化产品——实在RPA数字员工&#xff0c;部署实在智能集“自动化平台开箱即用解决方案咨询”为一体的数字员工解决方案&#xff0c;实现纳税申报、报表制作…

海思SS928/SD3403开发笔记1——使用串口调试开发板

该板子使用串口可以调试&#xff0c;下面是win11 调试 该板子步骤 1、给板子接入鼠标、键盘、usb转串口 2、下载SecureCRT&#xff0c;并科学使用 下载地址&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/11dIkZVstvHQUhE8uS1YO0Q 提取码&#xff1a;vinv 3、安装c…

Chromium 开发指南2024 Mac篇-安装和配置depot_tools工具(三)

1.引言 在前两篇指南中&#xff0c;我们详细介绍了在 macOS 环境下编译 Chromium 所需的硬件要求和系统依赖&#xff0c;并具体讲解了如何正确安装和配置 Xcode。通过这些步骤&#xff0c;您已经为编译 Chromium 打下了坚实的基础。然而&#xff0c;编译 Chromium 还需要配置一…

哪种考勤机好用,常见好用的考勤机种类

哪种考勤机好用&#xff0c;常见好用的考勤机种类 用考勤机完成上下班打卡制度&#xff0c;极大地为人事对公司的管理提供了便利。不同种类的考勤机均有各自的长处&#xff0c;那么究竟哪种考勤机比较好用呢&#xff1f;其中&#xff0c;智能云考勤机能够实现异地手机打卡&…

Window常用的脚本有哪些?快来看看有哪些是你正在用的!(欢迎评论补充~)

前言 在日常开发中&#xff0c;如果能熟练掌握以下这些使用频率很高的脚本&#xff0c;那工作起来真的是手拿把攥&#xff0c;事半功倍&#xff0c;接下来给大家介绍一些我们日常使用率很高的一些脚本&#xff01; 常用脚本(Batchfile & VBScript) 1.一键启动.bat 一次…

常见的网络设备

引入 园区网络安全部署场景 1、路由器&#xff1a; 跨网段通信设备 。 2、交换机&#xff1a; 同网段或跨网段通信设备。 3、AntiDDoS &#xff1a; DDoS 防御系统&#xff0c;通常旁挂部署于网络出口处&#xff0c; 位于防火墙上游&#xff0c;用于减轻防火墙报文处理负担。 …

C/S、B/S架构(详解)

一、CS、BS架构定义 CS架构&#xff08;Client-Server Architecture&#xff09;是一种分布式计算模型&#xff0c;其中客户端和服务器之间通过网络进行通信。在这种架构中&#xff0c;客户端负责向服务器发送请求&#xff0c;并接收服务器返回的响应。服务器则负责处理客户端的…

failed to create network xxxx: Error response from daemon

问题描述&#xff1a; 启动项目时&#xff0c;docker内部网络冲突。 解决方案&#xff1a; 1.删除所有docker容器&#xff08;强制删除一个或多个容器&#xff0c;即使它们正在运行&#xff09; docker rm -f $(docker ps -aq) 2.验证docker容器是否删除成功 docker ps --…

Kubernetes(K8s)

K8s是为了解决微服务架构中大量容器部署和管理的问题。 希腊语“舵手”的意思。K8s是一个开源的容器编排平台&#xff0c;用于自动部署、扩展和管理容器化应用程序。最初由Google设计并捐赠给CNCF来维护。 K8s需要部署在至少2台机器的硬件集群环境中&#xff0c;K8s也叫云原生操…

YOLOv8旋转目标检测Yolov8n-obb详细实例+rolabelimg

一、Yolov8环境搭建 首先创建虚拟环境下载安装&#xff08;其实就是yolov8的环境&#xff09;再大概写一下步骤&#xff0c;没有想详细的看本人另外一篇&#xff1a;YOLOv8环境搭建_yolov8环境配置-CSDN博客 1、下载安装anaconda 2、创建虚拟环境 conda create -n my_yolov8…

第29讲:Ceph集群使用RBD块存储设备与K8S的PV集成

文章目录 1.Ceph集群使用RBD块存储与K8S集成简介2.Ceph集群RBD块存储与K8S PV存储卷集成2.1.创建K8S集群PV使用的块存储2.2.创建K8S集群访问RBD块存储设备的认证用户2.3.将认证用户的Key存储在K8S Secret资源中2.4.在K8S集群的所有节点中安装Ceph命令2.5.创建PV及PVC资源使用RB…

【算法训练记录——Day31】

Day31——贪心算法Ⅰ 1. 理论1.1 什么是贪心1.2 什么时候用贪心1.3 贪心算法一般步骤 2.leetcode455——分发饼干3.leetcode376——摆动序列 目标&#xff1a; 理论leetcode455——分发饼干leetcode376——摆动序列leetcode53 —— 最大字序和 1. 理论 算法随想录——贪心 1…

Jenkins+K8s实现持续集成(三)

接上面一篇JenkinsK8s实现持续集成&#xff08;二&#xff09;&#xff0c;K8s创建秘钥。 看secret kubectl get secret 删除secret kubectl delete secret hello-secret -n train 创建secret kubectl create secret docker-registry hello-secret --docker-server镜像仓库…

3D开发工具HOOPS为BIM应用提供支持:复杂大模型实现Web端轻量化!

在数字化转型的浪潮中&#xff0c;Tech Soft 3D以其HOOPS SDK工具包&#xff0c;为软件开发人员提供了强大的支持。这一工具包不仅支持Windows、Linux、OSX和移动平台等多样化的操作系统&#xff0c;还使得开发人员能够构建出庞大而复杂的建筑和BIM应用程序。HOOPS SDK的多格式…

基于EasyAnimate模型的视频生成最佳实践

EasyAnimate是阿里云PAI平台自主研发的DiT的视频生成框架&#xff0c;它提供了完整的高清长视频生成解决方案&#xff0c;包括视频数据预处理、VAE训练、DiT训练、模型推理和模型评测等。本文为您介绍如何在PAI平台集成EasyAnimate并一键完成模型推理、微调及部署的实践流程。 …