关机充电图标修改

关机充电图标修改

这几天解一个defect,主要需求是修改关机充电的图标,把原来的样式进行修该成如图1所示样子:

图 1
修改后充电各个阶段具体要求如图2所示:

图 2
本来的样式为蓝色电池,充电动画为电量波动状,指望修改后变成5格滚动状。(其实我的感受仍是本来的好看,而新样式设计是一个UE作,反正以为她这个设计很脑残并且估计是抄袭把别的手机的样式吧,并且这个UE很坑壁,给的图片根本不符合要求,后面还要和她各类斯比各类gloomy).shell

分析以下:bash

  • 首先,须要找到原来版本充电图片所在位置,而后用新的图片替换掉原版本的充电图片。
    在原版本中,充电logo图片其实是由多个位图组合起来的。如图中充电电量95%则是由3张图片组合而成,而蓝色的电池部分是由一个白的电池形状图片和蓝色条状图片组合起来的。修改logo图标即便用大小尺寸同样的图片替换掉原来图片,在替换图片时,最好是按原来图片的方式来命令新的图片名字,这样就能够不用修改具体代码的逻辑了。(后面发现仍是要该部分代码)
  • 而后,和原版图标相比新样式的logo图标,各个位图的相对位置有所更改。须要找到控制位图坐标的代码并进行修改调整。
  • 最后,在链接充电器时,首先须要显示链接充电器的logo图片一秒,而后才显示充电电量的logo图标,因此须要在显示充电电量图片前加入显示该图片的逻辑。(其实本来的关机充电中,链接充电器会显示一张logo,应该是改此处)

1. 关机充电main函数

关机充电实际上是一个单独的应用,主要是由init进程开启,充电部分相关源码主要在vendor/mediatek/proprietary/external/charger/目录下。应用的入口在文件vendor/mediatek/proprietary/external/charger/main.cpp中,首先看看main函数。less

 
 
 
 
