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

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

基于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.mzph.cn/bicheng/29851.shtml

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

相关文章

【软件工程】【22.10】p2

关键字&#xff1a; 软件开发基本途径、初始需求发现技术、UML表达事物之间关系、RUP需求获取基本步骤、项目过程建立涉及工作、项目规划过程域的意图和专用目标 判定表、分支覆盖、条件覆盖 三、简答 四、应用 这里条件覆盖有待商榷

SpringBoot配置第三方专业缓存技术jetcache方法缓存方案

jetcache方法缓存 我们可以给每个方法配置缓存方案 JetCache 是一个基于 Java 的缓存库&#xff0c;支持多种缓存方案和缓存策略&#xff0c;主要用于提升应用程序的性能和响应速度。它提供了多种缓存模式和特性&#xff0c;可以根据需求选择合适的缓存方案。 JetCache 的主…

问题解决:局域网下多台电脑实现共享打印机

看了很多篇解决措施&#xff0c;都没有解决&#xff0c;自己鼓弄了好久&#xff0c;终于解决了&#xff0c;如下步骤所示&#xff0c;实测好用。 首先先保证本电脑已打开网络共享 其次关闭防火墙&#xff08;有时会出现奇怪问题&#xff0c;最好关闭&#xff09; 接着访问IP…

Scikit-Learn支持向量机回归