int main(int argc, char *argv[]) { set_draw_anim_mode(1); pthread_mutex_init(&lights_mutex, NULL); setpriority(PRIO_PROCESS, 0, -20); FILE *oom_adj = fopen("/proc/self/oom_adj", "w"); if (oom_adj) { fputs("-17", oom_adj); fclose(oom_adj); } //stop_backlight(); KPOC_LOGI("stop_backlight 1\n"); bootlogo_init(); alarm_control(); charging_control(); 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;}

2. 函数set_draw_anim_mode()

为设置充电动画的绘制模式,其中有2个模式:ide

  • DRAW_ANIM_MODE_SURFACE
  • DRAW_ANIM_MODE_SURFACE

3. 函数pthread_mutex_init();

这个函数做用没看懂,略过。函数

4. 函数bootlogo_init()

这个函数从名字上就能够看出主要是作一些初始化工做,主要包括充电动画版本(mtk有2个充电动画的版本)、动画绘制方式以及其余参数的初始化,下面看看这个函数的具体实现。oop

 
 
 
 
void bootlogo_init(){ KPOC_LOGI("[ChargingAnimation: %s %d]\n",__FUNCTION__,__LINE__); sync_anim_version(); anim_init();}

在bootlogo_init();中有2个函数动画

  • sync_anim_version();

主要是设定关机充电充电动画的版本,
version 0: show 4 recatangle growing animation without battery number
version 1: show wave animation with battery number
因此在这里控制了究竟是用哪一种充电动画ui

  • anim_init();

充电动画logo初始化,应该就是得到充电图片的在文件系统中的位置吧,方便后面调用指定图片。spa

5. 函数alarm_control();

这个函数做用没看懂,略过。.net

6. 函数charging_control();

这个函数比较重要,主要控制充电时led灯和动画效果的,具体来看看它的代码实现。

 
 
 
 
void charging_control(){ int ret = 0; pthread_attr_t attr, attrd, attrl; pthread_t uevent_thread, draw_thread, light_thread; //charging led control if (!is_charging_source_available()) { 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); }}

在该函数中,最开始对led进行检测,而后是对线程资源的初始化,后面分别开了2个线程,第一个线程主要是操做led灯的,第二个线程是操做充电动画效果的。

6.1 draw_thread_routine()

接下来看看函数draw_thread_routine()作了些什么。

  • 首先,是一些变量值的初始化,
  • 而后,进入while循环,这个while循环应该至始至终都在运行,先是等了charging_source_waiting_interval_ms长时间,保证charging_source_available准备好(实际上并无真的等charging_source_waiting_interval_ms长时间,只要usb_online、ac_online、wireless_online、vchr中有一个知足就会跳出等待状态),同时if(firstTime)语句只会跑一次,后面都不会执行了。以后跑充电动画,在动画跑完后执行stop_backlight();看名字该是熄灭背光灯,这时候背光灯熄灭后,还执行了 bootlogo_show_charging(bc, 1);显示图片,由于背光灯熄灭了,这个图片是看不到的。那它这么作事为了干什么呢,多是为了等下次背光灯亮起来而当前图片还没显示出来的状况下,先用bootlogo_show_charging(bc, 1);显示出图片作个缓冲吧。
  • 最后,应该是经过锁阻塞线程,让这个while循环中止在某个状态,当阻塞条件解除后继续while循环(或者说继续播放充电动画,固然这只是猜想,其实没看懂while循环后面部分那些线程锁的做用)。
 
 
 
 
static void* draw_thread_routine(void *arg){ int i, bc, bc_offset = 0; int fd_fb = -1, err =0; char buf[PROPERTY_VALUE_MAX]; char filename[32] = {0}; // protect the following critical section for the 1st time pthread_mutex_lock(&mutex); do { KPOC_LOGI("draw thread working...\n"); // move here to avoid suspend when syncing with surfaceflinger if(firstTime){ // make sure charging source online when in KPOC mode // add 2s tolerance if(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 value bc = get_capacity(); //动画播放的函数 draw_with_interval(bootlogo_show_charging, bc, nChgAnimDuration_msec, nCbInterval_msec); stop_backlight(); // @@@ draw fb again to refresh ddp bootlogo_show_charging(bc, 1); /* make fb blank */ snprintf(filename, sizeof(filename), "/dev/graphics/fb0"); 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_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_unlock(&mutex); KPOC_LOGI("draw thread waiting...\n"); pthread_mutex_lock(&mutex); pthread_cond_wait(&cond, &mutex); } while(1); pthread_exit(NULL); return NULL;}

6.2 draw_with_interval()

这个函数功能主要是设置播放充电动画时长和动画图片间时间间隔的

  • 参数1:void (*func)(int, int) 这个就是进行图片显示的函数,经过它循环调用它实现动画效果
  • 参数2:int bc 这个参数没搞懂是作什么用的
  • 参数3:int total_time_msec 看名字就知道是播放动画的总时长
  • 参数4:int interval_msec 上一个图片和下一个图片之间的时间间隔
 
 
 
 
// total_time : ms// interval : msstatic 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 = -1, err = 0; char filename[32] = {0}; gettimeofday(&start, NULL); /*这里的while循环就是动画效果的实现,不断的调用显示不一样图片的函数来达到动态效果,当播放时长达到total_time_msec设定值或者有power键按下,跳出while循环中止动画效果*/ while(!time_exceed(start, total_time_msec) && !key_trigger_suspend) { // check if need to draw animation before performing drawing if (!is_charging_source_available()) return; if (!resume_started) { resume_started = 1; request_suspend(false); /* make fb unblank */ snprintf(filename, sizeof(filename), "/dev/graphics/fb0"); 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(200*1000); start_backlight(); } KPOC_LOGI("draw_with_interval... key_trigger_suspend = %d\n",key_trigger_suspend); /*这里就上一个图片和下一个图片之间的时间间隔,经过usleep();实现,它是以微秒为单位的。若是设置的时间长,播放的速度就比较慢,若是设置的时间短,播放的速度就比较快*/ usleep(interval_msec*1000); }}

6.3 bootlogo_show_charging()

而后是函数bootlogo_show_charging,就是经过它来显示充电动画的图片和显示充电电量的。

 
 
 
 
/** Show charging animation with battery capacity * */void bootlogo_show_charging(int capacity, int cnt){ KPOC_LOGI("[ChargingAnimation: %s %d]%d, %d",__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);}

show_charger_ov_logo();和 show_low_battery();分别显示电压太高的图片和低电量图片,若是出现这2个状况中一个,就return;,程序就不在向下走了,不然根据当前的电量来显示不的动画效果。

6.4 show_battery_capacity()

show_battery_capacity一样是在根据不一样的动画版本(version 0 or version 1)来决定如何在屏幕上显示动画,

 
 
 
 
/* * 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(MTK_PUMP_EXPRESS_SUPPORT) || defined(MTK_PUMP_EXPRESS_PLUS_SUPPORT) || defined(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); }#else fill_animation_battery_by_ver(capacity, (void *)fb_addr, dec_logo_addr, logo_addr, phical_screen, show_animationm_ver);#endif anim_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(MTK_PUMP_EXPRESS_SUPPORT) || defined(MTK_PUMP_EXPRESS_PLUS_SUPPORT) || defined(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); }#else fill_animation_battery_by_ver(capacity, (void *)outBuffer.bits, dec_logo_addr, logo_addr, phical_screen, show_animationm_ver);#endif surface->unlockAndPost(); } }}

6.5 fill_animation_battery_by_ver()

在vendor/mediatek/proprietary/external/libshowlogo/show_animation_common.c文件中的fill_animation_battery_by_ver方法控制关机充电的样式,根本不一样的version值使用不一样充电动画,方法具体实现以下。

 
 
 
 
/* * 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; }}

而后继续查找show_animationm_ver赋值状况,能够看到文件开始位置有以下赋值语句:

 
 
 
 
/* * Get the defined charging animation version * */void sync_anim_version(){ dprintf(INFO, "[lk logo: %s %d]\n",__FUNCTION__,__LINE__);#ifdef ANIMATION_NEW show_animationm_ver = VERION_NEW_ANIMATION;#else show_animationm_ver = VERION_OLD_ANIMATION; dprintf(INFO, "[lk logo %s %d]not define ANIMATION_NEW:show old animation \n",__FUNCTION__,__LINE__);#endif}

而宏定义ANIMATION_NEW是在文件vendor/mediatek/proprietary/external/libshowlogo/cust_display.h中定义的。也就是说若是定义了字段ANIMATION_NEW,则使用fill_animation_battery_new动画,不然使用fill_animation_battery_old。无论使用哪一个充电动画效果,2个方法都须要使用图片组合来达到动画的效果,而图片的存放位置在一个名为logo的文件加中。名为logo的文件夹可能会比较多,具体使用哪一个文件夹中的图片须要根据具体编译的项目决定,同时在device/jrdcsh[project]/ProjectConfig.mk文件中,看到BOOT_LOGO = fhd;LCM_HEIGHT =1920;LCM_WIDTH=1080;这3个字段,分别表示存放logo图片的文件加名以及手机所用屏幕分辨率。若是须要客制化这些图片,须要用新logo图片替换掉原图片。(最开始作的时候没找对路径因此替换图片后仍是没有效果,主要是许多公司都会对基线代码添加定制值,项目最终使用的是定制化代码中fhd文件中的logo图标,因此必定要找对logo图标存储的文件夹再替换)。fill_animation_battery_new方法和fill_animation_battery_old方法使用到的图片共40张。

  • 低电量充电显示的动画是由[fhd_bat_10_01.bmp~ fhd_bat_10_01.bmp]这10张静态图片组成,针对verion 1.

  • 充电背景图片[fhd_bat_bg.bmp] 共1张,针对verion 1.

  • 正常充电填充图片[fhd_bat_img.bmp] 共1张,针对verion 1.

  • 充电时动画显示是由[fhd_bat_animation_01.bmp~ fhd_bat_animation_10.bmp] 这10张静态图片组成,针对verion 1.

  • 数字图片[fhd_num_0.bmp~ fhd_num_9.bmp]共10张,,针对verion 1.

  • 百分比图片[fhd_mun_percent.bmp] 共1张 ,针对verion 1.

  • 100%电量图[fhd_bat_100.bmp] 共1张 ,针对verion 1.

  • 低电量图片[fhd_low_battery.bmp] 共1张 ,未见过此状况 。

  • 过电压图片[fhd_change_ov.bmp] 共1张,未见过此状况 。

  • 电压太低的图片[fhd_low_voltage.bmp] 共1张,未见过此状况 。

  • Kernel图片[fhd_kernal.bmp] 共1张 ,

  • 关机插入充电器显示第一张图片[fhd_uboot.bmp] 共1张 ,mt_disp_show_boot_logo();方法调用,入口函数为platform_init();

  • 图片fhd_battery[fhd_battery.bmp]共1张,由方法fill_animation_battery_old调用,针对verion 0

而这些图片都由脚本vendor/jrdcom/build/common/update_logo.sh打包为一个文件,脚本具体以下。

 
 
 
 
#!/bin/bashif [ "$1" = "" ]; then echo "Please input resolution," echo "Such as: qvga, wqvga, wvga, hvga" exitfip=${1}product_path=${2}logo_path=${3}output_path=${4}boot_logo=${5}${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp0.raw ${logo_path}/$p/"${boot_logo}_uboot".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp1.raw ${logo_path}/$p/"${boot_logo}_battery".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp2.raw ${logo_path}/$p/"${boot_logo}_low_battery".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp3.raw ${logo_path}/$p/"${boot_logo}_charger_ov".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp4.raw ${logo_path}/$p/"${boot_logo}_num_0".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp5.raw ${logo_path}/$p/"${boot_logo}_num_1".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp6.raw ${logo_path}/$p/"${boot_logo}_num_2".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp7.raw ${logo_path}/$p/"${boot_logo}_num_3".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp8.raw ${logo_path}/$p/"${boot_logo}_num_4".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp9.raw ${logo_path}/$p/"${boot_logo}_num_5".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp10.raw ${logo_path}/$p/"${boot_logo}_num_6".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp11.raw ${logo_path}/$p/"${boot_logo}_num_7".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp12.raw ${logo_path}/$p/"${boot_logo}_num_8".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp13.raw ${logo_path}/$p/"${boot_logo}_num_9".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp14.raw ${logo_path}/$p/"${boot_logo}_num_percent".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp15.raw ${logo_path}/$p/"${boot_logo}_bat_animation_01".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp16.raw ${logo_path}/$p/"${boot_logo}_bat_animation_02".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp17.raw ${logo_path}/$p/"${boot_logo}_bat_animation_03".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp18.raw ${logo_path}/$p/"${boot_logo}_bat_animation_04".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp19.raw ${logo_path}/$p/"${boot_logo}_bat_animation_05".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp20.raw ${logo_path}/$p/"${boot_logo}_bat_animation_06".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp21.raw ${logo_path}/$p/"${boot_logo}_bat_animation_07".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp22.raw ${logo_path}/$p/"${boot_logo}_bat_animation_08".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp23.raw ${logo_path}/$p/"${boot_logo}_bat_animation_09".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp24.raw ${logo_path}/$p/"${boot_logo}_bat_animation_10".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp25.raw ${logo_path}/$p/"${boot_logo}_bat_10_01".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp26.raw ${logo_path}/$p/"${boot_logo}_bat_10_02".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp27.raw ${logo_path}/$p/"${boot_logo}_bat_10_03".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp28.raw ${logo_path}/$p/"${boot_logo}_bat_10_04".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp29.raw ${logo_path}/$p/"${boot_logo}_bat_10_05".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp30.raw ${logo_path}/$p/"${boot_logo}_bat_10_06".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp31.raw ${logo_path}/$p/"${boot_logo}_bat_10_07".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp32.raw ${logo_path}/$p/"${boot_logo}_bat_10_08".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp33.raw ${logo_path}/$p/"${boot_logo}_bat_10_09".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp34.raw ${logo_path}/$p/"${boot_logo}_bat_10_10".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp35.raw ${logo_path}/$p/"${boot_logo}_bat_bg".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp36.raw ${logo_path}/$p/"${boot_logo}_bat_img".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp37.raw ${logo_path}/$p/"${boot_logo}_bat_100_".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp38.raw ${logo_path}/$p/"${boot_logo}_kernel".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp39.raw ${logo_path}/$p/"${boot_logo}_low_voltage".bmp${product_path}/vendor/jrdcom/build/jrdtools/zpipe -l 9 ${output_path}/"${p}".raw ${output_path}/temp0.raw ${output_path}/temp1.raw ${output_path}/temp2.raw ${output_path}/temp3.raw ${output_path}/temp4.raw ${output_path}/temp5.raw ${output_path}/temp6.raw ${output_path}/temp7.raw ${output_path}/temp8.raw ${output_path}/temp9.raw ${output_path}/temp10.raw ${output_path}/temp11.raw ${output_path}/temp12.raw ${output_path}/temp13.raw ${output_path}/temp14.raw ${output_path}/temp15.raw ${output_path}/temp16.raw ${output_path}/temp17.raw ${output_path}/temp18.raw ${output_path}/temp19.raw ${output_path}/temp20.raw ${output_path}/temp21.raw ${output_path}/temp22.raw ${output_path}/temp23.raw ${output_path}/temp24.raw ${output_path}/temp25.raw ${output_path}/temp26.raw ${output_path}/temp27.raw ${output_path}/temp28.raw ${output_path}/temp29.raw ${output_path}/temp30.raw ${output_path}/temp31.raw ${output_path}/temp32.raw ${output_path}/temp33.raw ${output_path}/temp34.raw ${output_path}/temp35.raw ${output_path}/temp36.raw ${output_path}/temp37.raw ${output_path}/temp38.raw ${output_path}/temp39.rawrm -rf ${output_path}/temp0.raw ${output_path}/temp1.raw ${output_path}/temp2.raw ${output_path}/temp3.raw ${output_path}/temp4.raw ${output_path}/temp5.raw ${output_path}/temp6.raw ${output_path}/temp7.raw ${output_path}/temp8.raw ${output_path}/temp9.raw ${output_path}/temp10.raw ${output_path}/temp11.raw ${output_path}/temp12.raw ${output_path}/temp13.raw ${output_path}/temp14.raw ${output_path}/temp15.raw ${output_path}/temp16.raw ${output_path}/temp17.raw ${output_path}/temp18.raw ${output_path}/temp19.raw ${output_path}/temp20.raw ${output_path}/temp21.raw ${output_path}/temp22.raw ${output_path}/temp23.raw ${output_path}/temp24.raw ${output_path}/temp25.raw ${output_path}/temp26.raw ${output_path}/temp27.raw ${output_path}/temp28.raw ${output_path}/temp29.raw ${output_path}/temp30.raw ${output_path}/temp31.raw ${output_path}/temp32.raw ${output_path}/temp33.raw ${output_path}/temp34.raw ${output_path}/temp35.raw ${output_path}/temp36.raw ${output_path}/temp37.raw ${output_path}/temp38.raw ${output_path}/temp39.rawecho "conversion finished"

而这些图片被打包后如何使用呢?在文件vendor/mediatek/proprietary/external/libshowlogo/cust_display.h中,会把图片序号定义为宏,在代码中经过这些宏来调用指定图片。

 
 
 
 
#ifndef __CUST_DISPLAY_H__#define __CUST_DISPLAY_H__/* change*/// color #00FF00 #ffffff#define BAR_OCCUPIED_COLOR (0xFF7ED321) // Green#define BAR_EMPTY_COLOR (0xFF000000) // White#define BAR_BG_COLOR (0xFF000000) // Black/* change*/// LOGO number#define ANIM_V0_LOGO_NUM 5 // version 0: show 4 recatangle growing animation without battery number#define ANIM_V1_LOGO_NUM 39 // version 1: show wave animation with battery number #define ANIM_V2_LOGO_NUM 86 // version 2: show wireless charging animation // Common LOGO index#define BOOT_LOGO_INDEX 0 #define KERNEL_LOGO_INDEX 38 #define ANIM_V0_BACKGROUND_INDEX 1 /* change*/#define SHOW_BO_POWER 34/* change*/#define ANIM_V1_BACKGROUND_INDEX 35#define LOW_BATTERY_INDEX 2 #define CHARGER_OV_INDEX 3 #define FULL_BATTERY_INDEX 37 // version 1: show wave animation with battery number // NUMBER LOGO INDEX#define NUMBER_PIC_START_0 4 #define NUMBER_PIC_PERCENT 14 // DYNAMIC ANIMATION LOGO INDEX#define BAT_ANIM_START_0 15 // LOW BATTERY(0~10%) ANIMATION LOGO#define LOW_BAT_ANIM_START_0 25 #define ANIM_LINE_INDEX 36 // version 2: show wireless charging animation logo index#define V2_NUM_START_0_INDEX 57 #define V2_NUM_PERCENT_INDEX 67 #define V2_BAT_0_10_START_INDEX 68 #define V2_BAT_10_40_START_INDEX 72 #define V2_BAT_40_80_START_INDEX 76 #define V2_BAT_80_100_START_NDEX 80#define V2_BAT_0_INDEX 84#define V2_BAT_100_INDEX 85// show fast charging animation logo index#define FAST_CHARGING_BAT_100_INDEX 39#define FAST_CHARGING_BAT_START_0_INDEX 40#define FAST_CHARGING_NUM_START_0_INDEX 46#define FAST_CHARGING_NUM_PERCENT_INDEX 56#if defined(FHD) || defined(CU_FHD) || defined(CMCC_FHD) || defined(CT_FHD) || defined(CMCC_LTE_FHD) || defined(CT_LTE_FHD) || defined(CU_LTE_FHD) // fhd 1080*1920 // battery capacity rectangle #define CAPACITY_LEFT (387) // battery capacity center #define CAPACITY_TOP (802) #define CAPACITY_RIGHT (691) #define CAPACITY_BOTTOM (1292) /* change*/ // first number rectangle #define NUMBER_LEFT (512) // number #define NUMBER_TOP (1097) #define NUMBER_RIGHT (540) #define NUMBER_BOTTOM (1137) /* change*/ // % rectangle #define PERCENT_LEFT (568) // percent number_left + 2*number_width #define PERCENT_TOP (1110) #define PERCENT_RIGHT (592) #define PERCENT_BOTTOM (1137) /* change*/ // top animation part #define TOP_ANIMATION_LEFT (387) // top animation #define TOP_ANIMATION_TOP (100) #define TOP_ANIMATION_RIGHT (691) #define TOP_ANIMATION_BOTTOM (152) /* change*/ // for old animation #define BAR_LEFT (463) #define BAR_TOP (760) #define BAR_RIGHT (619) #define BAR_BOTTOM (1049) /* change*/#elif defined(WQHD) || defined(CU_WQHD) || defined(CMCC_WQHD) || defined(CT_WQHD) || defined(CMCC_LTE_WQHD) || defined(CT_LTE_WQHD) || defined(CU_LTE_WQHD) // wqhd 1440*2560 // battery capacity rectangle #define CAPACITY_LEFT (556) // battery capacity center #define CAPACITY_TOP (1112) #define CAPACITY_RIGHT (882) #define CAPACITY_BOTTOM (1630) // first number rectangle #define NUMBER_LEFT (570) // number #define NUMBER_TOP (770) #define NUMBER_RIGHT (660) #define NUMBER_BOTTOM (898) // % rectangle #define PERCENT_LEFT (750) // percent number_left + 2*number_width #define PERCENT_TOP (770) #define PERCENT_RIGHT (864) #define PERCENT_BOTTOM (898) // top animation part #define TOP_ANIMATION_LEFT (556) // top animation #define TOP_ANIMATION_TOP (100) #define TOP_ANIMATION_RIGHT (882) #define TOP_ANIMATION_BOTTOM (158) // for old animation #define BAR_LEFT (443) #define BAR_TOP (337) #define BAR_RIGHT (574) #define BAR_BOTTOM (641)#elif defined(HD720) || defined(CU_HD720) || defined(CMCC_HD720) || defined(CT_HD720) || defined(CMCC_LTE_HD720) || defined(CT_LTE_HD720) || defined(CU_LTE_HD720) // hd720 720*1280 // battery capacity rectangle #define CAPACITY_LEFT (278) // battery capacity center #define CAPACITY_TOP (556) #define CAPACITY_RIGHT (441) #define CAPACITY_BOTTOM (817) // first number rectangle #define NUMBER_LEFT (290) // number #define NUMBER_TOP (386) #define NUMBER_RIGHT (335) #define NUMBER_BOTTOM (450) // % rectangle #define PERCENT_LEFT (380) // percent number_left + 2*number_width #define PERCENT_TOP (386) #define PERCENT_RIGHT (437) #define PERCENT_BOTTOM (450) // top animation part #define TOP_ANIMATION_LEFT (278) // top animation #define TOP_ANIMATION_TOP (100) #define TOP_ANIMATION_RIGHT (441) #define TOP_ANIMATION_BOTTOM (129) // for old animation #define BAR_LEFT (313) #define BAR_TOP (238) #define BAR_RIGHT (406) #define BAR_BOTTOM (453)

同时,在这个文件中还定义了各个图片在屏幕上的坐标位置,以fhd 1080*1920这个屏幕为例,手机屏幕左上角的坐标为(0,0)(是以一个像素为一个单位来计的)右下角的坐标为(1080,1920)。

  • battery capacity rectangle –表示电池电量图像的坐标,针对verion 1.
  • first number rectangle – 表示电池电量值十位数上数字的坐标,针对verion 1.
  • % rectangle – 表示电池电量值百分号的坐标,针对verion 1.
  • top animation part – 表示电池充电时波浪状动画的坐标,针对verion 1.
  • for old animation – 表示电池电量图像的坐标,针对verion 0.
    若是想修改各个图片在屏幕上的位置,只须要调整对应坐标便可。
 
 
 
 
#if defined(FHD) || defined(CU_FHD) || defined(CMCC_FHD) || defined(CT_FHD) || defined(CMCC_LTE_FHD) || defined(CT_LTE_FHD) || defined(CU_LTE_FHD) // fhd 1080*1920 // battery capacity rectangle #define CAPACITY_LEFT (387) // battery capacity center #define CAPACITY_TOP (802) #define CAPACITY_RIGHT (691) #define CAPACITY_BOTTOM (1292) // first number rectangle #define NUMBER_LEFT (512) // number #define NUMBER_TOP (1097) #define NUMBER_RIGHT (540) #define NUMBER_BOTTOM (1137) // % rectangle #define PERCENT_LEFT (568) // percent number_left + 2*number_width #define PERCENT_TOP (1110) #define PERCENT_RIGHT (592) #define PERCENT_BOTTOM (1137) // top animation part #define TOP_ANIMATION_LEFT (387) // top animation #define TOP_ANIMATION_TOP (100) #define TOP_ANIMATION_RIGHT (691) #define TOP_ANIMATION_BOTTOM (152) // for old animation #define BAR_LEFT (463) #define BAR_TOP (760) #define BAR_RIGHT (619) #define BAR_BOTTOM (1049)

6.6 fill_animation_battery_new()与fill_animation_battery_old

接下来分别查看fill_animation_battery_new()与fill_animation_battery_old这2个函数的具体逻辑。

  • 首先,是fill_animation_battery_new函数,正如前面所说,该函数的动画效果是显示波浪状充电效果和电池电量白百分比(version 1: show wave animation with battery number)。
    在该方法中分别设定0~10%、10~90%、90~100%、100%等4个电量显示效果。
    0~10%为低电量效果:显示的大概是图片[fhd_bat_10_01.bmp~ fhd_bat_10_01.bmp]共10张轮流播放效果。
    10~90%为正常充电效果:显示由图片[fhd_bat_bg.bmp] 为背景,图片[fhd_bat_img.bmp]填充实际电量,图片[fhd_bat_animation_01.bmp~ fhd_bat_animation_10.bmp] 共10张显示动画效果3部分组成。
    90~100%正常充电效果:显示由图片[fhd_bat_bg.bmp] 为背景,图片[fhd_bat_img.bmp]填充实际电量,无动画效果,由前面2部分组成。
    100%电量效果:由图[fhd_bat_100.bmp] 共1张表示。
 
 
 
 
/*change*//* * 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 (capacity >= 100) { //show_logo(37); // battery 100 fill_animation_logo(FULL_BATTERY_INDEX, fill_addr, dec_logo_addr, logo_addr,phical_screen); } else if (capacity < 10) { if (MTK_LOG_ENABLE == 1) { SLOGD("[show_animation_common: %s %d]charging_low_index = %d\n",__FUNCTION__,__LINE__, charging_low_index); } //经过charging_low_index++来循环显示低电量的10张图片 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 { unsigned int capacity_grids = 0; //static RECT_REGION_T battery_rect = {CAPACITY_LEFT,CAPACITY_TOP,CAPACITY_RIGHT,CAPACITY_BOTTOM}; /*把电池分红100等分,而后计算当前电量所占比重(由于背景图片已近画了10%电量,因此这里有capacity - 10这个操做)*/ capacity_grids = CAPACITY_BOTTOM - (CAPACITY_BOTTOM - CAPACITY_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); } //background,即充电时的背景图片fhd_bat_bg.bmp,在该图中已经画出了10%电量 fill_animation_logo(ANIM_V1_BACKGROUND_INDEX, fill_addr, dec_logo_addr, logo_addr,phical_screen); //画出当前电池对应的电量 fill_animation_line(ANIM_LINE_INDEX, capacity_grids, fill_addr, logo_addr, phical_screen); 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); //若是电量小于90%,加上充电动画效果 if (capacity <= 90) { RECT_REGION_T top_animation_rect = {TOP_ANIMATION_LEFT, capacity_grids - (TOP_ANIMATION_BOTTOM - TOP_ANIMATION_TOP), TOP_ANIMATION_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_battery_old函数,该函数的动画是4格滚动的动画效果(version 0: show 4 recatangle growing animation without battery number),在该动画中使用图片fhd_battery.bmp充当背景图片,而后其余的4格电量都是经过函数fill_animation_prog_bar动态画出来的,fill_animation_battery_old函数具体实现以下。
 
 
 
 
/* * * Show old charging animation * */void fill_animation_battery_old(int capacity, void *fill_addr, void * dec_logo_addr, void * logo_addr, LCM_SCREEN_T phical_screen){ int capacity_grids = 0; if (capacity > 100) capacity = 100; //这里表示计算当前电量占的比重,字段ANIM_V0_REGIONS表示把电池划分红几个格的电量 capacity_grids = (capacity * (ANIM_V0_REGIONS)) / 100; if (version0_charging_index < capacity_grids * 2) version0_charging_index = capacity_grids * 2; if (capacity < 100){ version0_charging_index > 7? version0_charging_index = capacity_grids * 2 : version0_charging_index++; } else { version0_charging_index = ANIM_V0_REGIONS * 2; } //此处为显示背景图片fhd_battery.bmp的函数 fill_animation_logo(ANIM_V0_BACKGROUND_INDEX, fill_addr, dec_logo_addr, logo_addr,phical_screen); RECT_REGION_T rect_bar = {bar_rect.left + 1, bar_rect.top + 1, bar_rect.right, bar_rect.bottom}; //此处动态画出第0格到version0_charging_index/2格的电量 fill_animation_prog_bar(rect_bar, (unsigned int)(BAR_OCCUPIED_COLOR), 0, version0_charging_index/2, fill_addr, phical_screen); /*此处动态画出第version0_charging_index/2格到ANIM_V0_REGIONS - version0_charging_index/2格的电量,与前面的函数交替使用就会出现4格电量滚动的效果(固然还须要在draw_thread_routine中不断while循环)*/ fill_animation_prog_bar(rect_bar, (unsigned int)(BAR_EMPTY_COLOR), version0_charging_index/2, ANIM_V0_REGIONS - version0_charging_index/2, fill_addr, phical_screen);}

接下老看看函数fill_animation_prog_bar的具体实现。

 
 
 
 
/* * Fill a rectangle size address with special color * */void fill_animation_prog_bar(RECT_REGION_T rect_bar, unsigned int fgColor, unsigned int start_div, unsigned int occupied_div, void *fill_addr, LCM_SCREEN_T phical_screen){ //计算每个格电量占多少像素 unsigned int div_size = (rect_bar.bottom - rect_bar.top) / (ANIM_V0_REGIONS); /*这是计算每格电量实际须要画多少像素的图像,字段ANIM_V0_SPACE_AFTER_REGION为各个电量格之间的空隙,若是为0则表示电量格之间无空隙*/ unsigned int draw_size = div_size - (ANIM_V0_SPACE_AFTER_REGION); unsigned int i; for (i = start_div; i < start_div + occupied_div; ++ i) { unsigned int draw_bottom = rect_bar.bottom - div_size * i - (ANIM_V0_SPACE_AFTER_REGION); unsigned int draw_top = draw_bottom - draw_size; RECT_REGION_T rect = {rect_bar.left, draw_top, rect_bar.right, draw_bottom}; //这是函数才是真正进行电量格绘画的 fill_rect_with_color(fill_addr, rect, fgColor, phical_screen); }}

7. 函数 key_control(pwrkeys, ARRAY_SIZE(pwrkeys));

这个函数从名字上看该是对按键进行控制的函数,推测该是检测power键是否被按下的,字段longPressDuration = 500;该是设定须要长按power的时间,函数long_press_control();会开启一个线程进行检测,当长按power达到指定时间,就会退出关机充电的线程而后设定bootingUp = true;估计会经过设定的bootingUp值来进行手机的重启操做,下面是key_control函数的具体实现。

 
 
 
 
void key_control(int * pwrkeys, int pwrkeys_num){ int res,i,j,k; int pollres; const char *device = NULL; struct input_event event; longPressDuration = 500; long_press_control(); num_fds = 1; ufds = (struct pollfd*)calloc(1, sizeof(ufds[0])); ufds[0].fd = inotify_init(); ufds[0].events = POLLIN; wd = inotify_add_watch(ufds[0].fd, INPUT_DEVICE_PATH, IN_DELETE | IN_CREATE); if(wd < 0) { KPOC_LOGI("could not add watch for %s, %s\n", INPUT_DEVICE_PATH, strerror(errno)); exit_charger(EXIT_ERROR_SHUTDOWN); } res = scan_dir(INPUT_DEVICE_PATH); if(res < 0) { KPOC_LOGI("scan dir failed for %s\n", INPUT_DEVICE_PATH); exit_charger(EXIT_ERROR_SHUTDOWN); } while(1) { pollres = poll(ufds, num_fds, -1); if(ufds[0].revents & POLLIN) { read_notify(INPUT_DEVICE_PATH, ufds[0].fd); } for(i = 1; i < num_fds; i++) { if(ufds[i].revents) { if(ufds[i].revents & POLLIN) { res = read(ufds[i].fd, &event, sizeof(event)); if(res < (int)sizeof(event)) { KPOC_LOGI("could not get event\n"); exit_charger(EXIT_ERROR_SHUTDOWN); }#ifdef VERBOSE_OUTPUT KPOC_LOGI("%s: event.type:%d,%d:%d\n", __FUNCTION__, event.type, event.code, event.value);#endif if (EV_KEY == event.type) { for (k=0; k<pwrkeys_num; k++) { if(event.code == pwrkeys[k]) { if (1 == event.value) { powerKeyPressed = true; pthread_cond_signal(&keycond); } else powerKeyPressed = false; break; } } } } } } }}

而后看看函数long_press_control(),在该函数中先对开启线程所需各类资源进行初始化,而后开启线程,线程开启后并不表示就进行重启操做了,它还要等待其余条件也知足才会重启,long_press_control函数的具体实现以下所示。

 
 
 
 
void long_press_control(){ int ret = 0; pthread_attr_t attr; pthread_t pwrkey_thread; pthread_mutex_init(&mutex, NULL); pthread_cond_init(&keycond, NULL); pthread_attr_init(&attr); ret = pthread_create(&pwrkey_thread, &attr, key_thread_routine, NULL); if (ret != 0) { KPOC_LOGI("create key pthread failed.\n"); exit_charger(EXIT_ERROR_SHUTDOWN); }}

线程中的具体操做以下,先要判断powerKey是否被按下,而对powerKey是否被按下操做的检测是在函数key_control中实现的,当powerKey被按下则powerKeyPressed = true,在线程的实现函数中能够看到有2个while循环,最外层的while应该是循环等待powerKey被按下,达到要求会进入内层while进行计时等待的循环。

 
 
 
 
static void* key_thread_routine(void *arg){ static bool bootingUp = false; static bool long_press = false; struct timeval start; while(1) { pthread_mutex_lock(&mutex); pthread_cond_wait(&keycond, &mutex); /* longPressDetecting = true; */ gettimeofday(&start, NULL); KPOC_LOGI("pwr key long press check start\n"); while(powerKeyPressed) { usleep(1000*100); //200ms long_press = time_exceed(start, longPressDuration); if(long_press) { KPOC_LOGI("pwr key reaches boot condition\n"); if(get_voltage() > VBAT_POWER_ON) { showLowBattLogo = 0; // ready to boot up. inotify_rm_watch(ufds[0].fd, wd); if (keyDownPressed || keyUpPressed) exit_charger(EXIT_REBOOT_UBOOT); else exit_charger(EXIT_POWER_UP); bootingUp = true; } else { showLowBattLogo = 1; KPOC_LOGI("VBAT <= %d\n", VBAT_POWER_ON); break; } } } if (!long_press) showLowBattLogo = 0; if(!bootingUp) start_charging_anim(TRIGGER_ANIM_KEY); KPOC_LOGI("pwr key long press check end\n"); pthread_mutex_unlock(&mutex); } return NULL;}

8. solution

进过上面的分析(固然不少都是猜想,分析也比较水),就开始动手改代码,但愿可以实现指望的效果。

8.1 图片替换

总共修改/增长共16张图片:

  • 数字图片0~9 须要替换成新风格的数字图片 共10张,直接替换
  • 百分号图片,须要替换成新风格的百分号图片 共1张,直接替换
  • 充电背景图片 须要替换成新风格的图片 共1张,直接替换
  • 低电量图片 须要替换成新风格的图片 共1张,直接替换
  • 低电压、高电压图片 须要替换成新风格的图片 共2张,直接替换
  • 无电量图片(这是新加的,要求电量小于等于0时显示) 1张,添加
    被替换图片的位置必定要找对,否则就坑壁了,到时候效果出不来

8.2 修改vendor/mediatek/proprietary/external/charger/bootlogo.cpp文件

由于在显示充电动画以前,还须要先显示一张低电量图片,时长1秒钟。原本在插入充电器后,在启动lk/kernel会显示一个logo,原本想直接该这个logo的。可是发现从这个logo显示到开始播放充电动画之间间隔5~6秒钟,这固然不行,因此在开始播放充电动画前面加了个显示低电量图片时长1秒钟的逻辑,也不知道这样搞会不会被叼。先无论,改了看看效果再说,具体修改以下。

 
 
 
 
/* * Show charging animation with battery capacity * */void bootlogo_show_charging(int capacity, int cnt){ KPOC_LOGI("[ChargingAnimation: %s %d]%d, %d",__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; }/*change*///字段show_low_battery_one_time在前面还须要定义下,否则编译报错 if(show_low_battery_one_time) { //delay 1000ms show_low_battery(); usleep(1000*1000); show_low_battery_one_time=0; }/*change*/ show_battery_capacity(capacity);}

8.3 修改vendor/jrdcom/build/common/update_logo.sh文件

这个文件就是对图片进行打包成raw文件的脚本,由于前面添加一张无电量图片,因此也要在这个文件中添加,否则只在logo目录中添加是没用的,修改以下。

 
 
 
 
${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp29.raw ${logo_path}/$p/"${boot_logo}_bat_10_05".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp30.raw ${logo_path}/$p/"${boot_logo}_bat_10_06".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp31.raw ${logo_path}/$p/"${boot_logo}_bat_10_07".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp32.raw ${logo_path}/$p/"${boot_logo}_bat_10_08".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp33.raw ${logo_path}/$p/"${boot_logo}_bat_10_09".bmp#change 直接在原来低电量图片上改的,反正低电量效果不须要了${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp34.raw ${logo_path}/$p/"${boot_logo}_no_power".bmp#change${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp35.raw ${logo_path}/$p/"${boot_logo}_bat_bg".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp36.raw ${logo_path}/$p/"${boot_logo}_bat_img".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp37.raw ${logo_path}/$p/"${boot_logo}_bat_100".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp38.raw ${logo_path}/$p/"${boot_logo}_kernel".bmp

8.4 修改vendor/mediatek/proprietary/external/libshowlogo/cust_display.h文件

修改这个文件主要是调整新充电样式中电池电量、电量值、百分号的位置(坑爹的UE不给具体坐标,就说按设计文档上搞,卧槽真是被狗咬了一口的感受,文档上根本不是写的很清楚,坐标也是用GD表示的,没办法只能慢慢调了),电池电量的颜色还有就是添加无电量图片的宏定义,具体修改以下。

 
 
 
 
/*change*/// color #00FF00 #ffffff#define BAR_OCCUPIED_COLOR (0xFF7ED321) // Green#define BAR_EMPTY_COLOR (0xFF000000) // Black#define BAR_BG_COLOR (0xFF000000) // Black#define SHOW_NO_POWER 34 //这个是无电量图片对应的序号// first number rectangle #define NUMBER_LEFT (512) // number #define NUMBER_TOP (1097) #define NUMBER_RIGHT (540) #define NUMBER_BOTTOM (1137) // % rectangle #define PERCENT_LEFT (568) // percent number_left + 2*number_width #define PERCENT_TOP (1110) #define PERCENT_RIGHT (592) #define PERCENT_BOTTOM (1137) // top animation part #define TOP_ANIMATION_LEFT (387) // top animation #define TOP_ANIMATION_TOP (100) #define TOP_ANIMATION_RIGHT (691) #define TOP_ANIMATION_BOTTOM (152) // for old animation #define BAR_LEFT (465) #define BAR_TOP (773) #define BAR_RIGHT (616) #define BAR_BOTTOM (1048)/*change*/

8.5 修改vendor/mediatek/proprietary/external/libshowlogo/show_animation_common.h文件

修改这个文件主要是调整电池电量的格数,原来是4个格,并且每一个格之间有间隙,须要弄成5个格,每一个格之间无间隙,只须要修改2个宏,具体修改以下。

 
 
 
 
/*change*/// version_0 animation#define ANIM_V0_REGIONS 5#define ANIM_V0_SPACE_AFTER_REGION 0/*change*/

8.6 修改vendor/mediatek/proprietary/external/libshowlogo/show_animation_common.c文件

这个文件主要修改函数void fill_animation_battery_old,由于这个函数的功能就是实现4格滚动效果,因此直接在它上面改。

  • 本来没有显示电池电量值,因此须要添加
  • 须要设置90%后无动画
  • 须要设置电量小于等于0显示SHOW_NO_POWER图片

具体的修改以下所示。

 
 
 
 
/* * Show old charging animation * */void fill_animation_battery_old(int capacity, void *fill_addr, void * dec_logo_addr, void * logo_addr, LCM_SCREEN_T phical_screen){ int capacity_grids = 0; if (capacity > 100) capacity = 100; capacity_grids = (capacity * (ANIM_V0_REGIONS)) / 100;/*change*/ if (version0_charging_index < capacity_grids * 2) version0_charging_index = capacity_grids * 2; if (capacity < 100){ if(capacity < 90){ version0_charging_index > 9? version0_charging_index = capacity_grids * 2 : version0_charging_index++; }else{ version0_charging_index > 7? version0_charging_index = capacity_grids * 2 : version0_charging_index++; } } else { version0_charging_index = ANIM_V0_REGIONS * 2; } if(capacity>0) { fill_animation_logo(ANIM_V0_BACKGROUND_INDEX, fill_addr, dec_logo_addr, logo_addr,phical_screen); if (capacity < 10) { 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); }else{ if(capacity >=100){ fill_animation_number(NUMBER_PIC_START_0 + ((capacity%100)/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_number(NUMBER_PIC_START_0 + (capacity/100), -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); }else{ 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); } } RECT_REGION_T rect_bar = {bar_rect.left + 1, bar_rect.top + 1, bar_rect.right, bar_rect.bottom}; fill_animation_prog_bar(rect_bar, (unsigned int)(BAR_OCCUPIED_COLOR), 0, version0_charging_index/2, fill_addr, phical_screen); fill_animation_prog_bar(rect_bar, (unsigned int)(BAR_EMPTY_COLOR), version0_charging_index/2, ANIM_V0_REGIONS - version0_charging_index/2, fill_addr, phical_screen); }else{ fill_animation_logo(SHOW_NO_POWER, fill_addr, dec_logo_addr, logo_addr,phical_screen); }}/*change*/

改完后编译发现是能够达到需求上面的要求(固然不是一下就编成功了的,都编了n次,并且每次编译都要费很长的时间,看来作事要细心,否则错了或者漏改了都会报错),这样也算马马虎虎完成任务吧,最后就看设计的人是否以为达到她指望效果,否则估计还要坑壁的继续改。

9. 总结

最开始作这个还真的不知道怎么入手,而后是各类找资料,固然网上也会有一些参考的例子,不过看了后也仍是不是很是懂,主要是不理解关机充电在什么阶段开始的。而且对lk、kernel这些流程不是很是熟悉,只能慢慢尝试在图片上作标记,改不一样的坐标来看编译出来是什么效果。最开始找到的就是fill_animation_battery_new这个函数,只知道是它实现的充电动画效果,还想就在这个函数上面改为5格滚动的动画效果。后面看到关机充电动画实现四格滚动动画问题分析才知道原来原版系统原本就有这个滚动的动画效果实现(要是对相关代码有个全局观估计就不会这么狼狈),只要在它上修改其实就方便多了。同时,只要知道关机充电这个功能就是一个应用而已,它是由第一个进程init开启的,而后从这应用的入口函数vendor/mediatek/proprietary/external/charger/main.cpp中的main开始追,整个充电逻辑就会比较清楚了。
以上是我的对mtk关机充电部分的理解,应该会有一些错误和遗漏,欢迎批评指正!



相关文章
相关标签/搜索