Scikit-Learn支持向量机回归 1、支持向量机回归1.1、最大间隔与SVM的分类1.2、软间隔最大化1.3、支持向量机回归1.4、支持向量机回归的优缺点2、Scikit-Learn支持向量机回归2.1、Scikit-Learn支持向量机回归API2.2、支持向量机回归初体验2.3、支持向量机回归实践(加州房价预测…

TikTok账号养号的流程分享

对于很多刚开始运营TikTok的新手小白来说&#xff0c;都会有一个同样的疑问&#xff0c;那就是&#xff1a;TikTok到底需不需要养号&#xff1f;这里明确告诉大家是需要养号的&#xff0c;今天就把我自己实操过的养号经验和策略总结出来&#xff0c;分享给大家。 一、什么是Ti…

国产24位I2S输入+192kHz立体声DAC音频数模转换器CJC4344

CJC4344是一款立体声数模转换芯片&#xff0c;内含插值滤波器、multi bit数模转换器、输出模拟滤波器。CJC4344系列支持大部分的音频数据格式。CJC4344基于一个带线性模拟低通滤波器的四阶multi-bitΔ-Σ调制器&#xff0c;而且本芯片可以通过检测信号频率和主时钟频率&#xf…

【面试八股总结】Redis数据结构及底层实现

一、五种基本数据结构 Redis 提供了丰富的数据类型&#xff0c;常见的有五种数据类型&#xff1a;String&#xff08;字符串&#xff09;&#xff0c;Hash&#xff08;哈希&#xff09;&#xff0c;List&#xff08;列表&#xff09;&#xff0c;Set&#xff08;集合&#xff0…

C语言中的内存动态管理

1.为什么有动态内存管理 int a20;//开辟4个字节 int arr[10]{0};//开辟40个字节 上述的代码有两个特点 1.开辟空间的大小是固定的。 2.数组在申明的时候已经固定了大小&#xff0c;无法更改。 这样写代码不够灵活&#xff0c;所以c语言中引入了动态内存管理&#xff0c;让程序…

Springboot整合Kafka消息队列服务实例

一、Kafka相关概念 1、关于Kafka的描述 Kafka是由Apache开源&#xff0c;具有分布式、分区的、多副本的、多订阅者&#xff0c;基于Zookeeper协调的分布式处理平台&#xff0c;由Scala和Java语言编写。通常用来搜集用户在应用服务中产生的动作日志数据&#xff0c;并高速的处…

Milvus 2.4 向量库安装部署

1、linux 已有docker环境 2、安装fio命令 yum install -y fio 2、mkdir test-data fio --rwwrite --ioenginesync --fdatasync1 --directorytest-data --size2200m --bs2300 --namemytest ctrlc 3、lscpu 4、docker -v 6、安装docker compose组件 yum -y install python3-…

Maven下载安装、环境配置(超详细)(包括Windows、IDEA)

目录 一、引言 二、下载和安装 Maven &#xff08;1&#xff09;首先保证 Java 的环境是正常的。 1、电脑桌面上右击 " 此电脑 "&#xff0c;点击属性。 2、点击高级系统设置。 3、点击环境变量。 4、找到系统变量中的 Path。 5、点击新建&#xff0c;然后把…

深度剖析ElasticSearch分页原理与深分页问题|ES深分页问题|ES分页原理剖析

文章目录 ES分页|Paginate search resultsES深分页的问题一页获取数据量太大&#xff0c;报错分页深度太大&#xff0c;报错官方解释 其他解决方案Search after解决两个问题 有没有深分页查询的必要性&#xff1f;search after & PIT的使用方式1.创建pit2.首次查询3.之后的…

【C++】#20,#21

#20类和对象 #include <iostream>using namespace std;class Box{public: //公有 double length; //ctrle复制本行 double width;double height;void getVolume(){ //方法带&#xff08;&#xff09; cout<<"盒子体积为&#xff1a;"<<le…

我在高职教STM32——LCD液晶显示(1)

大家好&#xff0c;我是老耿&#xff0c;高职青椒一枚&#xff0c;一直从事单片机、嵌入式、物联网等课程的教学。对于高职的学生层次&#xff0c;同行应该都懂的&#xff0c;老师在课堂上教学几乎是没什么成就感的。正因如此&#xff0c;才有了借助 CSDN 平台寻求认同感和成就…

十、数据结构(图的基础)

文章目录 什么是图图的分类图算法的复杂度 图的模拟怎么储存一个图邻接矩阵&#xff1a;邻接矩阵的定义方式优劣分析 邻接表优劣分析实现代码 链式前向星实现代码优劣分析 图的遍历某个点的连通性拓扑排序1.拓扑排序的概念2.图的入度和出度3.基于 B F S BFS BFS的拓扑排序复杂度…

uniapp公用返回组件

uniapp写一个公用的头部组件&#xff0c;包含home和返回。 页面中的引用 2.在components文件夹下&#xff0c;新建一个navBar.vue <template><view class"view-wrap"><view :style"{ height: barHeight }"></view><view cla…

web前端之vue一键部署的shell脚本和它的点.bat文件、海螺AI、ChatGPT

MENU 前言vite.config.ts的配置deploy文件夹的其他内容remote.shpwd.txtdeploy.bat 前言 1、在src同级新建deploy.bat文件&#xff1b; 2、在src同级新建deploy文件夹&#xff0c;文件夹中新建pwd.txt和remote.sh文件&#xff1b; 3、配置好后&#xff0c;直接双击deploy.bat文…

Flat Ads:轻松玩转Kwai广告,开启全球营销新篇章

在当今数字化时代,短视频平台已成为人们生活中不可或缺的一部分。其中,快手旗下的一款海外短视频应用——Kwai 在海外新兴的拉美、中东、东南亚等多个市场迅速崛起并赢得了广大用户的喜爱。 作为全球头部短视频平台,Kwai 已遍布世界30多个国家,月活超过10亿,APP下载量位居拉美、…

怎么给软件做数字证书签名?

要想让软件获得身份并让计算机识别软件发布者就需要申请数字证书&#xff0c;CA机构严格实名认证后签发的数字证书就可以对指定的软件签名使用。 代码签名是使用数字证书对软件、固件、脚本和可执行文件进行签名的过程&#xff0c;旨在向最终用户和客户保证代码的完整性和真实…

【深度学习驱动流体力学】剖析流体力学可视化paraview原理

目录 1.paraview版本2.配置过程检查插件库文件配置 ParaView 环境变量启动 ParaView 并检查插件3.可视化测试插件功能 3.加载数据进行可视化第一步: 导入案例第二步:查看当前目录未更新前的内容第三步:使用 blockMesh 命令生成腔体案例的网格第四步:运行仿真icoFoam第五步:使用…